libpldm: Add decode API for UpdateComponent response
The update agent sends UpdateComponent command to request updating a
specific firmware component. The decode API will decode the response
from the firmware device. 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: Icf841a9a6feb4678206ba8b19bf8184467a42276
diff --git a/libpldm/tests/libpldm_firmware_update_test.cpp b/libpldm/tests/libpldm_firmware_update_test.cpp
index f0ae99d..cc2d0f0 100644
--- a/libpldm/tests/libpldm_firmware_update_test.cpp
+++ b/libpldm/tests/libpldm_firmware_update_test.cpp
@@ -1816,4 +1816,162 @@
         PLDM_STR_TYPE_UNKNOWN, compVerStrLen, &compVerStrInfo, requestMsg,
         sizeof(pldm_update_component_req) + compVerStrLen);
     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
-}
\ No newline at end of file
+}
+
+TEST(UpdateComponent, goodPathDecodeResponse)
+{
+    constexpr std::bitset<32> forceUpdateComp{1};
+    constexpr uint16_t timeBeforeSendingReqFwData100s = 100;
+    constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
+        updateComponentResponse1{0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                 0x01, 0x00, 0x00, 0x00, 0x64, 0x00};
+    auto responseMsg1 =
+        reinterpret_cast<const pldm_msg*>(updateComponentResponse1.data());
+
+    uint8_t completionCode = 0;
+    uint8_t compCompatibilityResp = 0;
+    uint8_t compCompatibilityRespCode = 0;
+    bitfield32_t updateOptionFlagsEnabled{};
+    uint16_t timeBeforeReqFWData = 0;
+
+    auto rc = decode_update_component_resp(
+        responseMsg1, sizeof(pldm_update_component_resp), &completionCode,
+        &compCompatibilityResp, &compCompatibilityRespCode,
+        &updateOptionFlagsEnabled, &timeBeforeReqFWData);
+
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+    EXPECT_EQ(completionCode, PLDM_SUCCESS);
+    EXPECT_EQ(compCompatibilityResp, PLDM_CCR_COMP_CAN_BE_UPDATED);
+    EXPECT_EQ(compCompatibilityRespCode, PLDM_CCRC_NO_RESPONSE_CODE);
+    EXPECT_EQ(updateOptionFlagsEnabled.value, forceUpdateComp);
+    EXPECT_EQ(timeBeforeReqFWData, timeBeforeSendingReqFwData100s);
+
+    constexpr std::bitset<32> noFlags{};
+    constexpr uint16_t timeBeforeSendingReqFwData0s = 0;
+    constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
+        updateComponentResponse2{0x00, 0x00, 0x00, 0x00, 0x01, 0x09,
+                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+    auto responseMsg2 =
+        reinterpret_cast<const pldm_msg*>(updateComponentResponse2.data());
+    rc = decode_update_component_resp(
+        responseMsg2, sizeof(pldm_update_component_resp), &completionCode,
+        &compCompatibilityResp, &compCompatibilityRespCode,
+        &updateOptionFlagsEnabled, &timeBeforeReqFWData);
+
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+    EXPECT_EQ(completionCode, PLDM_SUCCESS);
+    EXPECT_EQ(compCompatibilityResp, PLDM_CCR_COMP_CANNOT_BE_UPDATED);
+    EXPECT_EQ(compCompatibilityRespCode, PLDM_CCRC_COMP_INFO_NO_MATCH);
+    EXPECT_EQ(updateOptionFlagsEnabled.value, noFlags);
+    EXPECT_EQ(timeBeforeReqFWData, timeBeforeSendingReqFwData0s);
+
+    constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
+        updateComponentResponse3{0x00, 0x00, 0x00, 0x80};
+    auto responseMsg3 =
+        reinterpret_cast<const pldm_msg*>(updateComponentResponse3.data());
+
+    rc = decode_update_component_resp(
+        responseMsg3, sizeof(pldm_update_component_resp), &completionCode,
+        &compCompatibilityResp, &compCompatibilityRespCode,
+        &updateOptionFlagsEnabled, &timeBeforeReqFWData);
+
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+    EXPECT_EQ(completionCode, PLDM_FWUP_NOT_IN_UPDATE_MODE);
+}
+
+TEST(UpdateComponent, errorPathDecodeResponse)
+{
+    constexpr std::array<uint8_t,
+                         hdrSize + sizeof(pldm_update_component_resp) - 1>
+        updateComponentResponse1{0x00, 0x00, 0x00, 0x00, 0x01, 0x09,
+                                 0x00, 0x00, 0x00, 0x00, 0x00};
+    auto responseMsg1 =
+        reinterpret_cast<const pldm_msg*>(updateComponentResponse1.data());
+
+    uint8_t completionCode = 0;
+    uint8_t compCompatibilityResp = 0;
+    uint8_t compCompatibilityRespCode = 0;
+    bitfield32_t updateOptionFlagsEnabled{};
+    uint16_t timeBeforeReqFWData = 0;
+
+    auto rc = decode_update_component_resp(
+        nullptr, sizeof(pldm_update_component_resp) - 1, &completionCode,
+        &compCompatibilityResp, &compCompatibilityRespCode,
+        &updateOptionFlagsEnabled, &timeBeforeReqFWData);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    rc = decode_update_component_resp(
+        responseMsg1, sizeof(pldm_update_component_resp) - 1, nullptr,
+        &compCompatibilityResp, &compCompatibilityRespCode,
+        &updateOptionFlagsEnabled, &timeBeforeReqFWData);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    rc = decode_update_component_resp(
+        responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode,
+        nullptr, &compCompatibilityRespCode, &updateOptionFlagsEnabled,
+        &timeBeforeReqFWData);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    rc = decode_update_component_resp(
+        responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode,
+        &compCompatibilityResp, nullptr, &updateOptionFlagsEnabled,
+        &timeBeforeReqFWData);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    rc = decode_update_component_resp(
+        responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode,
+        &compCompatibilityResp, &compCompatibilityRespCode, nullptr,
+        &timeBeforeReqFWData);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    rc = decode_update_component_resp(
+        responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode,
+        &compCompatibilityResp, &compCompatibilityRespCode,
+        &updateOptionFlagsEnabled, nullptr);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    rc = decode_update_component_resp(
+        responseMsg1, 0, &completionCode, &compCompatibilityResp,
+        &compCompatibilityRespCode, &updateOptionFlagsEnabled,
+        &timeBeforeReqFWData);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    rc = decode_update_component_resp(
+        responseMsg1, sizeof(pldm_update_component_resp) - 1, &completionCode,
+        &compCompatibilityResp, &compCompatibilityRespCode,
+        &updateOptionFlagsEnabled, &timeBeforeReqFWData);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+
+    constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
+        updateComponentResponse2{0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+                                 0x01, 0x00, 0x00, 0x00, 0x64, 0x00};
+    auto responseMsg2 =
+        reinterpret_cast<const pldm_msg*>(updateComponentResponse2.data());
+    rc = decode_update_component_resp(
+        responseMsg2, sizeof(pldm_update_component_resp), &completionCode,
+        &compCompatibilityResp, &compCompatibilityRespCode,
+        &updateOptionFlagsEnabled, &timeBeforeReqFWData);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
+        updateComponentResponse3{0x00, 0x00, 0x00, 0x00, 0x00, 0x0C,
+                                 0x01, 0x00, 0x00, 0x00, 0x64, 0x00};
+    auto responseMsg3 =
+        reinterpret_cast<const pldm_msg*>(updateComponentResponse3.data());
+    rc = decode_update_component_resp(
+        responseMsg3, sizeof(pldm_update_component_resp), &completionCode,
+        &compCompatibilityResp, &compCompatibilityRespCode,
+        &updateOptionFlagsEnabled, &timeBeforeReqFWData);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+    constexpr std::array<uint8_t, hdrSize + sizeof(pldm_update_component_resp)>
+        updateComponentResponse4{0x00, 0x00, 0x00, 0x00, 0x00, 0xF0,
+                                 0x01, 0x00, 0x00, 0x00, 0x64, 0x00};
+    auto responseMsg4 =
+        reinterpret_cast<const pldm_msg*>(updateComponentResponse4.data());
+    rc = decode_update_component_resp(
+        responseMsg4, sizeof(pldm_update_component_resp), &completionCode,
+        &compCompatibilityResp, &compCompatibilityRespCode,
+        &updateOptionFlagsEnabled, &timeBeforeReqFWData);
+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}