[PATCH v2] lib: Export the parsing functions and related data structures of the PLDM library

From: Shawn.Shao
Date: Mon Sep 09 2024 - 03:17:46 EST


From: Shawn Shao <shawn.shao@xxxxxxxxxxxxxxx>

v1 -> v2: Updated the commit message, added a description
of the changes related to `DeviceUpdateOptionFlags`, etc.

The PLDM library is used to implement firmware upgrades,
but the current library functions only support the
`pldmfw_flash_image` function to complete a fixed
process of parsing, sending data to the backend,
and flashing (allowing users to implement custom
logic using `pldmfw_ops`). However, this poses
significant challenges for device vendors using
PLDM for firmware upgrades.
The following scenarios are not supported:
1. Only using the PLDM parsing functions, as the
current library does not support this operation.
2. The firmware upgrade process differs from this
fixed flow (the firmware upgrade process may
vary across different vendors).
|-> pldmfw_flash_image
|-> pldm_parse_image
|-> pldm_parse_header
|-> pldm_parse_records
|-> pldm_parse_components
-> pldm_verify_header_crc
|-> pldm_find_matching_record (xxx_match_record)
|-> pldm_send_package_data (xxx_send_package_data)
|-> pldm_send_component_tables (xxx_send_package_data)
|-> pldm_flash_components (xxx_flash_component)
|-> pldm_finalize_update (xxx_finalize_update)
3. The current PLDM library does not support parsing the
DeviceUpdateOptionFlags parameter, which is defined in the PLDM
specification to facilitate the transfer of control information
between the UA (Update Agent) and the firmware.Please refer to:
https://www.dmtf.org/sites/default/files/standards/documents
/DSP0267_1.3.0.pdf P37.

Signed-off-by: Shawn Shao <shawn.shao@xxxxxxxxxxxxxxx>
---
include/linux/pldmfw.h | 38 +++++++++++++++++++++++++++++++++++++
lib/pldmfw/pldmfw.c | 43 +++++-------------------------------------
2 files changed, 43 insertions(+), 38 deletions(-)

diff --git a/include/linux/pldmfw.h b/include/linux/pldmfw.h
index 0fc831338226..5058a07a5ea4 100644
--- a/include/linux/pldmfw.h
+++ b/include/linux/pldmfw.h
@@ -130,6 +130,42 @@ struct pldmfw {
struct device *dev;
};

+/* pldmfw_priv structure used to store details about the PLDM image file as it is
+ * being validated and processed.
+ */
+struct pldmfw_priv {
+ struct pldmfw *context;
+ const struct firmware *fw;
+
+ /* current offset of firmware image */
+ size_t offset;
+
+ struct list_head records;
+ struct list_head components;
+
+ /* PLDM Firmware Package Header */
+ const struct __pldm_header *header;
+ u16 total_header_size;
+
+ /* length of the component bitmap */
+ u16 component_bitmap_len;
+ u16 bitmap_size;
+
+ /* Start of the component image information */
+ u16 component_count;
+ const u8 *component_start;
+
+ /* Start pf the firmware device id records */
+ const u8 *record_start;
+ u8 record_count;
+
+ /* The CRC at the end of the package header */
+ u32 header_crc;
+
+ struct pldmfw_record *matching_record;
+};
+
+
bool pldmfw_op_pci_match_record(struct pldmfw *context, struct pldmfw_record *record);

/* Operations invoked by the generic PLDM firmware update engine. Used to
@@ -160,6 +196,8 @@ struct pldmfw_ops {
int (*finalize_update)(struct pldmfw *context);
};

+int pldm_parse_image(struct pldmfw_priv *data);
+void pldmfw_free_priv(struct pldmfw_priv *data);
int pldmfw_flash_image(struct pldmfw *context, const struct firmware *fw);

#endif
diff --git a/lib/pldmfw/pldmfw.c b/lib/pldmfw/pldmfw.c
index 54e1809a38fd..cd1698e9c340 100644
--- a/lib/pldmfw/pldmfw.c
+++ b/lib/pldmfw/pldmfw.c
@@ -14,41 +14,6 @@

#include "pldmfw_private.h"

-/* Internal structure used to store details about the PLDM image file as it is
- * being validated and processed.
- */
-struct pldmfw_priv {
- struct pldmfw *context;
- const struct firmware *fw;
-
- /* current offset of firmware image */
- size_t offset;
-
- struct list_head records;
- struct list_head components;
-
- /* PLDM Firmware Package Header */
- const struct __pldm_header *header;
- u16 total_header_size;
-
- /* length of the component bitmap */
- u16 component_bitmap_len;
- u16 bitmap_size;
-
- /* Start of the component image information */
- u16 component_count;
- const u8 *component_start;
-
- /* Start pf the firmware device id records */
- const u8 *record_start;
- u8 record_count;
-
- /* The CRC at the end of the package header */
- u32 header_crc;
-
- struct pldmfw_record *matching_record;
-};
-
/**
* pldm_check_fw_space - Verify that the firmware image has space left
* @data: pointer to private data
@@ -341,6 +306,7 @@ pldm_parse_one_record(struct pldmfw_priv *data,
return err;

record_len = get_unaligned_le16(&__record->record_len);
+ record->device_update_flags = get_unaligned_le32(&__record->device_update_flags);
record->package_data_len = get_unaligned_le16(&__record->package_data_len);
record->version_len = __record->version_len;
record->version_type = __record->version_type;
@@ -540,7 +506,7 @@ static int pldm_verify_header_crc(struct pldmfw_priv *data)
* Loops through and clears all allocated memory associated with each
* allocated descriptor, record, and component.
*/
-static void pldmfw_free_priv(struct pldmfw_priv *data)
+void pldmfw_free_priv(struct pldmfw_priv *data)
{
struct pldmfw_component *component, *c_safe;
struct pldmfw_record *record, *r_safe;
@@ -566,7 +532,7 @@ static void pldmfw_free_priv(struct pldmfw_priv *data)
kfree(record);
}
}
-
+EXPORT_SYMBOL(pldmfw_free_priv);
/**
* pldm_parse_image - parse and extract details from PLDM image
* @data: pointer to private data
@@ -581,7 +547,7 @@ static void pldmfw_free_priv(struct pldmfw_priv *data)
*
* Returns: zero on success, or a negative error code on failure.
*/
-static int pldm_parse_image(struct pldmfw_priv *data)
+int pldm_parse_image(struct pldmfw_priv *data)
{
int err;

@@ -602,6 +568,7 @@ static int pldm_parse_image(struct pldmfw_priv *data)

return pldm_verify_header_crc(data);
}
+EXPORT_SYMBOL(pldm_parse_image);

/* these are u32 so that we can store PCI_ANY_ID */
struct pldm_pci_record_id {
--
2.34.1