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 =