dsp: Add FD side firmware_update encode/decode
This implements FD counterparts for firmware update (type 5)
encoding/decoding.
In tests after encoding a message, a subsequent decode is performed and
the outputs are compared. This tests the FD portion of the message
decoding.
Change-Id: I5454acee19588b0679a9b0218588fc4c0a66b01d
Signed-off-by: Matt Johnston <matt@codeconstruct.com.au>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1a17350..af2ec0d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -63,6 +63,8 @@
The change removes redundant APIs in the process.
+9. Add Firmware Device side firmware_update encode/decode functions
+
### Fixed
1. dsp: platform: Fix location of closing paren in overflow detection
diff --git a/include/libpldm/firmware_update.h b/include/libpldm/firmware_update.h
index c818347..1610bd8 100644
--- a/include/libpldm/firmware_update.h
+++ b/include/libpldm/firmware_update.h
@@ -411,6 +411,29 @@
PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED = 1
};
+/* An arbitrary limit, for static storage */
+#define PLDM_FIRMWARE_MAX_STRING 64
+
+/** @struct pldm_firmware_string
+ *
+ * A fixed maximum length PLDM firmware string
+*/
+struct pldm_firmware_string {
+ enum pldm_firmware_update_string_type str_type;
+ uint8_t str_len;
+ uint8_t str_data[PLDM_FIRMWARE_MAX_STRING];
+};
+
+/** @struct pldm_firmware_version
+ *
+ * A PLDM component version
+*/
+struct pldm_firmware_version {
+ uint32_t comparison_stamp;
+ struct pldm_firmware_string str;
+ uint8_t date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN];
+};
+
/** @struct pldm_package_header_information
*
* Structure representing fixed part of package header information
@@ -499,6 +522,18 @@
uint8_t pending_comp_image_set_ver_str_len;
} __attribute__((packed));
+/** @struct pldm_get_firmware_parameters_resp_full
+ *
+ * Structure representing a full GetFirmwareParameters response
+ */
+struct pldm_get_firmware_parameters_resp_full {
+ uint8_t completion_code;
+ bitfield32_t capabilities_during_update;
+ uint16_t comp_count;
+ struct pldm_firmware_string active_comp_image_set_ver_str;
+ struct pldm_firmware_string pending_comp_image_set_ver_str;
+};
+
/** @struct pldm_query_downstream_devices_resp
*
* Structure representing response of QueryDownstreamDevices.
@@ -515,7 +550,7 @@
/** @struct pldm_component_parameter_entry
*
- * Structure representing component parameter table entry.
+ * Structure representing component parameter table entry, as wire format.
*/
struct pldm_component_parameter_entry {
uint16_t comp_classification;
@@ -533,6 +568,24 @@
bitfield32_t capabilities_during_update;
} __attribute__((packed));
+/** @struct pldm_component_parameter_entry_full
+ *
+ * Structure representing component parameter table entry.
+ * This is non-packed (contrast with struct pldm_component_parameter_entry),
+ * with version strings included.
+ */
+struct pldm_component_parameter_entry_full {
+ uint16_t comp_classification;
+ uint16_t comp_identifier;
+ uint8_t comp_classification_index;
+
+ struct pldm_firmware_version active_ver;
+ struct pldm_firmware_version pending_ver;
+
+ bitfield16_t comp_activation_methods;
+ bitfield32_t capabilities_during_update;
+};
+
/** @struct pldm_query_downstream_identifiers_req
*
* Structure for QueryDownstreamIdentifiers request defined in Table 16 -
@@ -801,7 +854,7 @@
/** @struct pldm_request_update_req
*
- * Structure representing fixed part of Request Update request
+ * Structure representing fixed part of Request Update request, as wire format.
*/
struct pldm_request_update_req {
uint32_t max_transfer_size;
@@ -812,6 +865,20 @@
uint8_t comp_image_set_ver_str_len;
} __attribute__((packed));
+/** @struct pldm_request_update_req_full
+ *
+ * Structure representing fixed part of Request Update request, including
+ * version string. This is unpacked (contrast to struct pldm_request_update_req).
+ */
+struct pldm_request_update_req_full {
+ uint32_t max_transfer_size;
+ uint16_t num_of_comp;
+ uint8_t max_outstanding_transfer_req;
+ uint16_t pkg_data_len;
+
+ struct pldm_firmware_string image_set_ver;
+};
+
/** @struct pldm_request_update_resp
*
* Structure representing Request Update response
@@ -824,7 +891,9 @@
/** @struct pldm_pass_component_table_req
*
- * Structure representing PassComponentTable request
+ * Structure representing PassComponentTable request, wire format.
+ * Version string data is not included.
+ * Prefer pldm_pass_component_table_req_full for new uses.
*/
struct pldm_pass_component_table_req {
uint8_t transfer_flag;
@@ -836,6 +905,20 @@
uint8_t comp_ver_str_len;
} __attribute__((packed));
+/** @struct pldm_pass_component_table_req_full
+ *
+ * Structure representing PassComponentTable request, including
+ * version string storage.
+ */
+struct pldm_pass_component_table_req_full {
+ uint8_t transfer_flag;
+ uint16_t comp_classification;
+ uint16_t comp_identifier;
+ uint8_t comp_classification_index;
+ uint32_t comp_comparison_stamp;
+ struct pldm_firmware_string version;
+};
+
/** @struct pldm_pass_component_table_resp
*
* Structure representing PassComponentTable response
@@ -848,7 +931,9 @@
/** @struct pldm_update_component_req
*
- * Structure representing UpdateComponent request
+ * Structure representing UpdateComponent request, wire format.
+ * Version string data is not included.
+ * Prefer pldm_update_component_req_full for new uses.
*/
struct pldm_update_component_req {
uint16_t comp_classification;
@@ -861,6 +946,23 @@
uint8_t comp_ver_str_len;
} __attribute__((packed));
+/** @struct pldm_update_component_req_full
+ *
+ * Structure representing UpdateComponent request, including
+ * version string storage.
+ */
+struct pldm_update_component_req_full {
+ uint16_t comp_classification;
+ uint16_t comp_identifier;
+ uint8_t comp_classification_index;
+
+ uint32_t comp_comparison_stamp;
+ struct pldm_firmware_string version;
+
+ uint32_t comp_image_size;
+ bitfield32_t update_option_flags;
+};
+
/** @struct pldm_update_component_resp
*
* Structure representing UpdateComponent response
@@ -1034,6 +1136,25 @@
size_t payload_length,
struct pldm_msg *msg);
+/** @brief Create a PLDM response message for QueryDeviceIdentifiers
+ *
+ * @param[in] instance_id - Message's instance id
+ * @param[in] descriptor_count - Number of descriptors
+ * @param[in] descriptor - Array of descriptors
+ * @param[in,out] msg - Message will be written to this
+ * @param[in,out] payload_length - Size of the response message payload, updated
+ * with used length.
+ *
+ * @return 0 on success, a negative errno value on failure.
+ *
+ * @note Caller is responsible for memory alloc and dealloc of param
+ * 'msg.payload'
+ */
+int encode_query_device_identifiers_resp(
+ uint8_t instance_id, uint8_t descriptor_count,
+ const struct pldm_descriptor *descriptors, struct pldm_msg *msg,
+ size_t *payload_length);
+
/** @brief Decode QueryDeviceIdentifiers response message
*
* @param[in] msg - Response message
@@ -1105,6 +1226,34 @@
struct variable_field *active_comp_ver_str,
struct variable_field *pending_comp_ver_str);
+/** @brief Encode a GetFirmwareParameters response
+ *
+ * @param[in] instance_id - Message's instance id
+ * @param[in] resp_data - Parameter data
+ * @param[in,out] msg - Message will be written to this
+ * @param[in,out] payload_length - Size of the response message payload, updated
+ * with used length.
+ *
+ * @return 0 on success, a negative errno value on failure.
+ */
+int encode_get_firmware_parameters_resp(
+ uint8_t instance_id,
+ const struct pldm_get_firmware_parameters_resp_full *resp_data,
+ struct pldm_msg *msg, size_t *payload_length);
+
+/** @brief Encode a ComponentParameterTable entry
+ *
+ * @param[in] comp - Component entry
+ * @param[in,out] payload - Message will be written to this
+ * @param[in,out] payload_length - Size of payload, updated
+ * with used length.
+ *
+ * @return 0 on success, a negative errno value on failure.
+ */
+int encode_get_firmware_parameters_resp_comp_entry(
+ const struct pldm_component_parameter_entry_full *comp,
+ uint8_t *payload, size_t *payload_length);
+
/** @brief Create a PLDM request message for QueryDownstreamDevices
*
* @param[in] instance_id - Message's instance id
@@ -1318,7 +1467,7 @@
* @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
+ * RequestFirmwareData
* commands that can be sent by the FD
* @param[in] pkg_data_len - Value of the FirmwareDevicePackageDataLength field
* present in firmware package header
@@ -1344,6 +1493,20 @@
const struct variable_field *comp_img_set_ver_str,
struct pldm_msg *msg, size_t payload_length);
+/** @brief Decode PLDM request message for RequestUpdate
+ *
+ * @param[in] msg - Message
+ * @param[in] payload_length - Length of request message payload
+ * @param[out] req - RequestUpdate request parameters
+ *
+ * @return 0 on success, a negative errno value on failure.
+ *
+ * @note Caller is responsible for memory alloc and dealloc of param
+ * 'msg.payload'
+ */
+int decode_request_update_req(const struct pldm_msg *msg, size_t payload_length,
+ struct pldm_request_update_req_full *req);
+
/** @brief Decode a RequestUpdate response message
*
* @param[in] msg - Response message
@@ -1359,6 +1522,22 @@
uint16_t *fd_meta_data_len,
uint8_t *fd_will_send_pkg_data);
+/** @brief Create PLDM response message for RequestUpdate
+ *
+ * @param[in] instance_id - Message's instance id
+ * @param[in] resp_data - Response data
+ * @param[out] msg - Message will be written to this
+ * @param[inout] payload_length - Length of response message payload
+ *
+ * @return 0 on success, a negative errno value on failure.
+ *
+ * @note Caller is responsible for memory alloc and dealloc of param
+ * 'msg.payload'
+ */
+int encode_request_update_resp(uint8_t instance_id,
+ const struct pldm_request_update_resp *resp_data,
+ struct pldm_msg *msg, size_t *payload_length);
+
/** @brief Create PLDM request message for PassComponentTable
*
* @param[in] instance_id - Message's instance id
@@ -1387,6 +1566,18 @@
const struct variable_field *comp_ver_str, struct pldm_msg *msg,
size_t payload_length);
+/** @brief Decode a PassComponentTable request
+ *
+ * @param[in] msg - PLDM Message
+ * @param[in] payload_length
+ * @param[out] pcomp - Pass Component Table Request
+ *
+ * @return 0 on success, a negative errno value on failure.
+ */
+int decode_pass_component_table_req(
+ const struct pldm_msg *msg, size_t payload_length,
+ struct pldm_pass_component_table_req_full *pcomp);
+
/** @brief Decode PassComponentTable response message
*
* @param[in] msg - Response message
@@ -1403,6 +1594,22 @@
uint8_t *comp_resp,
uint8_t *comp_resp_code);
+/** @brief Encode PassComponentTable response
+ *
+ * @param[in] instance_id - PLDM Instance ID matching the request
+ * @param[in] resp_data - response data
+ * @param[out] msg - Response message
+ * @param[inout] payload_length - Length of msg payload buffer,
+ * will be updated with the written
+ * length on success.
+ *
+ * @return 0 on success, a negative errno value on failure.
+ */
+int encode_pass_component_table_resp(
+ uint8_t instance_id,
+ const struct pldm_pass_component_table_resp *resp_data,
+ struct pldm_msg *msg, size_t *payload_length);
+
/** @brief Create PLDM request message for UpdateComponent
*
* @param[in] instance_id - Message's instance id
@@ -1432,6 +1639,18 @@
uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
struct pldm_msg *msg, size_t payload_length);
+/** @brief Decode UpdateComponent request message
+ *
+ * @param[in] msg - Request message
+ * @param[in] payload_length - Length of request message payload
+ * @param[out] up - UpdateComponent request parameters
+ *
+ * @return 0 on success, a negative errno value on failure.
+ */
+int decode_update_component_req(const struct pldm_msg *msg,
+ size_t payload_length,
+ struct pldm_update_component_req_full *up);
+
/** @brief Decode UpdateComponent response message
*
* @param[in] msg - Response message
@@ -1456,6 +1675,21 @@
bitfield32_t *update_option_flags_enabled,
uint16_t *time_before_req_fw_data);
+/** @brief Encode UpdateComponent response
+ *
+ * @param[in] instance_id - PLDM Instance ID matching the request
+ * @param[in] resp_data - Response data
+ * @param[out] msg - Response message
+ * @param[inout] payload_length - Length of msg payload buffer,
+ * will be updated with the written
+ * length on success.
+ *
+ * @return 0 on success, a negative errno value on failure.
+ */
+int encode_update_component_resp(
+ uint8_t instance_id, const struct pldm_update_component_resp *resp_data,
+ struct pldm_msg *msg, size_t *payload_length);
+
/** @brief Decode RequestFirmwareData request message
*
* @param[in] msg - Request message
@@ -1470,6 +1704,23 @@
size_t payload_length, uint32_t *offset,
uint32_t *length);
+/** @brief Encode RequestFirmwareData request
+ *
+ * @param[in] instance_id - PLDM Instance ID
+ * @param[in] req_params - Request parameters
+ * @param[in] length - firmware data length to request
+ * @param[out] msg - Response message
+ * @param[inout] payload_length - Length of msg payload buffer,
+ * will be updated with the written
+ * length on success.
+ *
+ * @return 0 on success, a negative errno value on failure.
+ */
+int encode_request_firmware_data_req(
+ uint8_t instance_id,
+ const struct pldm_request_firmware_data_req *req_params,
+ struct pldm_msg *msg, size_t *payload_length);
+
/** @brief Create PLDM response message for RequestFirmwareData
*
* The ComponentImagePortion is not encoded in the PLDM response message
@@ -1505,6 +1756,20 @@
size_t payload_length,
uint8_t *transfer_result);
+/** @brief Encode TransferComplete request
+ *
+ * @param[in] instance_id - PLDM Instance ID
+ * @param[in] transfer_result
+ * @param[out] msg - Response message
+ * @param[inout] payload_length - Length of msg payload buffer,
+ * will be updated with the written
+ * length on success.
+ *
+ * @return 0 on success, a negative errno value on failure.
+ */
+int encode_transfer_complete_req(uint8_t instance_id, uint8_t transfer_result,
+ struct pldm_msg *msg, size_t *payload_length);
+
/** @brief Create PLDM response message for TransferComplete
*
* @param[in] instance_id - Message's instance id
@@ -1531,6 +1796,20 @@
int decode_verify_complete_req(const struct pldm_msg *msg,
size_t payload_length, uint8_t *verify_result);
+/** @brief Encode VerifyComplete request
+ *
+ * @param[in] instance_id - PLDM Instance ID
+ * @param[in] verify_result
+ * @param[out] msg - Response message
+ * @param[inout] payload_length - Length of msg payload buffer,
+ * will be updated with the written
+ * length on success.
+ *
+ * @return 0 on success, a negative errno value on failure.
+ */
+int encode_verify_complete_req(uint8_t instance_id, uint8_t verify_result,
+ struct pldm_msg *msg, size_t *payload_length);
+
/** @brief Create PLDM response message for VerifyComplete
*
* @param[in] instance_id - Message's instance id
@@ -1561,6 +1840,21 @@
uint8_t *apply_result,
bitfield16_t *comp_activation_methods_modification);
+/** @brief Encode ApplyComplete request
+ *
+ * @param[in] instance_id - PLDM Instance ID
+ * @param[in] req_data - Request data
+ * @param[out] msg - Request message
+ * @param[inout] payload_length - Length of msg payload buffer,
+ * will be updated with the written
+ * length on success.
+ *
+ * @return 0 on success, a negative errno value on failure.
+ */
+int encode_apply_complete_req(uint8_t instance_id,
+ const struct pldm_apply_complete_req *req_data,
+ struct pldm_msg *msg, size_t *payload_length);
+
/** @brief Create PLDM response message for ApplyComplete
*
* @param[in] instance_id - Message's instance id
@@ -1592,6 +1886,17 @@
bool8_t self_contained_activation_req,
struct pldm_msg *msg, size_t payload_length);
+/** @brief Decode ActivateFirmware request
+ *
+ * @param[in] msg - Request message
+ * @param[in] payload_length - Length of request message payload
+ * @param[out] self_contained
+ *
+ * @return 0 on success, a negative errno value on failure.
+ */
+int decode_activate_firmware_req(const struct pldm_msg *msg,
+ size_t payload_length, bool *self_contained);
+
/** @brief Decode ActivateFirmware response message
*
* @param[in] msg - Response message
@@ -1607,6 +1912,22 @@
uint8_t *completion_code,
uint16_t *estimated_time_activation);
+/** @brief Encode ActivateFirmware response
+ *
+ * @param[in] instance_id - PLDM Instance ID matching the request
+ * @param[in] resp_data - Response data
+ * @param[out] msg - Response message
+ * @param[inout] payload_length - Length of msg payload buffer,
+ * will be updated with the written
+ * length on success.
+ *
+ * @return 0 on success, a negative errno value on failure.
+ */
+int encode_activate_firmware_resp(
+ uint8_t instance_id,
+ const struct pldm_activate_firmware_resp *resp_data,
+ struct pldm_msg *msg, size_t *payload_length);
+
/** @brief Create PLDM request message for GetStatus
*
* @param[in] instance_id - Message's instance id
@@ -1645,6 +1966,21 @@
uint8_t *reason_code,
bitfield32_t *update_option_flags_enabled);
+/** @brief Encode GetStatus response
+ *
+ * @param[in] instance_id - PLDM Instance ID matching the request
+ * @param[in] status - GetStatus response. completion_code must be PLDM_SUCCESS.
+ * @param[out] msg - Response message
+ * @param[inout] payload_length - Length of msg payload buffer,
+ * will be updated with the written
+ * length on success.
+ *
+ * @return 0 on success, a negative errno value on failure.
+ */
+int encode_get_status_resp(uint8_t instance_id,
+ const struct pldm_get_status_resp *status,
+ struct pldm_msg *msg, size_t *payload_length);
+
/** @brief Create PLDM request message for CancelUpdateComponent
*
* @param[in] instance_id - Message's instance id
@@ -1705,6 +2041,21 @@
bool8_t *non_functioning_component_indication,
bitfield64_t *non_functioning_component_bitmap);
+/** @brief Encode CancelUpdate response
+ *
+ * @param[in] instance_id - PLDM Instance ID matching the request
+ * @param[in] resp_data - Response data,
+ * @param[out] msg - Response message
+ * @param[inout] payload_length - Length of msg payload buffer,
+ * will be updated with the written
+ * length on success.
+ *
+ * @return 0 on success, a negative errno value on failure.
+ */
+int encode_cancel_update_resp(uint8_t instance_id,
+ const struct pldm_cancel_update_resp *resp_data,
+ struct pldm_msg *msg, size_t *payload_length);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/dsp/firmware_update.c b/src/dsp/firmware_update.c
index 9254e48..5c57171 100644
--- a/src/dsp/firmware_update.c
+++ b/src/dsp/firmware_update.c
@@ -9,6 +9,8 @@
#include <stdbool.h>
#include <string.h>
+static_assert(PLDM_FIRMWARE_MAX_STRING <= UINT8_MAX, "too large");
+
/** @brief Check whether string type value is valid
*
* @return true if string type value is valid, false if not
@@ -722,6 +724,66 @@
return PLDM_SUCCESS;
}
+LIBPLDM_ABI_TESTING
+int encode_query_device_identifiers_resp(
+ uint8_t instance_id, uint8_t descriptor_count,
+ const struct pldm_descriptor *descriptors, struct pldm_msg *msg,
+ size_t *payload_length)
+{
+ int rc;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (descriptors == NULL || msg == NULL || payload_length == NULL) {
+ return -EINVAL;
+ }
+
+ if (descriptor_count < 1) {
+ return -EINVAL;
+ }
+
+ rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
+ PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
+ if (rc) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ /* Determine total length */
+ uint32_t device_identifiers_len = 0;
+ for (uint8_t i = 0; i < descriptor_count; i++) {
+ const struct pldm_descriptor *d = &descriptors[i];
+ device_identifiers_len +=
+ 2 * sizeof(uint16_t) + d->descriptor_length;
+ }
+
+ pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
+ pldm_msgbuf_insert(buf, device_identifiers_len);
+ pldm_msgbuf_insert(buf, descriptor_count);
+
+ for (uint8_t i = 0; i < descriptor_count; i++) {
+ const struct pldm_descriptor *d = &descriptors[i];
+ pldm_msgbuf_insert(buf, d->descriptor_type);
+ pldm_msgbuf_insert(buf, d->descriptor_length);
+ if (d->descriptor_data == NULL) {
+ return -EINVAL;
+ }
+ rc = pldm_msgbuf_insert_array(
+ buf, d->descriptor_length,
+ (const uint8_t *)d->descriptor_data,
+ d->descriptor_length);
+ if (rc) {
+ return rc;
+ }
+ }
+
+ return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
+}
+
LIBPLDM_ABI_STABLE
int encode_get_firmware_parameters_req(uint8_t instance_id,
size_t payload_length,
@@ -838,6 +900,125 @@
return PLDM_SUCCESS;
}
+LIBPLDM_ABI_TESTING
+int encode_get_firmware_parameters_resp(
+ uint8_t instance_id,
+ const struct pldm_get_firmware_parameters_resp_full *resp_data,
+ struct pldm_msg *msg, size_t *payload_length)
+{
+ int rc;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (resp_data == NULL || msg == NULL || payload_length == NULL) {
+ return -EINVAL;
+ }
+
+ rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
+ PLDM_GET_FIRMWARE_PARAMETERS, msg);
+ if (rc) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_insert(buf, resp_data->completion_code);
+ pldm_msgbuf_insert(buf, resp_data->capabilities_during_update.value);
+ pldm_msgbuf_insert(buf, resp_data->comp_count);
+ pldm_msgbuf_insert(buf,
+ resp_data->active_comp_image_set_ver_str.str_type);
+ pldm_msgbuf_insert(buf,
+ resp_data->active_comp_image_set_ver_str.str_len);
+ pldm_msgbuf_insert(buf,
+ resp_data->pending_comp_image_set_ver_str.str_type);
+ pldm_msgbuf_insert(buf,
+ resp_data->pending_comp_image_set_ver_str.str_len);
+ /* String data appended */
+ rc = pldm_msgbuf_insert_array(
+ buf, resp_data->active_comp_image_set_ver_str.str_len,
+ resp_data->active_comp_image_set_ver_str.str_data,
+ resp_data->active_comp_image_set_ver_str.str_len);
+ if (rc) {
+ return rc;
+ }
+ rc = pldm_msgbuf_insert_array(
+ buf, resp_data->pending_comp_image_set_ver_str.str_len,
+ resp_data->pending_comp_image_set_ver_str.str_data,
+ resp_data->pending_comp_image_set_ver_str.str_len);
+ if (rc) {
+ return rc;
+ }
+
+ /* Further calls to encode_get_firmware_parameters_resp_comp_entry
+ * will populate the remainder */
+
+ return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
+}
+
+LIBPLDM_ABI_TESTING
+int encode_get_firmware_parameters_resp_comp_entry(
+ const struct pldm_component_parameter_entry_full *comp,
+ uint8_t *payload, size_t *payload_length)
+{
+ int rc;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (comp == NULL || payload == NULL || payload_length == NULL) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, payload, *payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_insert(buf, comp->comp_classification);
+ pldm_msgbuf_insert(buf, comp->comp_identifier);
+ pldm_msgbuf_insert(buf, comp->comp_classification_index);
+
+ pldm_msgbuf_insert(buf, comp->active_ver.comparison_stamp);
+ pldm_msgbuf_insert(buf, (uint8_t)comp->active_ver.str.str_type);
+ pldm_msgbuf_insert(buf, comp->active_ver.str.str_len);
+ rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
+ comp->active_ver.date,
+ PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_insert(buf, comp->pending_ver.comparison_stamp);
+ pldm_msgbuf_insert(buf, (uint8_t)comp->pending_ver.str.str_type);
+ pldm_msgbuf_insert(buf, comp->pending_ver.str.str_len);
+ rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
+ comp->pending_ver.date,
+ PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_insert(buf, comp->comp_activation_methods.value);
+ pldm_msgbuf_insert(buf, comp->capabilities_during_update.value);
+
+ rc = pldm_msgbuf_insert_array(buf, comp->active_ver.str.str_len,
+ comp->active_ver.str.str_data,
+ comp->active_ver.str.str_len);
+ if (rc) {
+ return rc;
+ }
+ rc = pldm_msgbuf_insert_array(buf, comp->pending_ver.str.str_len,
+ comp->pending_ver.str.str_data,
+ comp->pending_ver.str.str_len);
+ if (rc) {
+ return rc;
+ }
+
+ return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
+}
+
LIBPLDM_ABI_STABLE
int decode_get_firmware_parameters_resp_comp_entry(
const uint8_t *data, size_t length,
@@ -1359,6 +1540,51 @@
return PLDM_SUCCESS;
}
+LIBPLDM_ABI_TESTING
+int decode_request_update_req(const struct pldm_msg *msg, size_t payload_length,
+ struct pldm_request_update_req_full *req)
+{
+ int rc;
+ uint8_t t;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (msg == NULL || req == NULL) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_extract(buf, req->max_transfer_size);
+ pldm_msgbuf_extract(buf, req->num_of_comp);
+ pldm_msgbuf_extract(buf, req->max_outstanding_transfer_req);
+ pldm_msgbuf_extract(buf, req->pkg_data_len);
+ rc = pldm_msgbuf_extract(buf, t);
+ if (rc) {
+ return rc;
+ }
+ if (t > PLDM_STR_TYPE_UTF_16BE) {
+ return -EBADMSG;
+ }
+ req->image_set_ver.str_type = (enum pldm_firmware_update_string_type)t;
+ pldm_msgbuf_extract(buf, req->image_set_ver.str_len);
+ if (rc) {
+ return rc;
+ }
+
+ rc = pldm_msgbuf_extract_array(buf, req->image_set_ver.str_len,
+ req->image_set_ver.str_data,
+ PLDM_FIRMWARE_MAX_STRING);
+ if (rc) {
+ return rc;
+ }
+
+ return pldm_msgbuf_destroy_consumed(buf);
+}
+
LIBPLDM_ABI_STABLE
int decode_request_update_resp(const struct pldm_msg *msg,
size_t payload_length, uint8_t *completion_code,
@@ -1389,6 +1615,44 @@
return PLDM_SUCCESS;
}
+LIBPLDM_ABI_TESTING
+int encode_request_update_resp(uint8_t instance_id,
+ const struct pldm_request_update_resp *resp_data,
+ struct pldm_msg *msg, size_t *payload_length)
+{
+ int rc;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (msg == NULL || payload_length == NULL) {
+ return -EINVAL;
+ }
+
+ struct pldm_header_info header = {
+ .instance = instance_id,
+ .msg_type = PLDM_RESPONSE,
+ .pldm_type = PLDM_FWUP,
+ .command = PLDM_REQUEST_UPDATE,
+ };
+ rc = pack_pldm_header(&header, &(msg->hdr));
+ if (rc) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
+ pldm_msgbuf_insert(buf, resp_data->fd_meta_data_len);
+ pldm_msgbuf_insert(buf, resp_data->fd_will_send_pkg_data);
+
+ /* TODO: DSP0267 1.3.0 adds GetPackageDataMaximumTransferSize */
+
+ return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
+}
+
LIBPLDM_ABI_STABLE
int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
uint16_t comp_classification,
@@ -1449,6 +1713,52 @@
return PLDM_SUCCESS;
}
+LIBPLDM_ABI_TESTING
+int decode_pass_component_table_req(
+ const struct pldm_msg *msg, size_t payload_length,
+ struct pldm_pass_component_table_req_full *pcomp)
+{
+ int rc;
+ uint8_t t;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (msg == NULL || pcomp == NULL) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_extract(buf, pcomp->transfer_flag);
+ pldm_msgbuf_extract(buf, pcomp->comp_classification);
+ pldm_msgbuf_extract(buf, pcomp->comp_identifier);
+ pldm_msgbuf_extract(buf, pcomp->comp_classification_index);
+ pldm_msgbuf_extract(buf, pcomp->comp_comparison_stamp);
+ rc = pldm_msgbuf_extract(buf, t);
+ if (rc) {
+ return rc;
+ }
+ if (t > PLDM_STR_TYPE_UTF_16BE) {
+ return -EBADMSG;
+ }
+ pcomp->version.str_type = (enum pldm_firmware_update_string_type)t;
+ rc = pldm_msgbuf_extract(buf, pcomp->version.str_len);
+ if (rc) {
+ return rc;
+ }
+ rc = pldm_msgbuf_extract_array(buf, pcomp->version.str_len,
+ pcomp->version.str_data,
+ PLDM_FIRMWARE_MAX_STRING);
+ if (rc) {
+ return rc;
+ }
+
+ return pldm_msgbuf_destroy_consumed(buf);
+}
+
LIBPLDM_ABI_STABLE
int decode_pass_component_table_resp(const struct pldm_msg *msg,
const size_t payload_length,
@@ -1487,6 +1797,38 @@
return PLDM_SUCCESS;
}
+LIBPLDM_ABI_TESTING
+int encode_pass_component_table_resp(
+ uint8_t instance_id,
+ const struct pldm_pass_component_table_resp *resp_data,
+ struct pldm_msg *msg, size_t *payload_length)
+{
+ int rc;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (msg == NULL || payload_length == NULL) {
+ return -EINVAL;
+ }
+
+ rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
+ PLDM_PASS_COMPONENT_TABLE, msg);
+ if (rc) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
+ pldm_msgbuf_insert(buf, resp_data->comp_resp);
+ pldm_msgbuf_insert(buf, resp_data->comp_resp_code);
+
+ return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
+}
+
LIBPLDM_ABI_STABLE
int encode_update_component_req(
uint8_t instance_id, uint16_t comp_classification,
@@ -1546,6 +1888,57 @@
return PLDM_SUCCESS;
}
+LIBPLDM_ABI_TESTING
+int decode_update_component_req(const struct pldm_msg *msg,
+ size_t payload_length,
+ struct pldm_update_component_req_full *up)
+{
+ int rc;
+ uint8_t t;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (msg == NULL || up == NULL) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_extract(buf, up->comp_classification);
+ pldm_msgbuf_extract(buf, up->comp_identifier);
+ pldm_msgbuf_extract(buf, up->comp_classification_index);
+ pldm_msgbuf_extract(buf, up->comp_comparison_stamp);
+ pldm_msgbuf_extract(buf, up->comp_image_size);
+ pldm_msgbuf_extract(buf, up->update_option_flags.value);
+ rc = pldm_msgbuf_extract(buf, t);
+ if (rc) {
+ return rc;
+ }
+ if (t > PLDM_STR_TYPE_UTF_16BE) {
+ return -EBADMSG;
+ }
+ up->version.str_type = (enum pldm_firmware_update_string_type)t;
+ rc = pldm_msgbuf_extract(buf, up->version.str_len);
+ if (rc) {
+ return rc;
+ }
+ rc = pldm_msgbuf_extract_array(buf, up->version.str_len,
+ up->version.str_data,
+ PLDM_FIRMWARE_MAX_STRING);
+ if (rc) {
+ return rc;
+ }
+
+ if (buf->remaining != 0) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
LIBPLDM_ABI_STABLE
int decode_update_component_resp(const struct pldm_msg *msg,
size_t payload_length,
@@ -1594,6 +1987,39 @@
return PLDM_SUCCESS;
}
+LIBPLDM_ABI_TESTING
+int encode_update_component_resp(
+ uint8_t instance_id, const struct pldm_update_component_resp *resp_data,
+ struct pldm_msg *msg, size_t *payload_length)
+{
+ int rc;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (msg == NULL || payload_length == NULL) {
+ return -EINVAL;
+ }
+
+ rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
+ PLDM_UPDATE_COMPONENT, msg);
+ if (rc) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
+ pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp);
+ pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp_code);
+ pldm_msgbuf_insert(buf, resp_data->update_option_flags_enabled.value);
+ pldm_msgbuf_insert(buf, resp_data->time_before_req_fw_data);
+
+ return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
+}
+
LIBPLDM_ABI_STABLE
int decode_request_firmware_data_req(const struct pldm_msg *msg,
size_t payload_length, uint32_t *offset,
@@ -1617,6 +2043,37 @@
return PLDM_SUCCESS;
}
+LIBPLDM_ABI_TESTING
+int encode_request_firmware_data_req(
+ uint8_t instance_id,
+ const struct pldm_request_firmware_data_req *req_params,
+ struct pldm_msg *msg, size_t *payload_length)
+{
+ int rc;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (msg == NULL || payload_length == NULL) {
+ return -EINVAL;
+ }
+
+ rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
+ PLDM_REQUEST_FIRMWARE_DATA, msg);
+ if (rc) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_insert(buf, req_params->offset);
+ pldm_msgbuf_insert(buf, req_params->length);
+
+ return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
+}
+
LIBPLDM_ABI_STABLE
int encode_request_firmware_data_resp(uint8_t instance_id,
uint8_t completion_code,
@@ -1659,6 +2116,37 @@
return PLDM_SUCCESS;
}
+LIBPLDM_ABI_TESTING
+int encode_transfer_complete_req(uint8_t instance_id, uint8_t transfer_result,
+ struct pldm_msg *msg, size_t *payload_length)
+{
+ int rc;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (msg == NULL || payload_length == NULL) {
+ return -EINVAL;
+ }
+
+ rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
+ PLDM_TRANSFER_COMPLETE, msg);
+ if (rc) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ rc = pldm_msgbuf_insert(buf, transfer_result);
+ if (rc) {
+ return rc;
+ }
+
+ return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
+}
+
LIBPLDM_ABI_STABLE
int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
struct pldm_msg *msg, size_t payload_length)
@@ -1702,6 +2190,37 @@
return PLDM_SUCCESS;
}
+LIBPLDM_ABI_TESTING
+int encode_verify_complete_req(uint8_t instance_id, uint8_t verify_result,
+ struct pldm_msg *msg, size_t *payload_length)
+{
+ int rc;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (msg == NULL || payload_length == NULL) {
+ return -EINVAL;
+ }
+
+ rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
+ PLDM_VERIFY_COMPLETE, msg);
+ if (rc) {
+ return EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ rc = pldm_msgbuf_insert(buf, verify_result);
+ if (rc) {
+ return rc;
+ }
+
+ return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
+}
+
LIBPLDM_ABI_STABLE
int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
struct pldm_msg *msg, size_t payload_length)
@@ -1758,6 +2277,37 @@
return PLDM_SUCCESS;
}
+LIBPLDM_ABI_TESTING
+int encode_apply_complete_req(uint8_t instance_id,
+ const struct pldm_apply_complete_req *req_data,
+ struct pldm_msg *msg, size_t *payload_length)
+{
+ int rc;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (msg == NULL || payload_length == NULL) {
+ return -EINVAL;
+ }
+
+ rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
+ PLDM_APPLY_COMPLETE, msg);
+ if (rc) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_insert(buf, req_data->apply_result);
+ pldm_msgbuf_insert(
+ buf, req_data->comp_activation_methods_modification.value);
+
+ return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
+}
+
LIBPLDM_ABI_STABLE
int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
struct pldm_msg *msg, size_t payload_length)
@@ -1785,6 +2335,35 @@
return PLDM_SUCCESS;
}
+LIBPLDM_ABI_TESTING
+int decode_activate_firmware_req(const struct pldm_msg *msg,
+ size_t payload_length, bool *self_contained)
+{
+ int rc;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (msg == NULL || self_contained == NULL) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
+ if (rc) {
+ return 0;
+ }
+
+ uint8_t self_contained_u8 = 0;
+ rc = pldm_msgbuf_extract(buf, self_contained_u8);
+ if (rc) {
+ return rc;
+ }
+ if (buf->remaining != 0) {
+ return -EOVERFLOW;
+ }
+ *self_contained = (bool)self_contained_u8;
+ return 0;
+}
+
LIBPLDM_ABI_STABLE
int encode_activate_firmware_req(uint8_t instance_id,
bool8_t self_contained_activation_req,
@@ -1850,6 +2429,37 @@
return PLDM_SUCCESS;
}
+LIBPLDM_ABI_TESTING
+int encode_activate_firmware_resp(
+ uint8_t instance_id,
+ const struct pldm_activate_firmware_resp *resp_data,
+ struct pldm_msg *msg, size_t *payload_length)
+{
+ int rc;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (msg == NULL || payload_length == NULL) {
+ return -EINVAL;
+ }
+
+ rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
+ PLDM_ACTIVATE_FIRMWARE, msg);
+ if (rc) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
+ pldm_msgbuf_insert(buf, resp_data->estimated_time_activation);
+
+ return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
+}
+
LIBPLDM_ABI_STABLE
int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
size_t payload_length)
@@ -1942,6 +2552,46 @@
return PLDM_SUCCESS;
}
+LIBPLDM_ABI_TESTING
+int encode_get_status_resp(uint8_t instance_id,
+ const struct pldm_get_status_resp *status,
+ struct pldm_msg *msg, size_t *payload_length)
+{
+ int rc;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (status == NULL || msg == NULL || payload_length == NULL) {
+ return -EINVAL;
+ }
+
+ if (status->completion_code != PLDM_SUCCESS) {
+ return -EINVAL;
+ }
+
+ rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
+ PLDM_GET_STATUS, msg);
+ if (rc) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
+ pldm_msgbuf_insert(buf, status->current_state);
+ pldm_msgbuf_insert(buf, status->previous_state);
+ pldm_msgbuf_insert(buf, status->aux_state);
+ pldm_msgbuf_insert(buf, status->aux_state_status);
+ pldm_msgbuf_insert(buf, status->progress_percent);
+ pldm_msgbuf_insert(buf, status->reason_code);
+ pldm_msgbuf_insert(buf, status->update_option_flags_enabled.value);
+
+ return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
+}
+
LIBPLDM_ABI_STABLE
int encode_cancel_update_component_req(uint8_t instance_id,
struct pldm_msg *msg,
@@ -2048,3 +2698,35 @@
return PLDM_SUCCESS;
}
+
+LIBPLDM_ABI_TESTING
+int encode_cancel_update_resp(uint8_t instance_id,
+ const struct pldm_cancel_update_resp *resp_data,
+ struct pldm_msg *msg, size_t *payload_length)
+{
+ int rc;
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (msg == NULL || payload_length == NULL) {
+ return -EINVAL;
+ }
+
+ rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
+ PLDM_CANCEL_UPDATE, msg);
+ if (rc) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
+ pldm_msgbuf_insert(buf,
+ resp_data->non_functioning_component_indication);
+ pldm_msgbuf_insert(buf, resp_data->non_functioning_component_bitmap);
+
+ return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
+}
diff --git a/tests/dsp/firmware_update.cpp b/tests/dsp/firmware_update.cpp
index 6a2ec68..23a5d4f 100644
--- a/tests/dsp/firmware_update.cpp
+++ b/tests/dsp/firmware_update.cpp
@@ -24,6 +24,24 @@
constexpr auto hdrSize = sizeof(pldm_msg_hdr);
+#ifdef LIBPLDM_API_TESTING
+
+static const uint8_t FIXED_INSTANCE_ID = 31;
+
+/* data is a pointer to pldm message response header */
+static void check_response(const void* data, uint8_t command)
+{
+ auto enc = static_cast<const pldm_msg*>(data);
+ EXPECT_EQ(enc->hdr.request, PLDM_RESPONSE);
+ EXPECT_EQ(enc->hdr.type, PLDM_FWUP);
+ EXPECT_EQ(enc->hdr.command, command);
+ EXPECT_EQ(enc->hdr.reserved, 0);
+ EXPECT_EQ(enc->hdr.datagram, 0);
+ EXPECT_EQ(enc->hdr.header_ver, 0);
+ EXPECT_EQ(enc->hdr.instance_id, FIXED_INSTANCE_ID);
+}
+#endif
+
TEST(DecodePackageHeaderInfo, goodPath)
{
// Package header identifier for Version 1.0.x
@@ -858,6 +876,61 @@
responseMsg.end()));
}
+#ifdef LIBPLDM_API_TESTING
+TEST(QueryDeviceIdentifiers, goodPathEncodeResponse)
+{
+ int rc;
+ PLDM_MSG_DEFINE_P(enc, 1000);
+ size_t enc_payload_len = 1000;
+ pldm_descriptor check_desc[] = {
+ {
+ .descriptor_type = PLDM_FWUP_IANA_ENTERPRISE_ID,
+ .descriptor_length = 4,
+ .descriptor_data = "a123",
+ },
+ {
+ .descriptor_type = PLDM_FWUP_VENDOR_DEFINED,
+ .descriptor_length = 3,
+ .descriptor_data = "987",
+ },
+ };
+ rc = encode_query_device_identifiers_resp(FIXED_INSTANCE_ID, 2, check_desc,
+ enc, &enc_payload_len);
+ EXPECT_EQ(rc, 0);
+ EXPECT_THAT(std::span<uint8_t>(enc_buf + hdrSize, enc_payload_len),
+ ElementsAreArray<uint8_t>({
+ // completion code
+ 0x00,
+ // device identifiers length = 15
+ 0x0f,
+ 0x00,
+ 0x00,
+ 0x00,
+ // descriptor count
+ 0x02,
+ // desc 0
+ 0x01,
+ 0x00,
+ 0x04,
+ 0x00,
+ 0x61,
+ 0x31,
+ 0x32,
+ 0x33,
+ // desc 1
+ 0xff,
+ 0xff,
+ 0x03,
+ 0x00,
+ 0x39,
+ 0x38,
+ 0x37,
+ }));
+
+ check_response(enc, PLDM_QUERY_DEVICE_IDENTIFIERS);
+}
+#endif
+
TEST(GetFirmwareParameters, goodPathEncodeRequest)
{
std::array<uint8_t, sizeof(pldm_msg_hdr)> requestMsg{};
@@ -1221,6 +1294,7 @@
constexpr uint16_t compClassification = 0x0a0b;
// Random value for component classification
constexpr uint16_t compIdentifier = 0x0c0d;
+ constexpr uint16_t compClassificationIndex = 0xf;
// Random value for component classification
constexpr uint32_t timestamp = 0x12345678;
// Random value for component activation methods
@@ -1243,7 +1317,7 @@
inEntry->comp_classification = htole16(compClassification);
inEntry->comp_identifier = htole16(compIdentifier);
- inEntry->comp_classification_index = 0x0f;
+ inEntry->comp_classification_index = compClassificationIndex;
inEntry->active_comp_comparison_stamp = htole32(timestamp);
inEntry->active_comp_ver_str_type = 1;
inEntry->active_comp_ver_str_len = activeCompVerStrLen;
@@ -1305,6 +1379,48 @@
EXPECT_EQ(0, memcmp(outPendingCompVerStr.ptr,
entry.data() + pendingCompVerStrPos,
outPendingCompVerStr.length));
+
+#ifdef LIBPLDM_API_TESTING
+ /* Check the roundtrip matches */
+ std::vector<uint8_t> enc_data(1000);
+ size_t enc_payload_len = enc_data.size();
+ struct pldm_component_parameter_entry_full entryFull = {
+ .comp_classification = compClassification,
+ .comp_identifier = compIdentifier,
+ .comp_classification_index = compClassificationIndex,
+ .active_ver =
+ {
+ .comparison_stamp = 0x12345678,
+ .str = {.str_type = PLDM_STR_TYPE_ASCII,
+ .str_len = activeCompVerStrLen,
+ .str_data = {}},
+ .date = {},
+ },
+ .pending_ver =
+ {
+ .comparison_stamp = 0x12345678,
+ .str = {.str_type = PLDM_STR_TYPE_ASCII,
+ .str_len = pendingCompVerStrLen,
+ .str_data = {}},
+ .date = {},
+ },
+ .comp_activation_methods = inEntry->comp_activation_methods,
+ .capabilities_during_update = inEntry->capabilities_during_update,
+ };
+ // Fill strings
+ std::fill_n(entryFull.active_ver.str.str_data, activeCompVerStrLen, 0xaa);
+ std::fill_n(entryFull.pending_ver.str.str_data, pendingCompVerStrLen, 0xbb);
+ std::fill_n(entryFull.active_ver.date, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
+ 0xff);
+ std::fill_n(entryFull.pending_ver.date,
+ PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 0xff);
+
+ rc = encode_get_firmware_parameters_resp_comp_entry(
+ &entryFull, enc_data.data(), &enc_payload_len);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(enc_payload_len, entryLength);
+ EXPECT_TRUE(std::equal(entry.begin(), entry.end(), enc_data.begin()));
+#endif
}
#ifdef LIBPLDM_API_TESTING
@@ -2675,6 +2791,7 @@
TEST(RequestUpdate, goodPathDecodeResponse)
{
+ /* Test a success completion code */
constexpr uint16_t fdMetaDataLen = 1024;
constexpr uint8_t fdWillSendPkgData = 1;
constexpr std::array<uint8_t, hdrSize + sizeof(pldm_request_update_resp)>
@@ -2695,6 +2812,25 @@
EXPECT_EQ(outFdMetaDataLen, fdMetaDataLen);
EXPECT_EQ(outFdWillSendPkgData, fdWillSendPkgData);
+#ifdef LIBPLDM_API_TESTING
+ /* Check the success roundtrip matches */
+ PLDM_MSG_DEFINE_P(enc, 1000);
+ size_t enc_payload_len = 1000;
+ const struct pldm_request_update_resp resp_data = {
+ .completion_code = PLDM_SUCCESS,
+ .fd_meta_data_len = outFdMetaDataLen,
+ .fd_will_send_pkg_data = outFdWillSendPkgData,
+ };
+ rc = encode_request_update_resp(FIXED_INSTANCE_ID, &resp_data, enc,
+ &enc_payload_len);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(enc_payload_len + hdrSize, requestUpdateResponse1.size());
+ EXPECT_TRUE(std::equal(requestUpdateResponse1.begin() + hdrSize,
+ requestUpdateResponse1.end(), enc_buf + hdrSize));
+ check_response(enc, PLDM_REQUEST_UPDATE);
+#endif
+
+ /* Test a failure completion code */
outCompletionCode = 0;
outFdMetaDataLen = 0;
outFdWillSendPkgData = 0;
@@ -2786,6 +2922,27 @@
0x78, 0x56, 0x34, 0x12, 0x01, 0x0b, 0x30, 0x70, 0x65,
0x6e, 0x42, 0x6d, 0x63, 0x76, 0x31, 0x2e, 0x31};
EXPECT_EQ(request, outRequest);
+
+#ifdef LIBPLDM_API_TESTING
+ /* Check the roundtrip */
+ struct pldm_pass_component_table_req_full req;
+ PLDM_MSG_DEFINE_P(dec, outRequest.size());
+ std::copy(outRequest.begin(), outRequest.end(), dec_buf);
+ rc =
+ decode_pass_component_table_req(dec, outRequest.size() - hdrSize, &req);
+ ASSERT_EQ(rc, 0);
+
+ EXPECT_EQ(req.transfer_flag, PLDM_START_AND_END);
+ EXPECT_EQ(req.comp_classification, PLDM_COMP_FIRMWARE);
+ EXPECT_EQ(req.comp_identifier, compIdentifier);
+ EXPECT_EQ(req.comp_classification_index, compClassificationIndex);
+ EXPECT_EQ(req.comp_comparison_stamp, compComparisonStamp);
+ EXPECT_EQ(req.version.str_type, PLDM_STR_TYPE_ASCII);
+ EXPECT_EQ(req.version.str_len, compVerStrLen);
+ EXPECT_TRUE(std::equal(req.version.str_data,
+ req.version.str_data + req.version.str_len,
+ compVerStr.data()));
+#endif
}
TEST(PassComponentTable, errorPathEncodeRequest)
@@ -3030,6 +3187,27 @@
0x00, 0x00, 0x01, 0x0b, 0x4f, 0x70, 0x65, 0x6e, 0x42,
0x6d, 0x63, 0x76, 0x32, 0x2e, 0x32};
EXPECT_EQ(request, outRequest);
+
+#ifdef LIBPLDM_API_TESTING
+ /* Check the roundtrip */
+ struct pldm_update_component_req_full req;
+ PLDM_MSG_DEFINE_P(dec, outRequest.size());
+ std::copy(outRequest.begin(), outRequest.end(), dec_buf);
+ rc = decode_update_component_req(dec, outRequest.size() - hdrSize, &req);
+ ASSERT_EQ(rc, 0);
+
+ EXPECT_EQ(req.comp_classification, PLDM_COMP_FIRMWARE);
+ EXPECT_EQ(req.comp_identifier, compIdentifier);
+ EXPECT_EQ(req.comp_classification_index, compClassificationIndex);
+ EXPECT_EQ(req.comp_comparison_stamp, compComparisonStamp);
+ EXPECT_EQ(req.comp_image_size, compImageSize);
+ EXPECT_EQ(req.update_option_flags.value, updateOptionFlags.value);
+ EXPECT_EQ(req.version.str_type, PLDM_STR_TYPE_ASCII);
+ EXPECT_EQ(req.version.str_len, compVerStrLen);
+ EXPECT_TRUE(std::equal(req.version.str_data,
+ req.version.str_data + req.version.str_len,
+ compVerStr.data()));
+#endif
}
TEST(UpdateComponent, errorPathEncodeRequest)
@@ -3872,6 +4050,30 @@
EXPECT_EQ(reasonCode, PLDM_FD_TIMEOUT_DOWNLOAD);
EXPECT_EQ(updateOptionFlagsEnabled.value, updateOptionFlagsEnabled2);
+#ifdef LIBPLDM_API_TESTING
+ /* Check the roundtrip */
+ PLDM_MSG_DEFINE_P(enc, 1000);
+ size_t enc_payload_len = 1000;
+ const struct pldm_get_status_resp status_enc = {
+ .completion_code = PLDM_SUCCESS,
+ .current_state = currentState,
+ .previous_state = previousState,
+ .aux_state = auxState,
+ .aux_state_status = auxStateStatus,
+ .progress_percent = progressPercent,
+ .reason_code = reasonCode,
+ .update_option_flags_enabled = updateOptionFlagsEnabled,
+ };
+ rc = encode_get_status_resp(FIXED_INSTANCE_ID, &status_enc, enc,
+ &enc_payload_len);
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(enc_payload_len + hdrSize, getStatusResponse2.size());
+ EXPECT_TRUE(std::equal(getStatusResponse2.begin() + hdrSize,
+ getStatusResponse2.end(), enc_buf + hdrSize));
+ check_response(enc, PLDM_GET_STATUS);
+#endif
+
+ /* Check a not-ready completion code */
constexpr std::array<uint8_t, hdrSize + sizeof(completionCode)>
getStatusResponse3{0x00, 0x00, 0x00, 0x04};
auto responseMsg3 =