libpldm : Add decode API for QueryDeviceIdentifiers cmd

QueryDeviceIdentifiers command is used by update agent to obtain the
firmware identifiers for the firmware device and its defined in DSP0267
Version 1.1.0 sec:10.1.

Tested: Unit tests passed

Signed-off-by: gokulsanker <gokul.sanker.v.g@intel.com>
Change-Id: I9ef81ce75aaedaae2fff9f5632ce16aa952cda17
diff --git a/libpldm/firmware_update.c b/libpldm/firmware_update.c
index 25b2997..031ec85 100644
--- a/libpldm/firmware_update.c
+++ b/libpldm/firmware_update.c
@@ -1,4 +1,5 @@
 #include "firmware_update.h"

+#include <endian.h>

 

 int encode_query_device_identifiers_req(uint8_t instance_id,

 					size_t payload_length,

@@ -15,3 +16,51 @@
 	return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,

 				       PLDM_QUERY_DEVICE_IDENTIFIERS, msg);

 }

+

+int decode_query_device_identifiers_resp(const struct pldm_msg *msg,

+					 size_t payload_length,

+					 uint8_t *completion_code,

+					 uint32_t *device_identifiers_len,

+					 uint8_t *descriptor_count,

+					 uint8_t **descriptor_data)

+{

+	if (msg == NULL || completion_code == NULL ||

+	    device_identifiers_len == NULL || descriptor_count == NULL ||

+	    descriptor_data == NULL) {

+		return PLDM_ERROR_INVALID_DATA;

+	}

+

+	*completion_code = msg->payload[0];

+	if (PLDM_SUCCESS != *completion_code) {

+		return PLDM_SUCCESS;

+	}

+

+	if (payload_length <

+	    sizeof(struct pldm_query_device_identifiers_resp)) {

+		return PLDM_ERROR_INVALID_LENGTH;

+	}

+

+	struct pldm_query_device_identifiers_resp *response =

+	    (struct pldm_query_device_identifiers_resp *)msg->payload;

+	*device_identifiers_len = le32toh(response->device_identifiers_len);

+

+	if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {

+		return PLDM_ERROR_INVALID_LENGTH;

+	}

+

+	if (payload_length !=

+	    sizeof(struct pldm_query_device_identifiers_resp) +

+		*device_identifiers_len) {

+		return PLDM_ERROR_INVALID_LENGTH;

+	}

+	*descriptor_count = response->descriptor_count;

+

+	if (*descriptor_count == 0) {

+		return PLDM_ERROR_INVALID_DATA;

+	}

+

+	*descriptor_data =

+	    (uint8_t *)(msg->payload +

+			sizeof(struct pldm_query_device_identifiers_resp));

+	return PLDM_SUCCESS;

+}

diff --git a/libpldm/firmware_update.h b/libpldm/firmware_update.h
index dbff92d..6ebfa79 100644
--- a/libpldm/firmware_update.h
+++ b/libpldm/firmware_update.h
@@ -7,11 +7,25 @@
 #include "base.h"

 

 #define PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES 0

+/** @brief Minimum length of device descriptor, 2 bytes for descriptor type,

+ *         2 bytes for descriptor length and atleast 1 byte of descriptor data

+ */

+#define PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN 5

 

 /** @brief PLDM Firmware update commands

  */

 enum pldm_firmware_update_commands { PLDM_QUERY_DEVICE_IDENTIFIERS = 0x01 };

 

+/** @struct pldm_query_device_identifiers_resp

+ *

+ *  Structure representing query device identifiers response.

+ */

+struct pldm_query_device_identifiers_resp {

+	uint8_t completion_code;

+	uint32_t device_identifiers_len;

+	uint8_t descriptor_count;

+} __attribute__((packed));

+

 /** @brief Create a PLDM request message for QueryDeviceIdentifiers

  *

  *  @param[in] instance_id - Message's instance id

@@ -26,6 +40,24 @@
 int encode_query_device_identifiers_req(uint8_t instance_id,

 					size_t payload_length,

 					struct pldm_msg *msg);

+

+/** @brief Decode QueryDeviceIdentifiers response message

+ *

+ *  @param[in] msg - Response message

+ *  @param[in] payload_length - Length of response message payload

+ *  @param[out] completion_code - Pointer to response msg's PLDM completion code

+ *  @param[out] device_identifiers_len - Pointer to device identifiers length

+ *  @param[out] descriptor_count - Pointer to descriptor count

+ *  @param[out] descriptor_data - Pointer to descriptor data

+ *

+ *  @return pldm_completion_codes

+ */

+int decode_query_device_identifiers_resp(const struct pldm_msg *msg,

+					 size_t payload_length,

+					 uint8_t *completion_code,

+					 uint32_t *device_identifiers_len,

+					 uint8_t *descriptor_count,

+					 uint8_t **descriptor_data);

 #ifdef __cplusplus

 }

 #endif

diff --git a/libpldm/tests/libpldm_firmware_update_test.cpp b/libpldm/tests/libpldm_firmware_update_test.cpp
index 8387b77..489be16 100644
--- a/libpldm/tests/libpldm_firmware_update_test.cpp
+++ b/libpldm/tests/libpldm_firmware_update_test.cpp
@@ -20,3 +20,45 @@
     EXPECT_EQ(requestPtr->hdr.type, PLDM_FWUP);

     EXPECT_EQ(requestPtr->hdr.command, PLDM_QUERY_DEVICE_IDENTIFIERS);

 }

+

+TEST(QueryDeviceIdentifiers, goodPathDecodeResponse)

+{

+    // descriptorDataLen is not fixed here taking it as 6

+    constexpr uint8_t descriptorDataLen = 6;

+    std::array<uint8_t, hdrSize +

+                            sizeof(struct pldm_query_device_identifiers_resp) +

+                            descriptorDataLen>

+        responseMsg{};

+    auto inResp = reinterpret_cast<struct pldm_query_device_identifiers_resp*>(

+        responseMsg.data() + hdrSize);

+

+    inResp->completion_code = PLDM_SUCCESS;

+    inResp->device_identifiers_len = htole32(descriptorDataLen);

+    inResp->descriptor_count = 1;

+

+    // filling descriptor data

+    std::fill_n(responseMsg.data() + hdrSize +

+                    sizeof(struct pldm_query_device_identifiers_resp),

+                descriptorDataLen, 0xFF);

+

+    auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());

+    uint8_t completionCode = PLDM_SUCCESS;

+    uint32_t deviceIdentifiersLen = 0;

+    uint8_t descriptorCount = 0;

+    uint8_t* outDescriptorData = nullptr;

+

+    auto rc = decode_query_device_identifiers_resp(

+        response, responseMsg.size() - hdrSize, &completionCode,

+        &deviceIdentifiersLen, &descriptorCount, &outDescriptorData);

+

+    EXPECT_EQ(rc, PLDM_SUCCESS);

+    EXPECT_EQ(completionCode, PLDM_SUCCESS);

+    EXPECT_EQ(deviceIdentifiersLen, inResp->device_identifiers_len);

+    EXPECT_EQ(descriptorCount, inResp->descriptor_count);

+    EXPECT_EQ(true,

+              std::equal(outDescriptorData,

+                         outDescriptorData + deviceIdentifiersLen,

+                         responseMsg.begin() + hdrSize +

+                             sizeof(struct pldm_query_device_identifiers_resp),

+                         responseMsg.end()));

+}