libpldm: Add decode API for TransferComplete request

The FD sends TransferComplete command to the UA once the FD has
transferred all the data for the component image or determines the
transfer has failed. If the TransferResult of the request message
indicates the transfer completed without error then, upon the
successful completion of this command, the FD proceeds to the next
step that verifies the firmware. This implementation works with
DSP0267_1.1.0, DSP0267_1.0.1 and DSP0267_1.0.0.

Tested: Unit tests passed

Signed-off-by: gokulsanker <gokul.sanker.v.g@intel.com>
Change-Id: I22c6ef60324dbedd3b3fa67754c9aec48dd9f311
diff --git a/libpldm/firmware_update.c b/libpldm/firmware_update.c
index 05b6db9..b10c1a1 100644
--- a/libpldm/firmware_update.c
+++ b/libpldm/firmware_update.c
@@ -1039,4 +1039,20 @@
 	msg->payload[0] = completion_code;

 

 	return PLDM_SUCCESS;

-}
\ No newline at end of file
+}

+

+int decode_transfer_complete_req(const struct pldm_msg *msg,

+				 size_t payload_length,

+				 uint8_t *transfer_result)

+{

+	if (msg == NULL || transfer_result == NULL) {

+		return PLDM_ERROR_INVALID_DATA;

+	}

+

+	if (payload_length != sizeof(*transfer_result)) {

+		return PLDM_ERROR_INVALID_LENGTH;

+	}

+

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

+	return PLDM_SUCCESS;

+}

diff --git a/libpldm/firmware_update.h b/libpldm/firmware_update.h
index 24f8c56..7b1c9f1 100644
--- a/libpldm/firmware_update.h
+++ b/libpldm/firmware_update.h
@@ -185,6 +185,28 @@
 	PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX = 0xEF

 };

 

+/** @brief Common error codes in TransferComplete, VerifyComplete and

+ *        ApplyComplete request

+ */

+enum pldm_firmware_update_common_error_codes {

+	PLDM_FWUP_TIME_OUT = 0x09,

+	PLDM_FWUP_GENERIC_ERROR = 0x0A

+};

+

+/** @brief TransferResult values in the response of TransferComplete

+ */

+enum pldm_firmware_update_transfer_result {

+	PLDM_FWUP_TRANSFER_SUCCESS = 0x00,

+	PLDM_FWUP_TRANSFER_ERROR_IMAGE_CORRUPT = 0x02,

+	PLDM_FWUP_TRANSFER_ERROR_VERSION_MISMATCH = 0x02,

+	PLDM_FWUP_FD_ABORTED_TRANSFER = 0x03,

+	PLDM_FWUP_FD_ABORTED_TRANSFER_LOW_POWER_STATE = 0x0B,

+	PLDM_FWUP_FD_ABORTED_TRANSFER_RESET_NEEDED = 0x0C,

+	PLDM_FWUP_FD_ABORTED_TRANSFER_STORAGE_ISSUE = 0x0D,

+	PLDM_FWUP_VENDOR_TRANSFER_RESULT_RANGE_MIN = 0x70,

+	PLDM_FWUP_VENDOR_TRANSFER_RESULT_RANGE_MAX = 0x8F

+};

+

 /** @struct pldm_package_header_information

  *

  *  Structure representing fixed part of package header information

@@ -730,6 +752,17 @@
 				      struct pldm_msg *msg,

 				      size_t payload_length);

 

+/** @brief Decode TransferComplete request message

+ *

+ *  @param[in] msg - Request message

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

+ *  @param[out] transfer_result - Pointer to hold TransferResult

+ *

+ *  @return pldm_completion_codes

+ */

+int decode_transfer_complete_req(const struct pldm_msg *msg,

+				 size_t payload_length,

+				 uint8_t *transfer_result);

 #ifdef __cplusplus

 }

 #endif

diff --git a/libpldm/tests/libpldm_firmware_update_test.cpp b/libpldm/tests/libpldm_firmware_update_test.cpp
index 8aa012f..0aacb7b 100644
--- a/libpldm/tests/libpldm_firmware_update_test.cpp
+++ b/libpldm/tests/libpldm_firmware_update_test.cpp
@@ -2080,3 +2080,45 @@
     rc = encode_request_firmware_data_resp(0, PLDM_SUCCESS, responseMsg, 0);

     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);

 }

+

+TEST(TransferComplete, goodPathDecodeRequest)

+{

+    constexpr uint8_t transferResult = PLDM_FWUP_TRANSFER_SUCCESS;

+    constexpr std::array<uint8_t, hdrSize + sizeof(transferResult)>

+        transferCompleteReq1{0x00, 0x00, 0x00, 0x00};

+    auto requestMsg1 =

+        reinterpret_cast<const pldm_msg*>(transferCompleteReq1.data());

+    uint8_t outTransferResult = 0;

+

+    auto rc = decode_transfer_complete_req(requestMsg1, sizeof(transferResult),

+                                           &outTransferResult);

+    EXPECT_EQ(rc, PLDM_SUCCESS);

+    EXPECT_EQ(outTransferResult, transferResult);

+

+    constexpr std::array<uint8_t, hdrSize + sizeof(transferResult)>

+        transferCompleteReq2{0x00, 0x00, 0x00, 0x02};

+    auto requestMsg2 =

+        reinterpret_cast<const pldm_msg*>(transferCompleteReq2.data());

+    rc = decode_transfer_complete_req(requestMsg2, sizeof(transferResult),

+                                      &outTransferResult);

+    EXPECT_EQ(rc, PLDM_SUCCESS);

+    EXPECT_EQ(outTransferResult, PLDM_FWUP_TRANSFER_ERROR_IMAGE_CORRUPT);

+}

+

+TEST(TransferComplete, errorPathDecodeRequest)

+{

+    constexpr std::array<uint8_t, hdrSize> transferCompleteReq{0x00, 0x00,

+                                                               0x00};

+    auto requestMsg =

+        reinterpret_cast<const pldm_msg*>(transferCompleteReq.data());

+    uint8_t outTransferResult = 0;

+

+    auto rc = decode_transfer_complete_req(nullptr, 0, &outTransferResult);

+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);

+

+    rc = decode_transfer_complete_req(requestMsg, 0, nullptr);

+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);

+

+    rc = decode_transfer_complete_req(requestMsg, 0, &outTransferResult);

+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);

+}