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);
+}