platform: Add decode API for File Descriptor PDR
Add decode API to decode File Descriptor PDR raw data to
`pldm_file_descriptor_pdr` struct. The referred File Descriptor PDR is
based on DSP0248 1.3.0 Section 28.30 Table 108.
Change-Id: Ifcfae68d8bf6a723cf132b851621b068e2118d0e
Signed-off-by: Chau Ly <chaul@amperecomputing.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 06d4684..a3afd66 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -36,6 +36,11 @@
- base: Add encode req & decode resp for MultipartReceive
+- pdr: Add pldm_file_descriptor_pdr struct
+
+- platform: Add decode_pldm_file_descriptor_pdr() and
+ decode_pldm_file_descriptor_pdr_names()
+
### Changed
- dsp: firmware_update: Expand "params" in symbol names
diff --git a/include/libpldm/platform.h b/include/libpldm/platform.h
index 6e5d5a5..519a5a4 100644
--- a/include/libpldm/platform.h
+++ b/include/libpldm/platform.h
@@ -130,6 +130,15 @@
*/
#define PLDM_PDR_ENTITY_AUXILIARY_NAME_PDR_MIN_LENGTH 8
+/**
+ * Minimum length of File Descriptor PDR, including size of PLDMTerminusHandle,
+ * FileIdentifier, EntityType, EntityInstanceNumber, ContainerID,
+ * SuperiorDirectoryFileIdentifier, FileClassification, OemFileClassification,
+ * FileCapabilities, FileVersion, FileMaximumSize, FileMaximumFileDescriptorCount,
+ * FileNameLength in `Table 108 - File Descriptor PDR` of DSP0248 v1.3.0
+ */
+#define PLDM_PDR_FILE_DESCRIPTOR_PDR_MIN_LENGTH 36
+
#define PLDM_INVALID_EFFECTER_ID 0xffff
/* DSP0248 Table1 PLDM monitoring and control data types */
@@ -276,6 +285,7 @@
PLDM_REDFISH_RESOURCE_PDR = 22,
PLDM_REDFISH_ENTITY_ASSOCIATION_PDR = 23,
PLDM_REDFISH_ACTION_PDR = 24,
+ PLDM_FILE_DESCRIPTOR_PDR = 30,
PLDM_OEM_DEVICE_PDR = 126,
PLDM_OEM_PDR = 127,
};
@@ -926,6 +936,28 @@
uint8_t effecter_names[1];
} __attribute__((packed));
+/** @struct pldm_file_descriptor_pdr
+ *
+ * Structure representing PLDM File Descriptor PDR for unpacked value
+ * Refer to: DSP0248_1.3.0: 28.30 Table 108
+ */
+
+struct pldm_file_descriptor_pdr {
+ struct pldm_value_pdr_hdr hdr;
+ uint16_t terminus_handle;
+ uint16_t file_identifier;
+ pldm_entity container;
+ uint16_t superior_directory_file_identifier;
+ uint8_t file_classification;
+ uint8_t oem_file_classification;
+ bitfield16_t file_capabilities;
+ ver32_t file_version;
+ uint32_t file_maximum_size;
+ uint8_t file_maximum_file_descriptor_count;
+ struct variable_field file_name;
+ struct variable_field oem_file_classification_name;
+};
+
/** @brief Encode PLDM state effecter PDR
*
* @param[in/out] effecter Structure to encode. All members of
@@ -2541,6 +2573,24 @@
*/
uint8_t *
pldm_platform_cper_event_event_data(struct pldm_platform_cper_event *event);
+
+/** @brief Decode date fields from File Descriptor PDR
+ *
+ * @param[in] data - PLDM response message which includes the File
+ * Descriptor PDR in DSP0248_1.3.0 table 108.
+ * @param[in] data_length - Length of response message payload
+ * @param[out] pdr - pointer to the decoded pdr struct
+ *
+ * @return error code: 0 on success
+ * -EINVAL if 1. the input and output parameters' memory are not
+ * allocated
+ * -EBADMSG if the original length of the data buffer is larger
+ * than the target extract length
+ * -EOVERFLOW if the original length of the data buffer is smaller
+ * than the target extract length
+ */
+int decode_pldm_file_descriptor_pdr(const void *data, size_t data_length,
+ struct pldm_file_descriptor_pdr *pdr);
#ifdef __cplusplus
}
#endif
diff --git a/src/dsp/platform.c b/src/dsp/platform.c
index 0d5d917..18de641 100644
--- a/src/dsp/platform.c
+++ b/src/dsp/platform.c
@@ -3264,3 +3264,68 @@
{
return event->event_data;
}
+
+LIBPLDM_ABI_TESTING
+int decode_pldm_file_descriptor_pdr(const void *data, size_t data_length,
+ struct pldm_file_descriptor_pdr *pdr)
+{
+ PLDM_MSGBUF_DEFINE_P(buf);
+ int rc;
+
+ if (!data || !pdr) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf,
+ PLDM_PDR_FILE_DESCRIPTOR_PDR_MIN_LENGTH,
+ data, data_length);
+ if (rc) {
+ return rc;
+ }
+
+ rc = pldm_msgbuf_extract_value_pdr_hdr(
+ buf, &pdr->hdr, PLDM_PDR_FILE_DESCRIPTOR_PDR_MIN_LENGTH,
+ data_length);
+ if (rc) {
+ return pldm_msgbuf_discard(buf, rc);
+ }
+
+ pldm_msgbuf_extract(buf, pdr->terminus_handle);
+ pldm_msgbuf_extract(buf, pdr->file_identifier);
+ pldm_msgbuf_extract(buf, pdr->container.entity_type);
+ pldm_msgbuf_extract(buf, pdr->container.entity_instance_num);
+ pldm_msgbuf_extract(buf, pdr->container.entity_container_id);
+ pldm_msgbuf_extract(buf, pdr->superior_directory_file_identifier);
+ pldm_msgbuf_extract(buf, pdr->file_classification);
+ pldm_msgbuf_extract(buf, pdr->oem_file_classification);
+ pldm_msgbuf_extract(buf, pdr->file_capabilities.value);
+ pldm_msgbuf_extract(buf, pdr->file_version.alpha);
+ pldm_msgbuf_extract(buf, pdr->file_version.update);
+ pldm_msgbuf_extract(buf, pdr->file_version.minor);
+ pldm_msgbuf_extract(buf, pdr->file_version.major);
+ pldm_msgbuf_extract(buf, pdr->file_maximum_size);
+ pldm_msgbuf_extract(buf, pdr->file_maximum_file_descriptor_count);
+ rc = pldm_msgbuf_extract_uint8_to_size(buf, pdr->file_name.length);
+ if (rc) {
+ return pldm_msgbuf_discard(buf, rc);
+ }
+
+ pldm_msgbuf_span_required(buf, pdr->file_name.length,
+ (void **)&pdr->file_name.ptr);
+
+ pdr->oem_file_classification_name.length = 0;
+
+ if (pdr->oem_file_classification) {
+ rc = pldm_msgbuf_extract_uint8_to_size(
+ buf, pdr->oem_file_classification_name.length);
+ if (rc) {
+ return pldm_msgbuf_discard(buf, rc);
+ }
+
+ pldm_msgbuf_span_required(
+ buf, pdr->oem_file_classification_name.length,
+ (void **)&pdr->oem_file_classification_name.ptr);
+ }
+
+ return pldm_msgbuf_complete_consumed(buf);
+}
diff --git a/tests/dsp/platform.cpp b/tests/dsp/platform.cpp
index 2f88ee4..e0032a2 100644
--- a/tests/dsp/platform.cpp
+++ b/tests/dsp/platform.cpp
@@ -5839,3 +5839,244 @@
free(cperEvent);
}
+
+#ifdef LIBPLDM_API_TESTING
+TEST(decodePldmFileDescriptorPdr, oemFileClassificationPresentTest)
+{
+ std::vector<uint8_t> pdr1{
+ // Common PDR Header
+ 0x01, 0x0, 0x0, 0x0, // Record Handle
+ 0x01, // PDR Header Version
+ PLDM_FILE_DESCRIPTOR_PDR, // PDRType
+ 0x01, 0x00, // Record Change Number
+ 0x2A, 0x00, // Data Length = 42 bytes
+ /* PLDM File Descriptor PDR Data*/
+ 0x01, 0x00, // Terminus Handle = 0x01
+ 0x01, 0x00, // File Identifier = 0x01
+ 0x09, 0x00, // Entity Type = Physical | Device File
+ 0x01, 0x00, // Entity instance number = 1
+ PLDM_PLATFORM_ENTITY_SYSTEM_CONTAINER_ID,
+ 0, // Container ID = Overall system
+ 0x02, 0, // Supper Dir File Identifier = 0x0002
+ 0x01, // File Classification = 0x01 (BootLog)
+ 0x01, // OEM File Classification = 0x01
+ 0x15, 0x00, // File Capabilities = 0x0015
+ 0xff, 0xff, 0xff, 0xff, // File Version = 0xffffffff (Unversioned)
+ 0x00, 0x28, 0x00, 0x00, // File Maximum Size = 10KB
+ 0x02, // File Maximum File Descriptor count = 2
+ 0x06, // File Name Length = 6
+ 0x46, 0x69, 0x6C, 0x65, 0x31,
+ 0x00, // File Name = "File1\NULL"
+ 0x09, // OEM File Classification Name Length = 9
+ 0x4F, 0x45, 0x4D, 0x20, 0x46, 0x69, 0x6C, 0x65,
+ 0x00 // OEM File Classification Name = "OEM File\NULL"
+ };
+
+ const char expectFileName[] = "File1";
+ const char expectOEMClassificationName[] = "OEM File";
+
+ struct pldm_file_descriptor_pdr decodedPdr = {};
+
+ auto rc =
+ decode_pldm_file_descriptor_pdr(pdr1.data(), pdr1.size(), &decodedPdr);
+
+ ASSERT_EQ(0, rc);
+ EXPECT_EQ(1, decodedPdr.terminus_handle);
+ EXPECT_EQ(1, decodedPdr.file_identifier);
+ EXPECT_EQ(9, decodedPdr.container.entity_type);
+ EXPECT_EQ(1, decodedPdr.container.entity_instance_num);
+ EXPECT_EQ(PLDM_PLATFORM_ENTITY_SYSTEM_CONTAINER_ID,
+ decodedPdr.container.entity_container_id);
+ EXPECT_EQ(2, decodedPdr.superior_directory_file_identifier);
+ EXPECT_EQ(1, decodedPdr.file_classification);
+ EXPECT_EQ(1, decodedPdr.oem_file_classification);
+ EXPECT_EQ(21, decodedPdr.file_capabilities.value);
+ EXPECT_EQ(0xff, decodedPdr.file_version.alpha);
+ EXPECT_EQ(0xff, decodedPdr.file_version.update);
+ EXPECT_EQ(0xff, decodedPdr.file_version.minor);
+ EXPECT_EQ(0xff, decodedPdr.file_version.major);
+ EXPECT_EQ(10240, decodedPdr.file_maximum_size);
+ EXPECT_EQ(2, decodedPdr.file_maximum_file_descriptor_count);
+ EXPECT_EQ(6, decodedPdr.file_name.length);
+
+ EXPECT_EQ(memcmp(expectFileName, decodedPdr.file_name.ptr,
+ sizeof(char) * decodedPdr.file_name.length),
+ 0);
+
+ if (decodedPdr.oem_file_classification)
+ {
+ EXPECT_EQ(9, decodedPdr.oem_file_classification_name.length);
+ EXPECT_EQ(memcmp(expectOEMClassificationName,
+ decodedPdr.oem_file_classification_name.ptr,
+ sizeof(char) *
+ decodedPdr.oem_file_classification_name.length),
+ 0);
+ }
+}
+#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(decodePldmFileDescriptorPdr, BadTestUnAllocatedPtrParams)
+{
+ int rc;
+ std::vector<uint8_t> pdr1{
+ // Common PDR Header
+ 0x01, 0x0, 0x0, 0x0, // Record Handle
+ 0x01, // PDR Header Version
+ PLDM_FILE_DESCRIPTOR_PDR, // PDRType
+ 0x01, 0x00, // Record Change Number
+ 0x20, 0x00, // Data Length = 32 bytes
+ /* PLDM File Descriptor PDR Data*/
+ 0x01, 0x00, // Terminus Handle = 0x01
+ 0x01, 0x00, // File Identifier = 0x01
+ 0x09, 0x00, // Entity Type = Physical | Device File
+ 0x01, 0x00, // Entity instance number = 1
+ PLDM_PLATFORM_ENTITY_SYSTEM_CONTAINER_ID,
+ 0, // Container ID = Overall system
+ 0x02, 0, // Supper Dir File Identifier = 0x0002
+ 0x01, // File Classification = 0x01 (BootLog)
+ 0x00, // OEM File Classification = 0x00
+ 0x15, 0x00, // File Capabilities = 0x0015
+ 0xff, 0xff, 0xff, 0xff, // File Version = 0xffffffff (Unversioned)
+ 0x00, 0x28, 0x00, 0x00, // File Maximum Size = 10KB
+ 0x02, // File Maximum File Descriptor count = 2
+ 0x06, // File Name Length = 6
+ 0x46, 0x69, 0x6C, 0x65, 0x31,
+ 0x00, // File Name = "File1\NULL"
+ };
+
+ struct pldm_file_descriptor_pdr decodedPdr = {};
+
+ rc = decode_pldm_file_descriptor_pdr(nullptr, pdr1.size(), &decodedPdr);
+ EXPECT_EQ(-EINVAL, rc);
+
+ rc = decode_pldm_file_descriptor_pdr(pdr1.data(), pdr1.size(), nullptr);
+ EXPECT_EQ(-EINVAL, rc);
+}
+#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(decodePldmFileDescriptorPdr, BadTestInvalidExpectedParamLength)
+{
+ int rc;
+
+ std::vector<uint8_t> pdr1{
+ // Common PDR Header
+ 0x01, 0x0, 0x0, 0x0, // Record Handle
+ 0x01, // PDR Header Version
+ PLDM_FILE_DESCRIPTOR_PDR, // PDRType
+ 0x01, 0x00, // Record Change Number
+ 0x20, 0x00, // Data Length = 32 bytes
+ /* PLDM File Descriptor PDR Data*/
+ 0x01, 0x00, // Terminus Handle = 0x01
+ 0x01, 0x00, // File Identifier = 0x01
+ 0x09, 0x00, // Entity Type = Physical | Device File
+ 0x01, 0x00, // Entity instance number = 1
+ PLDM_PLATFORM_ENTITY_SYSTEM_CONTAINER_ID,
+ 0, // Container ID = Overall system
+ 0x02, 0, // Supper Dir File Identifier = 0x0002
+ 0x01, // File Classification = 0x01 (BootLog)
+ 0x00, // OEM File Classification = 0x00
+ 0x15, 0x00, // File Capabilities = 0x0015
+ 0xff, 0xff, 0xff, 0xff, // File Version = 0xffffffff (Unversioned)
+ 0x00, 0x28, 0x00, 0x00, // File Maximum Size = 10KB
+ 0x02, // File Maximum File Descriptor count = 2
+ 0x06, // File Name Length = 6
+ 0x46, 0x69, 0x6C, 0x65, 0x31,
+ 0x00, // File Name = "File1\NULL"
+ };
+
+ struct pldm_file_descriptor_pdr decodedPdr = {};
+
+ /* Expect error: Invalid input data length*/
+ rc = decode_pldm_file_descriptor_pdr(pdr1.data(), 1, &decodedPdr);
+ EXPECT_EQ(-EOVERFLOW, rc);
+}
+#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(decodePldmFileDescriptorPdr, BadTestDataBufferOverLength)
+{
+ int rc;
+
+ /*Un-matched File Name Length*/
+ std::vector<uint8_t> pdr1{
+ // Common PDR Header
+ 0x01, 0x0, 0x0, 0x0, // Record Handle
+ 0x01, // PDR Header Version
+ PLDM_FILE_DESCRIPTOR_PDR, // PDRType
+ 0x01, 0x00, // Record Change Number
+ 0x20, 0x00, // Data Length = 32 bytes
+ /* PLDM File Descriptor PDR Data*/
+ 0x01, 0x00, // Terminus Handle = 0x01
+ 0x01, 0x00, // File Identifier = 0x01
+ 0x09, 0x00, // Entity Type = Physical | Device File
+ 0x01, 0x00, // Entity instance number = 1
+ PLDM_PLATFORM_ENTITY_SYSTEM_CONTAINER_ID,
+ 0, // Container ID = Overall system
+ 0x02, 0, // Supper Dir File Identifier = 0x0002
+ 0x01, // File Classification = 0x01 (BootLog)
+ 0x00, // OEM File Classification = 0x00
+ 0x15, 0x00, // File Capabilities = 0x0015
+ 0xff, 0xff, 0xff, 0xff, // File Version = 0xffffffff (Unversioned)
+ 0x00, 0x28, 0x00, 0x00, // File Maximum Size = 10KB
+ 0x02, // File Maximum File Descriptor count = 2
+ 0x05, // File Name Length = 5
+ 0x46, 0x69, 0x6C, 0x65, 0x31,
+ 0x00, // File Name = "File1\NULL"
+ };
+
+ struct pldm_file_descriptor_pdr decodedPdr = {};
+
+ /*
+ * Expect error: The original length of the data buffer is larger than
+ * the target extract length.
+ */
+ rc = decode_pldm_file_descriptor_pdr(pdr1.data(), pdr1.size(), &decodedPdr);
+ EXPECT_EQ(-EBADMSG, rc);
+}
+
+TEST(decodePldmFileDescriptorPdr, BadTestDataBufferUnderLength)
+{
+ int rc;
+
+ /*Un-matched OEM File Classification Name Length*/
+ std::vector<uint8_t> pdr1{
+ // Common PDR Header
+ 0x01, 0x0, 0x0, 0x0, // Record Handle
+ 0x01, // PDR Header Version
+ PLDM_FILE_DESCRIPTOR_PDR, // PDRType
+ 0x01, 0x00, // Record Change Number
+ 0x2A, 0x00, // Data Length = 42 bytes
+ /* PLDM File Descriptor PDR Data*/
+ 0x01, 0x00, // Terminus Handle = 0x01
+ 0x01, 0x00, // File Identifier = 0x01
+ 0x09, 0x00, // Entity Type = Physical | Device File
+ 0x01, 0x00, // Entity instance number = 1
+ PLDM_PLATFORM_ENTITY_SYSTEM_CONTAINER_ID,
+ 0, // Container ID = Overall system
+ 0x02, 0, // Supper Dir File Identifier = 0x0002
+ 0x01, // File Classification = 0x01 (BootLog)
+ 0x01, // OEM File Classification = 0x01
+ 0x15, 0x00, // File Capabilities = 0x0015
+ 0xff, 0xff, 0xff, 0xff, // File Version = 0xffffffff (Unversioned)
+ 0x00, 0x28, 0x00, 0x00, // File Maximum Size = 10KB
+ 0x02, // File Maximum File Descriptor count = 2
+ 0x06, // File Name Length = 6
+ 0x46, 0x69, 0x6C, 0x65, 0x31,
+ 0x00, // File Name = "File1\NULL"
+ 0x0B, // OEM File Classification Name Length = 11
+ 0x4F, 0x45, 0x4D, 0x20, 0x46, 0x69, 0x6C, 0x65,
+ 0x00 // OEM File Classification Name = "OEM File\NULL"
+ };
+
+ struct pldm_file_descriptor_pdr decodedPdr = {};
+
+ /*
+ * Expect error: The original length of the data buffer is smaller than
+ * the target extract length.
+ */
+ rc = decode_pldm_file_descriptor_pdr(pdr1.data(), pdr1.size(), &decodedPdr);
+ EXPECT_EQ(-EOVERFLOW, rc);
+}
+#endif