libpldm: Add decode API for RequestUpdate cmd response
RequestUpdate command is the command to initiate a firmware update
for a 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: Id1c684aa17f140b318d587bd14116e03be2b4f20
diff --git a/libpldm/firmware_update.c b/libpldm/firmware_update.c
index 11007a7..b5b1162 100644
--- a/libpldm/firmware_update.c
+++ b/libpldm/firmware_update.c
@@ -670,4 +670,33 @@
comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
return PLDM_SUCCESS;
+}
+
+int decode_request_update_resp(const struct pldm_msg *msg,
+ size_t payload_length, uint8_t *completion_code,
+ uint16_t *fd_meta_data_len,
+ uint8_t *fd_will_send_pkg_data)
+{
+ if (msg == NULL || completion_code == NULL ||
+ fd_meta_data_len == NULL || fd_will_send_pkg_data == 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_request_update_resp)) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ struct pldm_request_update_resp *response =
+ (struct pldm_request_update_resp *)msg->payload;
+
+ *fd_meta_data_len = le16toh(response->fd_meta_data_len);
+ *fd_will_send_pkg_data = response->fd_will_send_pkg_data;
+
+ return PLDM_SUCCESS;
}
\ No newline at end of file
diff --git a/libpldm/firmware_update.h b/libpldm/firmware_update.h
index b21eaff..a73e083 100644
--- a/libpldm/firmware_update.h
+++ b/libpldm/firmware_update.h
@@ -26,6 +26,31 @@
PLDM_REQUEST_UPDATE = 0x10
};
+/** @brief PLDM Firmware update completion codes
+ */
+enum pldm_firmware_update_completion_codes {
+ PLDM_FWUP_NOT_IN_UPDATE_MODE = 0x80,
+ PLDM_FWUP_ALREADY_IN_UPDATE_MODE = 0x81,
+ PLDM_FWUP_DATA_OUT_OF_RANGE = 0x82,
+ PLDM_FWUP_INVALID_TRANSFER_LENGTH = 0x83,
+ PLDM_FWUP_INVALID_STATE_FOR_COMMAND = 0x84,
+ PLDM_FWUP_INCOMPLETE_UPDATE = 0x85,
+ PLDM_FWUP_BUSY_IN_BACKGROUND = 0x86,
+ PLDM_FWUP_CANCEL_PENDING = 0x87,
+ PLDM_FWUP_COMMAND_NOT_EXPECTED = 0x87,
+ PLDM_FWUP_RETRY_REQUEST_FW_DATA = 0x89,
+ PLDM_FWUP_UNABLE_TO_INITIATE_UPDATE = 0x8A,
+ PLDM_FWUP_ACTIVATION_NOT_REQUIRED = 0x8B,
+ PLDM_FWUP_SELF_CONTAINED_ACTIVATION_NOT_PERMITTED = 0x8C,
+ PLDM_FWUP_NO_DEVICE_METADATA = 0x8D,
+ PLDM_FWUP_RETRY_REQUEST_UPDATE = 0x8E,
+ PLDM_FWUP_NO_PACKAGE_DATA = 0x8F,
+ PLDM_FWUP_INVALID_TRANSFER_HANDLE = 0x90,
+ PLDM_FWUP_INVALID_TRANSFER_OPERATION_FLAG = 0x91,
+ PLDM_FWUP_ACTIVATE_PENDING_IMAGE_NOT_PERMITTED = 0x92,
+ PLDM_FWUP_PACKAGE_DATA_ERROR = 0x93
+};
+
/** @brief String type values defined in the PLDM firmware update specification
*/
enum pldm_firmware_update_string_type {
@@ -203,6 +228,16 @@
uint8_t comp_image_set_ver_str_len;
} __attribute__((packed));
+/** @struct pldm_request_update_resp
+ *
+ * Structure representing Request Update response
+ */
+struct pldm_request_update_resp {
+ uint8_t completion_code;
+ uint16_t fd_meta_data_len;
+ uint8_t fd_will_send_pkg_data;
+} __attribute__((packed));
+
/** @brief Decode the PLDM package header information
*
* @param[in] data - pointer to package header information
@@ -408,6 +443,22 @@
uint8_t comp_image_set_ver_str_len,
const struct variable_field *comp_img_set_ver_str,
struct pldm_msg *msg, size_t payload_length);
+
+/** @brief Decode a RequestUpdate response message
+ *
+ * @param[in] msg - Response message
+ * @param[in] payload_length - Length of response message payload
+ * @param[out] completion_code - Pointer to hold the completion code
+ * @param[out] fd_meta_data_len - Pointer to hold the length of FD metadata
+ * @param[out] fd_will_send_pkg_data - Pointer to hold information whether FD
+ * will send GetPackageData command
+ * @return pldm_completion_codes
+ */
+int decode_request_update_resp(const struct pldm_msg *msg,
+ size_t payload_length, uint8_t *completion_code,
+ uint16_t *fd_meta_data_len,
+ uint8_t *fd_will_send_pkg_data);
+
#ifdef __cplusplus
}
#endif
diff --git a/libpldm/tests/libpldm_firmware_update_test.cpp b/libpldm/tests/libpldm_firmware_update_test.cpp
index bbd3dfa..ca2b1a4 100644
--- a/libpldm/tests/libpldm_firmware_update_test.cpp
+++ b/libpldm/tests/libpldm_firmware_update_test.cpp
@@ -1393,3 +1393,81 @@
sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
}
+
+TEST(RequestUpdate, goodPathDecodeResponse)
+{
+ constexpr uint16_t fdMetaDataLen = 1024;
+ constexpr uint8_t fdWillSendPkgData = 1;
+ constexpr std::array<uint8_t, hdrSize + sizeof(pldm_request_update_resp)>
+ requestUpdateResponse1{0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01};
+
+ auto responseMsg1 =
+ reinterpret_cast<const pldm_msg*>(requestUpdateResponse1.data());
+ uint8_t outCompletionCode = 0;
+ uint16_t outFdMetaDataLen = 0;
+ uint8_t outFdWillSendPkgData = 0;
+
+ auto rc = decode_request_update_resp(
+ responseMsg1, requestUpdateResponse1.size() - hdrSize,
+ &outCompletionCode, &outFdMetaDataLen, &outFdWillSendPkgData);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(outCompletionCode, PLDM_SUCCESS);
+ EXPECT_EQ(outFdMetaDataLen, fdMetaDataLen);
+ EXPECT_EQ(outFdWillSendPkgData, fdWillSendPkgData);
+
+ outCompletionCode = 0;
+ outFdMetaDataLen = 0;
+ outFdWillSendPkgData = 0;
+
+ constexpr std::array<uint8_t, hdrSize + sizeof(outCompletionCode)>
+ requestUpdateResponse2{0x00, 0x00, 0x00, 0x81};
+ auto responseMsg2 =
+ reinterpret_cast<const pldm_msg*>(requestUpdateResponse2.data());
+ rc = decode_request_update_resp(
+ responseMsg2, requestUpdateResponse2.size() - hdrSize,
+ &outCompletionCode, &outFdMetaDataLen, &outFdWillSendPkgData);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(outCompletionCode, PLDM_FWUP_ALREADY_IN_UPDATE_MODE);
+}
+
+TEST(RequestUpdate, errorPathDecodeResponse)
+{
+ constexpr std::array<uint8_t,
+ hdrSize + sizeof(pldm_request_update_resp) - 1>
+ requestUpdateResponse{0x00, 0x00, 0x00, 0x00, 0x00, 0x04};
+
+ auto responseMsg =
+ reinterpret_cast<const pldm_msg*>(requestUpdateResponse.data());
+ uint8_t outCompletionCode = 0;
+ uint16_t outFdMetaDataLen = 0;
+ uint8_t outFdWillSendPkgData = 0;
+
+ auto rc = decode_request_update_resp(
+ nullptr, requestUpdateResponse.size() - hdrSize, &outCompletionCode,
+ &outFdMetaDataLen, &outFdWillSendPkgData);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_request_update_resp(
+ responseMsg, requestUpdateResponse.size() - hdrSize, nullptr,
+ &outFdMetaDataLen, &outFdWillSendPkgData);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_request_update_resp(
+ responseMsg, requestUpdateResponse.size() - hdrSize, &outCompletionCode,
+ nullptr, &outFdWillSendPkgData);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_request_update_resp(
+ responseMsg, requestUpdateResponse.size() - hdrSize, &outCompletionCode,
+ &outFdMetaDataLen, nullptr);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_request_update_resp(responseMsg, 0, &outCompletionCode,
+ &outFdMetaDataLen, &outFdWillSendPkgData);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = decode_request_update_resp(
+ responseMsg, requestUpdateResponse.size() - hdrSize, &outCompletionCode,
+ &outFdMetaDataLen, &outFdWillSendPkgData);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}