libpldm: Add decode API for ComponentParameterTable entry
ComponentParameterTable is present in the response of
GetFirmwareParameters command. ComponentParameterTable is a table that
contains component entries for all of the updateable components which
reside on the firmware device.
decode_get_firmware_parameters_resp_comp_entry decodes each entry in
the ComponentParameterTable.
Tested: Unit tests passed
Signed-off-by: gokulsanker <gokul.sanker.v.g@intel.com>
Change-Id: I3698b268cf42345d80d7d218919d42ffad0b011f
diff --git a/libpldm/firmware_update.c b/libpldm/firmware_update.c
index b0daddb..58dd21f 100644
--- a/libpldm/firmware_update.c
+++ b/libpldm/firmware_update.c
@@ -1,5 +1,6 @@
#include "firmware_update.h"
#include <endian.h>
+#include <string.h>
int encode_query_device_identifiers_req(uint8_t instance_id,
size_t payload_length,
@@ -154,3 +155,77 @@
return PLDM_SUCCESS;
}
+
+int decode_get_firmware_parameters_resp_comp_entry(
+ const uint8_t *data, size_t length,
+ struct pldm_component_parameter_entry *component_data,
+ struct variable_field *active_comp_ver_str,
+ struct variable_field *pending_comp_ver_str)
+{
+ if (data == NULL || component_data == NULL ||
+ active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if (length < sizeof(struct pldm_component_parameter_entry)) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ struct pldm_component_parameter_entry *entry =
+ (struct pldm_component_parameter_entry *)(data);
+ if (entry->active_comp_ver_str_len == 0) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
+ entry->active_comp_ver_str_len +
+ entry->pending_comp_ver_str_len;
+
+ if (length != entry_length) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ component_data->comp_classification =
+ le16toh(entry->comp_classification);
+ component_data->comp_identifier = le16toh(entry->comp_identifier);
+ component_data->comp_classification_index =
+ entry->comp_classification_index;
+ component_data->active_comp_comparison_stamp =
+ le32toh(entry->active_comp_comparison_stamp);
+ component_data->active_comp_ver_str_type =
+ entry->active_comp_ver_str_type;
+ component_data->active_comp_ver_str_len =
+ entry->active_comp_ver_str_len;
+ memcpy(component_data->active_comp_release_date,
+ entry->active_comp_release_date,
+ sizeof(entry->active_comp_release_date));
+ component_data->pending_comp_comparison_stamp =
+ le32toh(entry->pending_comp_comparison_stamp);
+ component_data->pending_comp_ver_str_type =
+ entry->pending_comp_ver_str_type;
+ component_data->pending_comp_ver_str_len =
+ entry->pending_comp_ver_str_len;
+ memcpy(component_data->pending_comp_release_date,
+ entry->pending_comp_release_date,
+ sizeof(entry->pending_comp_release_date));
+ component_data->comp_activation_methods.value =
+ le16toh(entry->comp_activation_methods.value);
+ component_data->capabilities_during_update.value =
+ le32toh(entry->capabilities_during_update.value);
+
+ active_comp_ver_str->ptr =
+ data + sizeof(struct pldm_component_parameter_entry);
+ active_comp_ver_str->length = entry->active_comp_ver_str_len;
+
+ if (entry->pending_comp_ver_str_len != 0) {
+
+ pending_comp_ver_str->ptr =
+ data + sizeof(struct pldm_component_parameter_entry) +
+ entry->active_comp_ver_str_len;
+ pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
+ } else {
+ pending_comp_ver_str->ptr = NULL;
+ pending_comp_ver_str->length = 0;
+ }
+ return PLDM_SUCCESS;
+}
diff --git a/libpldm/firmware_update.h b/libpldm/firmware_update.h
index dc6d7d6..1c3e21b 100644
--- a/libpldm/firmware_update.h
+++ b/libpldm/firmware_update.h
@@ -45,6 +45,26 @@
uint8_t pending_comp_image_set_ver_str_len;
} __attribute__((packed));
+/** @struct pldm_component_parameter_entry
+ *
+ * Structure representing component parameter table entry.
+ */
+struct pldm_component_parameter_entry {
+ uint16_t comp_classification;
+ uint16_t comp_identifier;
+ uint8_t comp_classification_index;
+ uint32_t active_comp_comparison_stamp;
+ uint8_t active_comp_ver_str_type;
+ uint8_t active_comp_ver_str_len;
+ uint8_t active_comp_release_date[8];
+ uint32_t pending_comp_comparison_stamp;
+ uint8_t pending_comp_ver_str_type;
+ uint8_t pending_comp_ver_str_len;
+ uint8_t pending_comp_release_date[8];
+ bitfield16_t comp_activation_methods;
+ bitfield32_t capabilities_during_update;
+} __attribute__((packed));
+
/** @brief Create a PLDM request message for QueryDeviceIdentifiers
*
* @param[in] instance_id - Message's instance id
@@ -112,6 +132,24 @@
struct variable_field *active_comp_image_set_ver_str,
struct variable_field *pending_comp_image_set_ver_str);
+/** @brief Decode component entries in the component parameter table which is
+ * part of the response of GetFirmwareParameters command
+ *
+ * @param[in] data - Component entry
+ * @param[in] length - Length of component entry
+ * @param[out] component_data - Pointer to component parameter table
+ * @param[out] active_comp_ver_str - Pointer to active component version string
+ * @param[out] pending_comp_ver_str - Pointer to pending component version
+ * string
+ *
+ * @return pldm_completion_codes
+ */
+int decode_get_firmware_parameters_resp_comp_entry(
+ const uint8_t *data, size_t length,
+ struct pldm_component_parameter_entry *component_data,
+ struct variable_field *active_comp_ver_str,
+ struct variable_field *pending_comp_ver_str);
+
#ifdef __cplusplus
}
#endif
diff --git a/libpldm/pldm_types.h b/libpldm/pldm_types.h
index ee823a5..5e7e068 100644
--- a/libpldm/pldm_types.h
+++ b/libpldm/pldm_types.h
@@ -31,6 +31,28 @@
typedef uint8_t bool8_t;
typedef union {
+ uint16_t value;
+ struct {
+ uint8_t bit0 : 1;
+ uint8_t bit1 : 1;
+ uint8_t bit2 : 1;
+ uint8_t bit3 : 1;
+ uint8_t bit4 : 1;
+ uint8_t bit5 : 1;
+ uint8_t bit6 : 1;
+ uint8_t bit7 : 1;
+ uint8_t bit8 : 1;
+ uint8_t bit9 : 1;
+ uint8_t bit10 : 1;
+ uint8_t bit11 : 1;
+ uint8_t bit12 : 1;
+ uint8_t bit13 : 1;
+ uint8_t bit14 : 1;
+ uint8_t bit15 : 1;
+ } __attribute__((packed)) bits;
+} bitfield16_t;
+
+typedef union {
uint32_t value;
struct {
uint8_t bit0 : 1;
diff --git a/libpldm/tests/libpldm_firmware_update_test.cpp b/libpldm/tests/libpldm_firmware_update_test.cpp
index b02e8ca..3e35cf6 100644
--- a/libpldm/tests/libpldm_firmware_update_test.cpp
+++ b/libpldm/tests/libpldm_firmware_update_test.cpp
@@ -146,3 +146,94 @@
response.data() + pendingCompImageSetVerStrPos,
outPendingCompImageSetVerStr.length));
}
+
+TEST(GetFirmwareParameters, goodPathDecodeComponentParameterEntry)
+{
+ // Random value for component classification
+ constexpr uint16_t compClassification = 0x0A0B;
+ // Random value for component classification
+ constexpr uint16_t compIdentifier = 0x0C0D;
+ // Random value for component classification
+ constexpr uint32_t timestamp = 0X12345678;
+ // Random value for component activation methods
+ constexpr uint16_t compActivationMethods = 0xBBDD;
+ // Random value for capabilities during update
+ constexpr uint32_t capabilitiesDuringUpdate = 0xBADBEEFE;
+
+ // ActiveCompImageSetVerStrLen is not fixed here taking it as 8
+ constexpr uint8_t activeCompVerStrLen = 8;
+ // PendingCompImageSetVerStrLen is not fixed here taking it as 8
+ constexpr uint8_t pendingCompVerStrLen = 8;
+ constexpr size_t entryLength =
+ sizeof(struct pldm_component_parameter_entry) + activeCompVerStrLen +
+ pendingCompVerStrLen;
+ std::array<uint8_t, entryLength> entry{};
+
+ auto inEntry =
+ reinterpret_cast<struct pldm_component_parameter_entry*>(entry.data());
+
+ inEntry->comp_classification = htole16(compClassification);
+ inEntry->comp_identifier = htole16(compIdentifier);
+ inEntry->comp_classification_index = 0x0F;
+ inEntry->active_comp_comparison_stamp = htole32(timestamp);
+ inEntry->active_comp_ver_str_type = 1;
+ inEntry->active_comp_ver_str_len = activeCompVerStrLen;
+ std::fill_n(inEntry->active_comp_release_date,
+ sizeof(inEntry->active_comp_release_date), 0xFF);
+ inEntry->pending_comp_comparison_stamp = htole32(timestamp);
+ inEntry->pending_comp_ver_str_type = 1;
+ inEntry->pending_comp_ver_str_len = pendingCompVerStrLen;
+ std::fill_n(inEntry->pending_comp_release_date,
+ sizeof(inEntry->pending_comp_release_date), 0xFF);
+ inEntry->comp_activation_methods.value = htole16(compActivationMethods);
+ inEntry->capabilities_during_update.value =
+ htole32(capabilitiesDuringUpdate);
+ constexpr auto activeCompVerStrPos =
+ sizeof(struct pldm_component_parameter_entry);
+ std::fill_n(entry.data() + activeCompVerStrPos, activeCompVerStrLen, 0xAA);
+ constexpr auto pendingCompVerStrPos =
+ activeCompVerStrPos + activeCompVerStrLen;
+ std::fill_n(entry.data() + pendingCompVerStrPos, pendingCompVerStrLen,
+ 0xBB);
+
+ struct pldm_component_parameter_entry outEntry;
+ struct variable_field outActiveCompVerStr;
+ struct variable_field outPendingCompVerStr;
+
+ auto rc = decode_get_firmware_parameters_resp_comp_entry(
+ entry.data(), entryLength, &outEntry, &outActiveCompVerStr,
+ &outPendingCompVerStr);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ EXPECT_EQ(outEntry.comp_classification, compClassification);
+ EXPECT_EQ(outEntry.comp_identifier, compIdentifier);
+ EXPECT_EQ(inEntry->comp_classification_index,
+ outEntry.comp_classification_index);
+ EXPECT_EQ(outEntry.active_comp_comparison_stamp, timestamp);
+ EXPECT_EQ(inEntry->active_comp_ver_str_type,
+ outEntry.active_comp_ver_str_type);
+ EXPECT_EQ(inEntry->active_comp_ver_str_len,
+ outEntry.active_comp_ver_str_len);
+ EXPECT_EQ(0, memcmp(inEntry->active_comp_release_date,
+ outEntry.active_comp_release_date,
+ sizeof(inEntry->active_comp_release_date)));
+ EXPECT_EQ(outEntry.pending_comp_comparison_stamp, timestamp);
+ EXPECT_EQ(inEntry->pending_comp_ver_str_type,
+ outEntry.pending_comp_ver_str_type);
+ EXPECT_EQ(inEntry->pending_comp_ver_str_len,
+ outEntry.pending_comp_ver_str_len);
+ EXPECT_EQ(0, memcmp(inEntry->pending_comp_release_date,
+ outEntry.pending_comp_release_date,
+ sizeof(inEntry->pending_comp_release_date)));
+ EXPECT_EQ(outEntry.comp_activation_methods.value, compActivationMethods);
+ EXPECT_EQ(outEntry.capabilities_during_update.value,
+ capabilitiesDuringUpdate);
+
+ EXPECT_EQ(0, memcmp(outActiveCompVerStr.ptr,
+ entry.data() + activeCompVerStrPos,
+ outActiveCompVerStr.length));
+ EXPECT_EQ(0, memcmp(outPendingCompVerStr.ptr,
+ entry.data() + pendingCompVerStrPos,
+ outPendingCompVerStr.length));
+}