libpldm: Add decode API for ActivateFirmware response

After all firmware components in the FD have been transferred and
applied, the UA sends this command to inform the FD to prepare all
successfully applied components to become active at the next
activation. 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: I68621957dd4eaf5004b1be92ef7e8669dbd25213
diff --git a/libpldm/firmware_update.c b/libpldm/firmware_update.c
index 7a4fbba..cf8080e 100644
--- a/libpldm/firmware_update.c
+++ b/libpldm/firmware_update.c
@@ -1229,3 +1229,31 @@
 

 	return PLDM_SUCCESS;

 }

+

+int decode_activate_firmware_resp(const struct pldm_msg *msg,

+				  size_t payload_length,

+				  uint8_t *completion_code,

+				  uint16_t *estimated_time_activation)

+{

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

+	    estimated_time_activation == NULL || !payload_length) {

+		return PLDM_ERROR_INVALID_DATA;

+	}

+

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

+	if (*completion_code != PLDM_SUCCESS) {

+		return PLDM_SUCCESS;

+	}

+

+	if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {

+		return PLDM_ERROR_INVALID_LENGTH;

+	}

+

+	struct pldm_activate_firmware_resp *response =

+	    (struct pldm_activate_firmware_resp *)msg->payload;

+

+	*estimated_time_activation =

+	    le16toh(response->estimated_time_activation);

+

+	return PLDM_SUCCESS;

+}

diff --git a/libpldm/firmware_update.h b/libpldm/firmware_update.h
index bffd296..bb09c56 100644
--- a/libpldm/firmware_update.h
+++ b/libpldm/firmware_update.h
@@ -464,6 +464,15 @@
 	bool8_t self_contained_activation_req;

 } __attribute__((packed));

 

+/** @struct activate_firmware_resp

+ *

+ *  Structure representing Activate Firmware response

+ */

+struct pldm_activate_firmware_resp {

+	uint8_t completion_code;

+	uint16_t estimated_time_activation;

+} __attribute__((packed));

+

 /** @brief Decode the PLDM package header information

  *

  *  @param[in] data - pointer to package header information

@@ -916,6 +925,21 @@
 				 bool8_t self_contained_activation_req,

 				 struct pldm_msg *msg, size_t payload_length);

 

+/** @brief Decode ActivateFirmware response message

+ *

+ *  @param[in] msg - Response message

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

+ *  @param[out] completion_code - Pointer to hold CompletionCode

+ *  @param[out] estimated_time_activation - Pointer to hold

+ *                                       EstimatedTimeForSelfContainedActivation

+ *

+ *  @return pldm_completion_codes

+ */

+int decode_activate_firmware_resp(const struct pldm_msg *msg,

+				  size_t payload_length,

+				  uint8_t *completion_code,

+				  uint16_t *estimated_time_activation);

+

 #ifdef __cplusplus

 }

 #endif

diff --git a/libpldm/tests/libpldm_firmware_update_test.cpp b/libpldm/tests/libpldm_firmware_update_test.cpp
index 89e1f4a..350db59 100644
--- a/libpldm/tests/libpldm_firmware_update_test.cpp
+++ b/libpldm/tests/libpldm_firmware_update_test.cpp
@@ -2385,3 +2385,70 @@
                                       sizeof(pldm_activate_firmware_req));

     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);

 }

+

+TEST(ActivateFirmware, goodPathDecodeResponse)

+{

+    constexpr uint16_t estimatedTimeForActivation100s = 100;

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

+        activateFirmwareResponse1{0x00, 0x00, 0x00, 0x00, 0x64, 0x00};

+    auto responseMsg1 =

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

+

+    uint8_t completionCode = 0;

+    uint16_t estimatedTimeForActivation = 0;

+

+    auto rc = decode_activate_firmware_resp(

+        responseMsg1, sizeof(pldm_activate_firmware_resp), &completionCode,

+        &estimatedTimeForActivation);

+

+    EXPECT_EQ(rc, PLDM_SUCCESS);

+    EXPECT_EQ(completionCode, PLDM_SUCCESS);

+    EXPECT_EQ(estimatedTimeForActivation, estimatedTimeForActivation100s);

+

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

+        activateFirmwareResponse2{0x00, 0x00, 0x00, 0x85};

+    auto responseMsg2 =

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

+

+    rc = decode_activate_firmware_resp(responseMsg2, sizeof(completionCode),

+                                       &completionCode,

+                                       &estimatedTimeForActivation);

+

+    EXPECT_EQ(rc, PLDM_SUCCESS);

+    EXPECT_EQ(completionCode, PLDM_FWUP_INCOMPLETE_UPDATE);

+}

+

+TEST(ActivateFirmware, errorPathDecodeResponse)

+{

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

+        activateFirmwareResponse{0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

+    auto responseMsg =

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

+

+    uint8_t completionCode = 0;

+    uint16_t estimatedTimeForActivation = 0;

+

+    auto rc = decode_activate_firmware_resp(

+        nullptr, sizeof(pldm_activate_firmware_resp), &completionCode,

+        &estimatedTimeForActivation);

+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);

+

+    rc = decode_activate_firmware_resp(responseMsg,

+                                       sizeof(pldm_activate_firmware_resp),

+                                       nullptr, &estimatedTimeForActivation);

+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);

+

+    rc = decode_activate_firmware_resp(responseMsg,

+                                       sizeof(pldm_activate_firmware_resp),

+                                       &completionCode, nullptr);

+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);

+

+    rc = decode_activate_firmware_resp(responseMsg, 0, &completionCode,

+                                       &estimatedTimeForActivation);

+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);

+

+    rc = decode_activate_firmware_resp(

+        responseMsg, sizeof(pldm_activate_firmware_resp) - 1, &completionCode,

+        &estimatedTimeForActivation);

+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);

+}
\ No newline at end of file