libpldm: Add encode API for RequestUpdate cmd request
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: Id74a65aa5975839c89ca433c16cfc67dcf4890c1
diff --git a/libpldm/firmware_update.c b/libpldm/firmware_update.c
index 23487eb..11007a7 100644
--- a/libpldm/firmware_update.c
+++ b/libpldm/firmware_update.c
@@ -612,3 +612,62 @@
}
return PLDM_SUCCESS;
}
+
+int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
+ uint16_t num_of_comp,
+ uint8_t max_outstanding_transfer_req,
+ uint16_t pkg_data_len,
+ uint8_t comp_image_set_ver_str_type,
+ 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)
+{
+ if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
+ msg == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if (payload_length != sizeof(struct pldm_request_update_req) +
+ comp_img_set_ver_str->length) {
+ return PLDM_ERROR_INVALID_LENGTH;
+ }
+
+ if ((comp_image_set_ver_str_len == 0) ||
+ (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
+ (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ if (!is_string_type_valid(comp_image_set_ver_str_type)) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ struct pldm_header_info header = {0};
+ header.instance = instance_id;
+ header.msg_type = PLDM_REQUEST;
+ header.pldm_type = PLDM_FWUP;
+ header.command = PLDM_REQUEST_UPDATE;
+ uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
+ if (rc) {
+ return rc;
+ }
+
+ struct pldm_request_update_req *request =
+ (struct pldm_request_update_req *)msg->payload;
+
+ request->max_transfer_size = htole32(max_transfer_size);
+ request->num_of_comp = htole16(num_of_comp);
+ request->max_outstanding_transfer_req = max_outstanding_transfer_req;
+ request->pkg_data_len = htole16(pkg_data_len);
+ request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
+ request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
+
+ memcpy(msg->payload + sizeof(struct pldm_request_update_req),
+ comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
+
+ return PLDM_SUCCESS;
+}
\ No newline at end of file
diff --git a/libpldm/firmware_update.h b/libpldm/firmware_update.h
index f7039db..b21eaff 100644
--- a/libpldm/firmware_update.h
+++ b/libpldm/firmware_update.h
@@ -15,12 +15,15 @@
*/
#define PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN 5
#define PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES 0
+#define PLDM_FWUP_BASELINE_TRANSFER_SIZE 32
+#define PLDM_FWUP_MIN_OUTSTANDING_REQ 1
/** @brief PLDM Firmware update commands
*/
enum pldm_firmware_update_commands {
PLDM_QUERY_DEVICE_IDENTIFIERS = 0x01,
- PLDM_GET_FIRMWARE_PARAMETERS = 0x02
+ PLDM_GET_FIRMWARE_PARAMETERS = 0x02,
+ PLDM_REQUEST_UPDATE = 0x10
};
/** @brief String type values defined in the PLDM firmware update specification
@@ -187,6 +190,19 @@
bitfield32_t capabilities_during_update;
} __attribute__((packed));
+/** @struct pldm_request_update_req
+ *
+ * Structure representing fixed part of Request Update request
+ */
+struct pldm_request_update_req {
+ uint32_t max_transfer_size;
+ uint16_t num_of_comp;
+ uint8_t max_outstanding_transfer_req;
+ uint16_t pkg_data_len;
+ uint8_t comp_image_set_ver_str_type;
+ uint8_t comp_image_set_ver_str_len;
+} __attribute__((packed));
+
/** @brief Decode the PLDM package header information
*
* @param[in] data - pointer to package header information
@@ -358,6 +374,40 @@
struct variable_field *active_comp_ver_str,
struct variable_field *pending_comp_ver_str);
+/** @brief Create PLDM request message for RequestUpdate
+ *
+ * @param[in] instance_id - Message's instance id
+ * @param[in] max_transfer_size - Maximum size of the variable payload allowed
+ * to be requested via RequestFirmwareData
+ * command
+ * @param[in] num_of_comp - Total number of components that will be passed to
+ * the FD during the update
+ * @param[in] max_outstanding_transfer_req - Total number of outstanding
+ * RequestFirmwareData
+ * commands that can be sent by the FD
+ * @param[in] pkg_data_len - Value of the FirmwareDevicePackageDataLength field
+ * present in firmware package header
+ * @param[in] comp_image_set_ver_str_type - StringType of
+ * ComponentImageSetVersionString
+ * @param[in] comp_image_set_ver_str_len - The length of the
+ * ComponentImageSetVersionString
+ * @param[in] comp_img_set_ver_str - Component Image Set version information
+ * @param[in,out] msg - Message will be written to this
+ * @param[in] payload_length - Length of request message payload
+ *
+ * @return pldm_completion_codes
+ *
+ * @note Caller is responsible for memory alloc and dealloc of param
+ * 'msg.payload'
+ */
+int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
+ uint16_t num_of_comp,
+ uint8_t max_outstanding_transfer_req,
+ uint16_t pkg_data_len,
+ uint8_t comp_image_set_ver_str_type,
+ 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);
#ifdef __cplusplus
}
#endif
diff --git a/libpldm/tests/libpldm_firmware_update_test.cpp b/libpldm/tests/libpldm_firmware_update_test.cpp
index 444d71c..bbd3dfa 100644
--- a/libpldm/tests/libpldm_firmware_update_test.cpp
+++ b/libpldm/tests/libpldm_firmware_update_test.cpp
@@ -1266,3 +1266,130 @@
entry.data() + pendingCompVerStrPos,
outPendingCompVerStr.length));
}
+
+TEST(RequestUpdate, goodPathEncodeRequest)
+{
+ constexpr uint8_t instanceId = 1;
+ constexpr uint32_t maxTransferSize = 512;
+ constexpr uint16_t numOfComp = 3;
+ constexpr uint8_t maxOutstandingTransferReq = 2;
+ constexpr uint16_t pkgDataLen = 0x1234;
+ constexpr std::string_view compImgSetVerStr = "0penBmcv1.0";
+ constexpr uint8_t compImgSetVerStrLen =
+ static_cast<uint8_t>(compImgSetVerStr.size());
+ variable_field compImgSetVerStrInfo{};
+ compImgSetVerStrInfo.ptr =
+ reinterpret_cast<const uint8_t*>(compImgSetVerStr.data());
+ compImgSetVerStrInfo.length = compImgSetVerStrLen;
+
+ std::array<uint8_t, hdrSize + sizeof(struct pldm_request_update_req) +
+ compImgSetVerStrLen>
+ request{};
+ auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
+
+ auto rc = encode_request_update_req(
+ instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
+ pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen,
+ &compImgSetVerStrInfo, requestMsg,
+ sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+
+ std::array<uint8_t, hdrSize + sizeof(struct pldm_request_update_req) +
+ compImgSetVerStrLen>
+ outRequest{0x81, 0x05, 0x10, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00,
+ 0x02, 0x34, 0x12, 0x01, 0x0b, 0x30, 0x70, 0x65, 0x6e,
+ 0x42, 0x6d, 0x63, 0x76, 0x31, 0x2e, 0x30};
+ EXPECT_EQ(request, outRequest);
+}
+
+TEST(RequestUpdate, errorPathEncodeRequest)
+{
+ constexpr uint8_t instanceId = 1;
+ uint32_t maxTransferSize = 512;
+ constexpr uint16_t numOfComp = 3;
+ uint8_t maxOutstandingTransferReq = 2;
+ constexpr uint16_t pkgDataLen = 0x1234;
+ constexpr std::string_view compImgSetVerStr = "0penBmcv1.0";
+ uint8_t compImgSetVerStrLen = static_cast<uint8_t>(compImgSetVerStr.size());
+ variable_field compImgSetVerStrInfo{};
+ compImgSetVerStrInfo.ptr =
+ reinterpret_cast<const uint8_t*>(compImgSetVerStr.data());
+ compImgSetVerStrInfo.length = compImgSetVerStrLen;
+
+ std::array<uint8_t, hdrSize + sizeof(struct pldm_request_update_req) +
+ compImgSetVerStr.size()>
+ request{};
+ auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
+
+ auto rc = encode_request_update_req(
+ instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
+ pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen, nullptr,
+ requestMsg,
+ sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ compImgSetVerStrInfo.ptr = nullptr;
+ rc = encode_request_update_req(
+ instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
+ pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen,
+ &compImgSetVerStrInfo, requestMsg,
+ sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ compImgSetVerStrInfo.ptr =
+ reinterpret_cast<const uint8_t*>(compImgSetVerStr.data());
+
+ rc = encode_request_update_req(
+ instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
+ pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen,
+ &compImgSetVerStrInfo, nullptr,
+ sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+
+ rc = encode_request_update_req(instanceId, maxTransferSize, numOfComp,
+ maxOutstandingTransferReq, pkgDataLen,
+ PLDM_STR_TYPE_ASCII, compImgSetVerStrLen,
+ &compImgSetVerStrInfo, requestMsg, 0);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+
+ compImgSetVerStrLen = 0;
+ rc = encode_request_update_req(
+ instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
+ pkgDataLen, PLDM_STR_TYPE_ASCII, 0, &compImgSetVerStrInfo, nullptr,
+ sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ compImgSetVerStrLen = static_cast<uint8_t>(compImgSetVerStr.size());
+
+ compImgSetVerStrInfo.length = 0xFFFF;
+ rc = encode_request_update_req(
+ instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
+ pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen,
+ &compImgSetVerStrInfo, nullptr,
+ sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ compImgSetVerStrInfo.length = compImgSetVerStrLen;
+
+ maxTransferSize = PLDM_FWUP_BASELINE_TRANSFER_SIZE - 1;
+ rc = encode_request_update_req(
+ instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
+ pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen,
+ &compImgSetVerStrInfo, nullptr,
+ sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ maxTransferSize = PLDM_FWUP_BASELINE_TRANSFER_SIZE;
+
+ maxOutstandingTransferReq = PLDM_FWUP_MIN_OUTSTANDING_REQ - 1;
+ rc = encode_request_update_req(
+ instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
+ pkgDataLen, PLDM_STR_TYPE_ASCII, compImgSetVerStrLen,
+ &compImgSetVerStrInfo, nullptr,
+ sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+ maxOutstandingTransferReq = PLDM_FWUP_MIN_OUTSTANDING_REQ;
+
+ rc = encode_request_update_req(
+ instanceId, maxTransferSize, numOfComp, maxOutstandingTransferReq,
+ pkgDataLen, PLDM_STR_TYPE_UNKNOWN, compImgSetVerStrLen,
+ &compImgSetVerStrInfo, nullptr,
+ sizeof(struct pldm_request_update_req) + compImgSetVerStrLen);
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}