xref: /openbmc/libpldm/src/dsp/firmware_update.c (revision e5c3f1483ab0c9ea0013ad3d0211ad958a8034d5)
1  /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2  #include "api.h"
3  #include "dsp/base.h"
4  #include "msgbuf.h"
5  #include <libpldm/firmware_update.h>
6  #include <libpldm/utils.h>
7  
8  #include <endian.h>
9  #include <stdbool.h>
10  #include <string.h>
11  
12  static_assert(PLDM_FIRMWARE_MAX_STRING <= UINT8_MAX, "too large");
13  
14  /** @brief Check whether string type value is valid
15   *
16   *  @return true if string type value is valid, false if not
17   */
is_string_type_valid(uint8_t string_type)18  static bool is_string_type_valid(uint8_t string_type)
19  {
20  	switch (string_type) {
21  	case PLDM_STR_TYPE_UNKNOWN:
22  		return false;
23  	case PLDM_STR_TYPE_ASCII:
24  	case PLDM_STR_TYPE_UTF_8:
25  	case PLDM_STR_TYPE_UTF_16:
26  	case PLDM_STR_TYPE_UTF_16LE:
27  	case PLDM_STR_TYPE_UTF_16BE:
28  		return true;
29  	default:
30  		return false;
31  	}
32  }
33  
34  /** @brief Return the length of the descriptor type described in firmware update
35   *         specification
36   *
37   *  @return length of the descriptor type if descriptor type is valid else
38   *          return 0
39   */
get_descriptor_type_length(uint16_t descriptor_type)40  static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
41  {
42  	switch (descriptor_type) {
43  	case PLDM_FWUP_PCI_VENDOR_ID:
44  		return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
45  	case PLDM_FWUP_IANA_ENTERPRISE_ID:
46  		return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
47  	case PLDM_FWUP_UUID:
48  		return PLDM_FWUP_UUID_LENGTH;
49  	case PLDM_FWUP_PNP_VENDOR_ID:
50  		return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
51  	case PLDM_FWUP_ACPI_VENDOR_ID:
52  		return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
53  	case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
54  		return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
55  	case PLDM_FWUP_SCSI_VENDOR_ID:
56  		return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
57  	case PLDM_FWUP_PCI_DEVICE_ID:
58  		return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
59  	case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
60  		return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
61  	case PLDM_FWUP_PCI_SUBSYSTEM_ID:
62  		return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
63  	case PLDM_FWUP_PCI_REVISION_ID:
64  		return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
65  	case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
66  		return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
67  	case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
68  		return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
69  	case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
70  		return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
71  	case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
72  		return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
73  	case PLDM_FWUP_SCSI_PRODUCT_ID:
74  		return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
75  	case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
76  		return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
77  	default:
78  		return 0;
79  	}
80  }
81  
is_downstream_device_update_support_valid(uint8_t resp)82  static bool is_downstream_device_update_support_valid(uint8_t resp)
83  {
84  	switch (resp) {
85  	case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED:
86  	case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED:
87  		return true;
88  	default:
89  		return false;
90  	}
91  }
92  
93  static bool
is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag)94  is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag)
95  {
96  	switch (transfer_op_flag) {
97  	case PLDM_GET_NEXTPART:
98  	case PLDM_GET_FIRSTPART:
99  		return true;
100  	default:
101  		return false;
102  	}
103  }
104  
105  /** @brief Check whether ComponentResponse is valid
106   *
107   *  @return true if ComponentResponse is valid, false if not
108   */
is_comp_resp_valid(uint8_t comp_resp)109  static bool is_comp_resp_valid(uint8_t comp_resp)
110  {
111  	switch (comp_resp) {
112  	case PLDM_CR_COMP_CAN_BE_UPDATED:
113  	case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
114  		return true;
115  
116  	default:
117  		return false;
118  	}
119  }
120  
121  /** @brief Check whether ComponentResponseCode is valid
122   *
123   *  @return true if ComponentResponseCode is valid, false if not
124   */
is_comp_resp_code_valid(uint8_t comp_resp_code)125  static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
126  {
127  	switch (comp_resp_code) {
128  	case PLDM_CRC_COMP_CAN_BE_UPDATED:
129  	case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
130  	case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
131  	case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
132  	case PLDM_CRC_COMP_CONFLICT:
133  	case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
134  	case PLDM_CRC_COMP_NOT_SUPPORTED:
135  	case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
136  	case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
137  	case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
138  	case PLDM_CRC_COMP_VER_STR_IDENTICAL:
139  	case PLDM_CRC_COMP_VER_STR_LOWER:
140  		return true;
141  
142  	default:
143  		if (comp_resp_code >=
144  			    PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
145  		    comp_resp_code <=
146  			    PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
147  			return true;
148  		}
149  		return false;
150  	}
151  }
152  
153  /** @brief Check whether ComponentCompatibilityResponse is valid
154   *
155   *  @return true if ComponentCompatibilityResponse is valid, false if not
156   */
is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)157  static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
158  {
159  	switch (comp_compatibility_resp) {
160  	case PLDM_CCR_COMP_CAN_BE_UPDATED:
161  	case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
162  		return true;
163  
164  	default:
165  		return false;
166  	}
167  }
168  
169  /** @brief Check whether ComponentCompatibilityResponse Code is valid
170   *
171   *  @return true if ComponentCompatibilityResponse Code is valid, false if not
172   */
173  static bool
is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)174  is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
175  {
176  	switch (comp_compatibility_resp_code) {
177  	case PLDM_CCRC_NO_RESPONSE_CODE:
178  	case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
179  	case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
180  	case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
181  	case PLDM_CCRC_COMP_CONFLICT:
182  	case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
183  	case PLDM_CCRC_COMP_NOT_SUPPORTED:
184  	case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
185  	case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
186  	case PLDM_CCRC_COMP_INFO_NO_MATCH:
187  	case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
188  	case PLDM_CCRC_COMP_VER_STR_LOWER:
189  		return true;
190  
191  	default:
192  		if (comp_compatibility_resp_code >=
193  			    PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
194  		    comp_compatibility_resp_code <=
195  			    PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
196  			return true;
197  		}
198  		return false;
199  	}
200  }
201  
202  /** @brief Check whether SelfContainedActivationRequest is valid
203   *
204   *  @return true if SelfContainedActivationRequest is valid, false if not
205   */
206  static bool
is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)207  is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
208  {
209  	switch (self_contained_activation_req) {
210  	case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
211  	case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
212  		return true;
213  
214  	default:
215  		return false;
216  	}
217  }
218  
219  /** @brief Check if current or previous status in GetStatus command response is
220   *         valid
221   *
222   *	@param[in] state - current or previous different state machine state of
223   *                     the FD
224   *	@return true if state is valid, false if not
225   */
is_state_valid(uint8_t state)226  static bool is_state_valid(uint8_t state)
227  {
228  	switch (state) {
229  	case PLDM_FD_STATE_IDLE:
230  	case PLDM_FD_STATE_LEARN_COMPONENTS:
231  	case PLDM_FD_STATE_READY_XFER:
232  	case PLDM_FD_STATE_DOWNLOAD:
233  	case PLDM_FD_STATE_VERIFY:
234  	case PLDM_FD_STATE_APPLY:
235  	case PLDM_FD_STATE_ACTIVATE:
236  		return true;
237  
238  	default:
239  		return false;
240  	}
241  }
242  
243  /** @brief Check if aux state in GetStatus command response is valid
244   *
245   *  @param[in] aux_state - provides additional information to the UA to describe
246   *                         the current operation state of the FD/FDP
247   *
248   *	@return true if aux state is valid, false if not
249   */
is_aux_state_valid(uint8_t aux_state)250  static bool is_aux_state_valid(uint8_t aux_state)
251  {
252  	switch (aux_state) {
253  	case PLDM_FD_OPERATION_IN_PROGRESS:
254  	case PLDM_FD_OPERATION_SUCCESSFUL:
255  	case PLDM_FD_OPERATION_FAILED:
256  	case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER:
257  		return true;
258  
259  	default:
260  		return false;
261  	}
262  }
263  
264  /** @brief Check if aux state status in GetStatus command response is valid
265   *
266   *	@param[in] aux_state_status - aux state status
267   *
268   *	@return true if aux state status is valid, false if not
269   */
is_aux_state_status_valid(uint8_t aux_state_status)270  static bool is_aux_state_status_valid(uint8_t aux_state_status)
271  {
272  	if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS ||
273  	    aux_state_status == PLDM_FD_TIMEOUT ||
274  	    aux_state_status == PLDM_FD_GENERIC_ERROR ||
275  	    (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
276  	     aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) {
277  		return true;
278  	}
279  
280  	return false;
281  }
282  
283  /** @brief Check if reason code in GetStatus command response is valid
284   *
285   *	@param[in] reason_code - provides the reason for why the current state
286   *                           entered the IDLE state
287   *
288   *	@return true if reason code is valid, false if not
289   */
is_reason_code_valid(uint8_t reason_code)290  static bool is_reason_code_valid(uint8_t reason_code)
291  {
292  	switch (reason_code) {
293  	case PLDM_FD_INITIALIZATION:
294  	case PLDM_FD_ACTIVATE_FW:
295  	case PLDM_FD_CANCEL_UPDATE:
296  	case PLDM_FD_TIMEOUT_LEARN_COMPONENT:
297  	case PLDM_FD_TIMEOUT_READY_XFER:
298  	case PLDM_FD_TIMEOUT_DOWNLOAD:
299  	case PLDM_FD_TIMEOUT_VERIFY:
300  	case PLDM_FD_TIMEOUT_APPLY:
301  		return true;
302  
303  	default:
304  		if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) {
305  			return true;
306  		}
307  		return false;
308  	}
309  }
310  
311  /** @brief Check if non functioning component indication in CancelUpdate
312   *         response is valid
313   *
314   *  @return true if non functioning component indication is valid, false if not
315   */
is_non_functioning_component_indication_valid(bool8_t non_functioning_component_indication)316  static bool is_non_functioning_component_indication_valid(
317  	bool8_t non_functioning_component_indication)
318  {
319  	switch (non_functioning_component_indication) {
320  	case PLDM_FWUP_COMPONENTS_FUNCTIONING:
321  	case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING:
322  		return true;
323  
324  	default:
325  		return false;
326  	}
327  }
328  
329  LIBPLDM_ABI_STABLE
decode_pldm_package_header_info(const uint8_t * data,size_t length,struct pldm_package_header_information * package_header_info,struct variable_field * package_version_str)330  int decode_pldm_package_header_info(
331  	const uint8_t *data, size_t length,
332  	struct pldm_package_header_information *package_header_info,
333  	struct variable_field *package_version_str)
334  {
335  	if (data == NULL || package_header_info == NULL ||
336  	    package_version_str == NULL) {
337  		return PLDM_ERROR_INVALID_DATA;
338  	}
339  
340  	if (length < sizeof(struct pldm_package_header_information)) {
341  		return PLDM_ERROR_INVALID_LENGTH;
342  	}
343  
344  	struct pldm_package_header_information *data_header =
345  		(struct pldm_package_header_information *)(data);
346  
347  	if (!is_string_type_valid(data_header->package_version_string_type) ||
348  	    (data_header->package_version_string_length == 0)) {
349  		return PLDM_ERROR_INVALID_DATA;
350  	}
351  
352  	if (length < sizeof(struct pldm_package_header_information) +
353  			     data_header->package_version_string_length) {
354  		return PLDM_ERROR_INVALID_LENGTH;
355  	}
356  
357  	if ((data_header->component_bitmap_bit_length %
358  	     PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
359  		return PLDM_ERROR_INVALID_DATA;
360  	}
361  
362  	memcpy(package_header_info->uuid, data_header->uuid,
363  	       sizeof(data_header->uuid));
364  	package_header_info->package_header_format_version =
365  		data_header->package_header_format_version;
366  	package_header_info->package_header_size =
367  		le16toh(data_header->package_header_size);
368  	memcpy(package_header_info->package_release_date_time,
369  	       data_header->package_release_date_time,
370  	       sizeof(data_header->package_release_date_time));
371  	package_header_info->component_bitmap_bit_length =
372  		le16toh(data_header->component_bitmap_bit_length);
373  	package_header_info->package_version_string_type =
374  		data_header->package_version_string_type;
375  	package_header_info->package_version_string_length =
376  		data_header->package_version_string_length;
377  	package_version_str->ptr =
378  		data + sizeof(struct pldm_package_header_information);
379  	package_version_str->length =
380  		package_header_info->package_version_string_length;
381  
382  	return PLDM_SUCCESS;
383  }
384  
385  LIBPLDM_ABI_STABLE
decode_firmware_device_id_record(const uint8_t * data,size_t length,uint16_t component_bitmap_bit_length,struct pldm_firmware_device_id_record * fw_device_id_record,struct variable_field * applicable_components,struct variable_field * comp_image_set_version_str,struct variable_field * record_descriptors,struct variable_field * fw_device_pkg_data)386  int decode_firmware_device_id_record(
387  	const uint8_t *data, size_t length,
388  	uint16_t component_bitmap_bit_length,
389  	struct pldm_firmware_device_id_record *fw_device_id_record,
390  	struct variable_field *applicable_components,
391  	struct variable_field *comp_image_set_version_str,
392  	struct variable_field *record_descriptors,
393  	struct variable_field *fw_device_pkg_data)
394  {
395  	if (data == NULL || fw_device_id_record == NULL ||
396  	    applicable_components == NULL ||
397  	    comp_image_set_version_str == NULL || record_descriptors == NULL ||
398  	    fw_device_pkg_data == NULL) {
399  		return PLDM_ERROR_INVALID_DATA;
400  	}
401  
402  	if (length < sizeof(struct pldm_firmware_device_id_record)) {
403  		return PLDM_ERROR_INVALID_LENGTH;
404  	}
405  
406  	if ((component_bitmap_bit_length %
407  	     PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
408  		return PLDM_ERROR_INVALID_DATA;
409  	}
410  
411  	struct pldm_firmware_device_id_record *data_record =
412  		(struct pldm_firmware_device_id_record *)(data);
413  
414  	if (!is_string_type_valid(
415  		    data_record->comp_image_set_version_string_type) ||
416  	    (data_record->comp_image_set_version_string_length == 0)) {
417  		return PLDM_ERROR_INVALID_DATA;
418  	}
419  
420  	fw_device_id_record->record_length =
421  		le16toh(data_record->record_length);
422  	fw_device_id_record->descriptor_count = data_record->descriptor_count;
423  	fw_device_id_record->device_update_option_flags.value =
424  		le32toh(data_record->device_update_option_flags.value);
425  	fw_device_id_record->comp_image_set_version_string_type =
426  		data_record->comp_image_set_version_string_type;
427  	fw_device_id_record->comp_image_set_version_string_length =
428  		data_record->comp_image_set_version_string_length;
429  	fw_device_id_record->fw_device_pkg_data_length =
430  		le16toh(data_record->fw_device_pkg_data_length);
431  
432  	if (length < fw_device_id_record->record_length) {
433  		return PLDM_ERROR_INVALID_LENGTH;
434  	}
435  
436  	uint16_t applicable_components_length =
437  		component_bitmap_bit_length /
438  		PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
439  	size_t calc_min_record_length =
440  		sizeof(struct pldm_firmware_device_id_record) +
441  		applicable_components_length +
442  		data_record->comp_image_set_version_string_length +
443  		PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
444  		fw_device_id_record->fw_device_pkg_data_length;
445  
446  	if (fw_device_id_record->record_length < calc_min_record_length) {
447  		return PLDM_ERROR_INVALID_LENGTH;
448  	}
449  
450  	applicable_components->ptr =
451  		data + sizeof(struct pldm_firmware_device_id_record);
452  	applicable_components->length = applicable_components_length;
453  
454  	comp_image_set_version_str->ptr =
455  		applicable_components->ptr + applicable_components->length;
456  	comp_image_set_version_str->length =
457  		fw_device_id_record->comp_image_set_version_string_length;
458  
459  	record_descriptors->ptr = comp_image_set_version_str->ptr +
460  				  comp_image_set_version_str->length;
461  	record_descriptors->length =
462  		fw_device_id_record->record_length -
463  		sizeof(struct pldm_firmware_device_id_record) -
464  		applicable_components_length -
465  		fw_device_id_record->comp_image_set_version_string_length -
466  		fw_device_id_record->fw_device_pkg_data_length;
467  
468  	if (fw_device_id_record->fw_device_pkg_data_length) {
469  		fw_device_pkg_data->ptr =
470  			record_descriptors->ptr + record_descriptors->length;
471  		fw_device_pkg_data->length =
472  			fw_device_id_record->fw_device_pkg_data_length;
473  	}
474  
475  	return PLDM_SUCCESS;
476  }
477  
478  LIBPLDM_ABI_STABLE
decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter * iter,struct pldm_descriptor * desc)479  int decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter *iter,
480  				     struct pldm_descriptor *desc)
481  {
482  	struct pldm_msgbuf _buf;
483  	struct pldm_msgbuf *buf = &_buf;
484  	int rc;
485  
486  	if (!iter || !iter->field || !desc) {
487  		return -EINVAL;
488  	}
489  
490  	rc = pldm_msgbuf_init_errno(buf, PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN,
491  				    iter->field->ptr, iter->field->length);
492  	if (rc) {
493  		return rc;
494  	}
495  
496  	pldm_msgbuf_extract(buf, desc->descriptor_type);
497  	rc = pldm_msgbuf_extract(buf, desc->descriptor_length);
498  	if (rc) {
499  		return rc;
500  	}
501  
502  	desc->descriptor_data = NULL;
503  	pldm_msgbuf_span_required(buf, desc->descriptor_length,
504  				  (void **)&desc->descriptor_data);
505  	iter->field->ptr = NULL;
506  	pldm_msgbuf_span_remaining(buf, (void **)&iter->field->ptr,
507  				   &iter->field->length);
508  
509  	return pldm_msgbuf_destroy(buf);
510  }
511  
512  LIBPLDM_ABI_STABLE
decode_descriptor_type_length_value(const uint8_t * data,size_t length,uint16_t * descriptor_type,struct variable_field * descriptor_data)513  int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
514  					uint16_t *descriptor_type,
515  					struct variable_field *descriptor_data)
516  {
517  	uint16_t descriptor_length = 0;
518  
519  	if (data == NULL || descriptor_type == NULL ||
520  	    descriptor_data == NULL) {
521  		return PLDM_ERROR_INVALID_DATA;
522  	}
523  
524  	if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
525  		return PLDM_ERROR_INVALID_LENGTH;
526  	}
527  
528  	struct pldm_descriptor_tlv *entry =
529  		(struct pldm_descriptor_tlv *)(data);
530  
531  	*descriptor_type = le16toh(entry->descriptor_type);
532  	descriptor_length = le16toh(entry->descriptor_length);
533  	if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
534  		if (descriptor_length !=
535  		    get_descriptor_type_length(*descriptor_type)) {
536  			return PLDM_ERROR_INVALID_LENGTH;
537  		}
538  	}
539  
540  	if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
541  		      descriptor_length)) {
542  		return PLDM_ERROR_INVALID_LENGTH;
543  	}
544  
545  	descriptor_data->ptr = entry->descriptor_data;
546  	descriptor_data->length = descriptor_length;
547  
548  	return PLDM_SUCCESS;
549  }
550  
551  LIBPLDM_ABI_STABLE
decode_vendor_defined_descriptor_value(const uint8_t * data,size_t length,uint8_t * descriptor_title_str_type,struct variable_field * descriptor_title_str,struct variable_field * descriptor_data)552  int decode_vendor_defined_descriptor_value(
553  	const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
554  	struct variable_field *descriptor_title_str,
555  	struct variable_field *descriptor_data)
556  {
557  	if (data == NULL || descriptor_title_str_type == NULL ||
558  	    descriptor_title_str == NULL || descriptor_data == NULL) {
559  		return PLDM_ERROR_INVALID_DATA;
560  	}
561  
562  	if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
563  		return PLDM_ERROR_INVALID_LENGTH;
564  	}
565  
566  	struct pldm_vendor_defined_descriptor_title_data *entry =
567  		(struct pldm_vendor_defined_descriptor_title_data *)(data);
568  	if (!is_string_type_valid(
569  		    entry->vendor_defined_descriptor_title_str_type) ||
570  	    (entry->vendor_defined_descriptor_title_str_len == 0)) {
571  		return PLDM_ERROR_INVALID_DATA;
572  	}
573  
574  	// Assuming at least 1 byte of VendorDefinedDescriptorData
575  	if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
576  		      entry->vendor_defined_descriptor_title_str_len)) {
577  		return PLDM_ERROR_INVALID_LENGTH;
578  	}
579  
580  	*descriptor_title_str_type =
581  		entry->vendor_defined_descriptor_title_str_type;
582  	descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
583  	descriptor_title_str->length =
584  		entry->vendor_defined_descriptor_title_str_len;
585  
586  	descriptor_data->ptr =
587  		descriptor_title_str->ptr + descriptor_title_str->length;
588  	descriptor_data->length =
589  		length -
590  		sizeof(entry->vendor_defined_descriptor_title_str_type) -
591  		sizeof(entry->vendor_defined_descriptor_title_str_len) -
592  		descriptor_title_str->length;
593  
594  	return PLDM_SUCCESS;
595  }
596  
597  LIBPLDM_ABI_STABLE
decode_pldm_comp_image_info(const uint8_t * data,size_t length,struct pldm_component_image_information * pldm_comp_image_info,struct variable_field * comp_version_str)598  int decode_pldm_comp_image_info(
599  	const uint8_t *data, size_t length,
600  	struct pldm_component_image_information *pldm_comp_image_info,
601  	struct variable_field *comp_version_str)
602  {
603  	if (data == NULL || pldm_comp_image_info == NULL ||
604  	    comp_version_str == NULL) {
605  		return PLDM_ERROR_INVALID_DATA;
606  	}
607  
608  	if (length < sizeof(struct pldm_component_image_information)) {
609  		return PLDM_ERROR_INVALID_LENGTH;
610  	}
611  
612  	struct pldm_component_image_information *data_header =
613  		(struct pldm_component_image_information *)(data);
614  
615  	if (!is_string_type_valid(data_header->comp_version_string_type) ||
616  	    (data_header->comp_version_string_length == 0)) {
617  		return PLDM_ERROR_INVALID_DATA;
618  	}
619  
620  	if (length < sizeof(struct pldm_component_image_information) +
621  			     data_header->comp_version_string_length) {
622  		return PLDM_ERROR_INVALID_LENGTH;
623  	}
624  
625  	pldm_comp_image_info->comp_classification =
626  		le16toh(data_header->comp_classification);
627  	pldm_comp_image_info->comp_identifier =
628  		le16toh(data_header->comp_identifier);
629  	pldm_comp_image_info->comp_comparison_stamp =
630  		le32toh(data_header->comp_comparison_stamp);
631  	pldm_comp_image_info->comp_options.value =
632  		le16toh(data_header->comp_options.value);
633  	pldm_comp_image_info->requested_comp_activation_method.value =
634  		le16toh(data_header->requested_comp_activation_method.value);
635  	pldm_comp_image_info->comp_location_offset =
636  		le32toh(data_header->comp_location_offset);
637  	pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
638  	pldm_comp_image_info->comp_version_string_type =
639  		data_header->comp_version_string_type;
640  	pldm_comp_image_info->comp_version_string_length =
641  		data_header->comp_version_string_length;
642  
643  	if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
644  	     pldm_comp_image_info->comp_comparison_stamp !=
645  		     PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
646  		return PLDM_ERROR_INVALID_DATA;
647  	}
648  
649  	if (pldm_comp_image_info->comp_location_offset == 0 ||
650  	    pldm_comp_image_info->comp_size == 0) {
651  		return PLDM_ERROR_INVALID_DATA;
652  	}
653  
654  	comp_version_str->ptr =
655  		data + sizeof(struct pldm_component_image_information);
656  	comp_version_str->length =
657  		pldm_comp_image_info->comp_version_string_length;
658  
659  	return PLDM_SUCCESS;
660  }
661  
662  LIBPLDM_ABI_STABLE
encode_query_device_identifiers_req(uint8_t instance_id,size_t payload_length,struct pldm_msg * msg)663  int encode_query_device_identifiers_req(uint8_t instance_id,
664  					size_t payload_length,
665  					struct pldm_msg *msg)
666  {
667  	if (msg == NULL) {
668  		return PLDM_ERROR_INVALID_DATA;
669  	}
670  
671  	if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
672  		return PLDM_ERROR_INVALID_LENGTH;
673  	}
674  
675  	return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
676  				       PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
677  }
678  
679  LIBPLDM_ABI_STABLE
decode_query_device_identifiers_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint32_t * device_identifiers_len,uint8_t * descriptor_count,uint8_t ** descriptor_data)680  int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
681  					 size_t payload_length,
682  					 uint8_t *completion_code,
683  					 uint32_t *device_identifiers_len,
684  					 uint8_t *descriptor_count,
685  					 uint8_t **descriptor_data)
686  {
687  	if (msg == NULL || completion_code == NULL ||
688  	    device_identifiers_len == NULL || descriptor_count == NULL ||
689  	    descriptor_data == NULL) {
690  		return PLDM_ERROR_INVALID_DATA;
691  	}
692  
693  	*completion_code = msg->payload[0];
694  	if (PLDM_SUCCESS != *completion_code) {
695  		return PLDM_SUCCESS;
696  	}
697  
698  	if (payload_length <
699  	    sizeof(struct pldm_query_device_identifiers_resp)) {
700  		return PLDM_ERROR_INVALID_LENGTH;
701  	}
702  
703  	struct pldm_query_device_identifiers_resp *response =
704  		(struct pldm_query_device_identifiers_resp *)msg->payload;
705  	*device_identifiers_len = le32toh(response->device_identifiers_len);
706  
707  	if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
708  		return PLDM_ERROR_INVALID_LENGTH;
709  	}
710  
711  	if (payload_length !=
712  	    sizeof(struct pldm_query_device_identifiers_resp) +
713  		    *device_identifiers_len) {
714  		return PLDM_ERROR_INVALID_LENGTH;
715  	}
716  	*descriptor_count = response->descriptor_count;
717  
718  	if (*descriptor_count == 0) {
719  		return PLDM_ERROR_INVALID_DATA;
720  	}
721  	*descriptor_data =
722  		(uint8_t *)(msg->payload +
723  			    sizeof(struct pldm_query_device_identifiers_resp));
724  	return PLDM_SUCCESS;
725  }
726  
727  LIBPLDM_ABI_TESTING
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)728  int encode_query_device_identifiers_resp(
729  	uint8_t instance_id, uint8_t descriptor_count,
730  	const struct pldm_descriptor *descriptors, struct pldm_msg *msg,
731  	size_t *payload_length)
732  {
733  	int rc;
734  	struct pldm_msgbuf _buf;
735  	struct pldm_msgbuf *buf = &_buf;
736  
737  	if (descriptors == NULL || msg == NULL || payload_length == NULL) {
738  		return -EINVAL;
739  	}
740  
741  	if (descriptor_count < 1) {
742  		return -EINVAL;
743  	}
744  
745  	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
746  				     PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
747  	if (rc) {
748  		return -EINVAL;
749  	}
750  
751  	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
752  	if (rc) {
753  		return rc;
754  	}
755  
756  	/* Determine total length */
757  	uint32_t device_identifiers_len = 0;
758  	for (uint8_t i = 0; i < descriptor_count; i++) {
759  		const struct pldm_descriptor *d = &descriptors[i];
760  		device_identifiers_len +=
761  			2 * sizeof(uint16_t) + d->descriptor_length;
762  	}
763  
764  	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
765  	pldm_msgbuf_insert(buf, device_identifiers_len);
766  	pldm_msgbuf_insert(buf, descriptor_count);
767  
768  	for (uint8_t i = 0; i < descriptor_count; i++) {
769  		const struct pldm_descriptor *d = &descriptors[i];
770  		pldm_msgbuf_insert(buf, d->descriptor_type);
771  		pldm_msgbuf_insert(buf, d->descriptor_length);
772  		if (d->descriptor_data == NULL) {
773  			return -EINVAL;
774  		}
775  		rc = pldm_msgbuf_insert_array(
776  			buf, d->descriptor_length,
777  			(const uint8_t *)d->descriptor_data,
778  			d->descriptor_length);
779  		if (rc) {
780  			return rc;
781  		}
782  	}
783  
784  	return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
785  }
786  
787  LIBPLDM_ABI_STABLE
encode_get_firmware_parameters_req(uint8_t instance_id,size_t payload_length,struct pldm_msg * msg)788  int encode_get_firmware_parameters_req(uint8_t instance_id,
789  				       size_t payload_length,
790  				       struct pldm_msg *msg)
791  {
792  	if (msg == NULL) {
793  		return PLDM_ERROR_INVALID_DATA;
794  	}
795  
796  	if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
797  		return PLDM_ERROR_INVALID_LENGTH;
798  	}
799  
800  	return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
801  				       PLDM_GET_FIRMWARE_PARAMETERS, msg);
802  }
803  
804  LIBPLDM_ABI_STABLE
decode_get_firmware_parameters_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_get_firmware_parameters_resp * resp_data,struct variable_field * active_comp_image_set_ver_str,struct variable_field * pending_comp_image_set_ver_str,struct variable_field * comp_parameter_table)805  int decode_get_firmware_parameters_resp(
806  	const struct pldm_msg *msg, size_t payload_length,
807  	struct pldm_get_firmware_parameters_resp *resp_data,
808  	struct variable_field *active_comp_image_set_ver_str,
809  	struct variable_field *pending_comp_image_set_ver_str,
810  	struct variable_field *comp_parameter_table)
811  {
812  	if (msg == NULL || resp_data == NULL ||
813  	    active_comp_image_set_ver_str == NULL ||
814  	    pending_comp_image_set_ver_str == NULL ||
815  	    comp_parameter_table == NULL || !payload_length) {
816  		return PLDM_ERROR_INVALID_DATA;
817  	}
818  
819  	resp_data->completion_code = msg->payload[0];
820  	if (PLDM_SUCCESS != resp_data->completion_code) {
821  		return PLDM_SUCCESS;
822  	}
823  
824  	if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
825  		return PLDM_ERROR_INVALID_LENGTH;
826  	}
827  
828  	struct pldm_get_firmware_parameters_resp *response =
829  		(struct pldm_get_firmware_parameters_resp *)msg->payload;
830  
831  	if (!is_string_type_valid(
832  		    response->active_comp_image_set_ver_str_type) ||
833  	    (response->active_comp_image_set_ver_str_len == 0)) {
834  		return PLDM_ERROR_INVALID_DATA;
835  	}
836  
837  	if (response->pending_comp_image_set_ver_str_len == 0) {
838  		if (response->pending_comp_image_set_ver_str_type !=
839  		    PLDM_STR_TYPE_UNKNOWN) {
840  			return PLDM_ERROR_INVALID_DATA;
841  		}
842  	} else {
843  		if (!is_string_type_valid(
844  			    response->pending_comp_image_set_ver_str_type)) {
845  			return PLDM_ERROR_INVALID_DATA;
846  		}
847  	}
848  
849  	size_t partial_response_length =
850  		sizeof(struct pldm_get_firmware_parameters_resp) +
851  		response->active_comp_image_set_ver_str_len +
852  		response->pending_comp_image_set_ver_str_len;
853  
854  	if (payload_length < partial_response_length) {
855  		return PLDM_ERROR_INVALID_LENGTH;
856  	}
857  
858  	resp_data->capabilities_during_update.value =
859  		le32toh(response->capabilities_during_update.value);
860  	resp_data->comp_count = le16toh(response->comp_count);
861  	resp_data->active_comp_image_set_ver_str_type =
862  		response->active_comp_image_set_ver_str_type;
863  	resp_data->active_comp_image_set_ver_str_len =
864  		response->active_comp_image_set_ver_str_len;
865  	resp_data->pending_comp_image_set_ver_str_type =
866  		response->pending_comp_image_set_ver_str_type;
867  	resp_data->pending_comp_image_set_ver_str_len =
868  		response->pending_comp_image_set_ver_str_len;
869  
870  	active_comp_image_set_ver_str->ptr =
871  		msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
872  	active_comp_image_set_ver_str->length =
873  		resp_data->active_comp_image_set_ver_str_len;
874  
875  	if (resp_data->pending_comp_image_set_ver_str_len != 0) {
876  		pending_comp_image_set_ver_str->ptr =
877  			msg->payload +
878  			sizeof(struct pldm_get_firmware_parameters_resp) +
879  			resp_data->active_comp_image_set_ver_str_len;
880  		pending_comp_image_set_ver_str->length =
881  			resp_data->pending_comp_image_set_ver_str_len;
882  	} else {
883  		pending_comp_image_set_ver_str->ptr = NULL;
884  		pending_comp_image_set_ver_str->length = 0;
885  	}
886  
887  	if (payload_length > partial_response_length && resp_data->comp_count) {
888  		comp_parameter_table->ptr =
889  			msg->payload +
890  			sizeof(struct pldm_get_firmware_parameters_resp) +
891  			resp_data->active_comp_image_set_ver_str_len +
892  			resp_data->pending_comp_image_set_ver_str_len;
893  		comp_parameter_table->length =
894  			payload_length - partial_response_length;
895  	} else {
896  		comp_parameter_table->ptr = NULL;
897  		comp_parameter_table->length = 0;
898  	}
899  
900  	return PLDM_SUCCESS;
901  }
902  
903  LIBPLDM_ABI_TESTING
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)904  int encode_get_firmware_parameters_resp(
905  	uint8_t instance_id,
906  	const struct pldm_get_firmware_parameters_resp_full *resp_data,
907  	struct pldm_msg *msg, size_t *payload_length)
908  {
909  	int rc;
910  	struct pldm_msgbuf _buf;
911  	struct pldm_msgbuf *buf = &_buf;
912  
913  	if (resp_data == NULL || msg == NULL || payload_length == NULL) {
914  		return -EINVAL;
915  	}
916  
917  	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
918  				     PLDM_GET_FIRMWARE_PARAMETERS, msg);
919  	if (rc) {
920  		return -EINVAL;
921  	}
922  
923  	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
924  	if (rc) {
925  		return rc;
926  	}
927  
928  	pldm_msgbuf_insert(buf, resp_data->completion_code);
929  	pldm_msgbuf_insert(buf, resp_data->capabilities_during_update.value);
930  	pldm_msgbuf_insert(buf, resp_data->comp_count);
931  	pldm_msgbuf_insert(buf,
932  			   resp_data->active_comp_image_set_ver_str.str_type);
933  	pldm_msgbuf_insert(buf,
934  			   resp_data->active_comp_image_set_ver_str.str_len);
935  	pldm_msgbuf_insert(buf,
936  			   resp_data->pending_comp_image_set_ver_str.str_type);
937  	pldm_msgbuf_insert(buf,
938  			   resp_data->pending_comp_image_set_ver_str.str_len);
939  	/* String data appended */
940  	rc = pldm_msgbuf_insert_array(
941  		buf, resp_data->active_comp_image_set_ver_str.str_len,
942  		resp_data->active_comp_image_set_ver_str.str_data,
943  		resp_data->active_comp_image_set_ver_str.str_len);
944  	if (rc) {
945  		return rc;
946  	}
947  	rc = pldm_msgbuf_insert_array(
948  		buf, resp_data->pending_comp_image_set_ver_str.str_len,
949  		resp_data->pending_comp_image_set_ver_str.str_data,
950  		resp_data->pending_comp_image_set_ver_str.str_len);
951  	if (rc) {
952  		return rc;
953  	}
954  
955  	/* Further calls to encode_get_firmware_parameters_resp_comp_entry
956  	 * will populate the remainder */
957  
958  	return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
959  }
960  
961  LIBPLDM_ABI_TESTING
encode_get_firmware_parameters_resp_comp_entry(const struct pldm_component_parameter_entry_full * comp,uint8_t * payload,size_t * payload_length)962  int encode_get_firmware_parameters_resp_comp_entry(
963  	const struct pldm_component_parameter_entry_full *comp,
964  	uint8_t *payload, size_t *payload_length)
965  {
966  	int rc;
967  	struct pldm_msgbuf _buf;
968  	struct pldm_msgbuf *buf = &_buf;
969  
970  	if (comp == NULL || payload == NULL || payload_length == NULL) {
971  		return -EINVAL;
972  	}
973  
974  	rc = pldm_msgbuf_init_errno(buf, 0, payload, *payload_length);
975  	if (rc) {
976  		return rc;
977  	}
978  
979  	pldm_msgbuf_insert(buf, comp->comp_classification);
980  	pldm_msgbuf_insert(buf, comp->comp_identifier);
981  	pldm_msgbuf_insert(buf, comp->comp_classification_index);
982  
983  	pldm_msgbuf_insert(buf, comp->active_ver.comparison_stamp);
984  	pldm_msgbuf_insert(buf, (uint8_t)comp->active_ver.str.str_type);
985  	pldm_msgbuf_insert(buf, comp->active_ver.str.str_len);
986  	rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
987  				      comp->active_ver.date,
988  				      PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
989  	if (rc) {
990  		return rc;
991  	}
992  
993  	pldm_msgbuf_insert(buf, comp->pending_ver.comparison_stamp);
994  	pldm_msgbuf_insert(buf, (uint8_t)comp->pending_ver.str.str_type);
995  	pldm_msgbuf_insert(buf, comp->pending_ver.str.str_len);
996  	rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
997  				      comp->pending_ver.date,
998  				      PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
999  	if (rc) {
1000  		return rc;
1001  	}
1002  
1003  	pldm_msgbuf_insert(buf, comp->comp_activation_methods.value);
1004  	pldm_msgbuf_insert(buf, comp->capabilities_during_update.value);
1005  
1006  	rc = pldm_msgbuf_insert_array(buf, comp->active_ver.str.str_len,
1007  				      comp->active_ver.str.str_data,
1008  				      comp->active_ver.str.str_len);
1009  	if (rc) {
1010  		return rc;
1011  	}
1012  	rc = pldm_msgbuf_insert_array(buf, comp->pending_ver.str.str_len,
1013  				      comp->pending_ver.str.str_data,
1014  				      comp->pending_ver.str.str_len);
1015  	if (rc) {
1016  		return rc;
1017  	}
1018  
1019  	return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
1020  }
1021  
1022  LIBPLDM_ABI_STABLE
decode_get_firmware_parameters_resp_comp_entry(const uint8_t * data,size_t length,struct pldm_component_parameter_entry * component_data,struct variable_field * active_comp_ver_str,struct variable_field * pending_comp_ver_str)1023  int decode_get_firmware_parameters_resp_comp_entry(
1024  	const uint8_t *data, size_t length,
1025  	struct pldm_component_parameter_entry *component_data,
1026  	struct variable_field *active_comp_ver_str,
1027  	struct variable_field *pending_comp_ver_str)
1028  {
1029  	if (data == NULL || component_data == NULL ||
1030  	    active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
1031  		return PLDM_ERROR_INVALID_DATA;
1032  	}
1033  
1034  	if (length < sizeof(struct pldm_component_parameter_entry)) {
1035  		return PLDM_ERROR_INVALID_LENGTH;
1036  	}
1037  
1038  	struct pldm_component_parameter_entry *entry =
1039  		(struct pldm_component_parameter_entry *)(data);
1040  
1041  	size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
1042  			      entry->active_comp_ver_str_len +
1043  			      entry->pending_comp_ver_str_len;
1044  
1045  	if (length < entry_length) {
1046  		return PLDM_ERROR_INVALID_LENGTH;
1047  	}
1048  
1049  	component_data->comp_classification =
1050  		le16toh(entry->comp_classification);
1051  	component_data->comp_identifier = le16toh(entry->comp_identifier);
1052  	component_data->comp_classification_index =
1053  		entry->comp_classification_index;
1054  	component_data->active_comp_comparison_stamp =
1055  		le32toh(entry->active_comp_comparison_stamp);
1056  	component_data->active_comp_ver_str_type =
1057  		entry->active_comp_ver_str_type;
1058  	component_data->active_comp_ver_str_len =
1059  		entry->active_comp_ver_str_len;
1060  	memcpy(component_data->active_comp_release_date,
1061  	       entry->active_comp_release_date,
1062  	       sizeof(entry->active_comp_release_date));
1063  	component_data->pending_comp_comparison_stamp =
1064  		le32toh(entry->pending_comp_comparison_stamp);
1065  	component_data->pending_comp_ver_str_type =
1066  		entry->pending_comp_ver_str_type;
1067  	component_data->pending_comp_ver_str_len =
1068  		entry->pending_comp_ver_str_len;
1069  	memcpy(component_data->pending_comp_release_date,
1070  	       entry->pending_comp_release_date,
1071  	       sizeof(entry->pending_comp_release_date));
1072  	component_data->comp_activation_methods.value =
1073  		le16toh(entry->comp_activation_methods.value);
1074  	component_data->capabilities_during_update.value =
1075  		le32toh(entry->capabilities_during_update.value);
1076  
1077  	if (entry->active_comp_ver_str_len != 0) {
1078  		active_comp_ver_str->ptr =
1079  			data + sizeof(struct pldm_component_parameter_entry);
1080  		active_comp_ver_str->length = entry->active_comp_ver_str_len;
1081  	} else {
1082  		active_comp_ver_str->ptr = NULL;
1083  		active_comp_ver_str->length = 0;
1084  	}
1085  
1086  	if (entry->pending_comp_ver_str_len != 0) {
1087  		pending_comp_ver_str->ptr =
1088  			data + sizeof(struct pldm_component_parameter_entry) +
1089  			entry->active_comp_ver_str_len;
1090  		pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
1091  	} else {
1092  		pending_comp_ver_str->ptr = NULL;
1093  		pending_comp_ver_str->length = 0;
1094  	}
1095  	return PLDM_SUCCESS;
1096  }
1097  
1098  LIBPLDM_ABI_STABLE
encode_query_downstream_devices_req(uint8_t instance_id,struct pldm_msg * msg)1099  int encode_query_downstream_devices_req(uint8_t instance_id,
1100  					struct pldm_msg *msg)
1101  {
1102  	if (msg == NULL) {
1103  		return -EINVAL;
1104  	}
1105  
1106  	return encode_pldm_header_only_errno(PLDM_REQUEST, instance_id,
1107  					     PLDM_FWUP,
1108  					     PLDM_QUERY_DOWNSTREAM_DEVICES,
1109  					     msg);
1110  }
1111  
1112  LIBPLDM_ABI_STABLE
decode_query_downstream_devices_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_query_downstream_devices_resp * resp_data)1113  int decode_query_downstream_devices_resp(
1114  	const struct pldm_msg *msg, size_t payload_length,
1115  	struct pldm_query_downstream_devices_resp *resp_data)
1116  {
1117  	struct pldm_msgbuf _buf;
1118  	struct pldm_msgbuf *buf = &_buf;
1119  	int rc;
1120  
1121  	if (msg == NULL || resp_data == NULL || !payload_length) {
1122  		return -EINVAL;
1123  	}
1124  
1125  	rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1126  				    msg->payload, payload_length);
1127  	if (rc) {
1128  		return rc;
1129  	}
1130  
1131  	rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1132  	if (rc) {
1133  		return rc;
1134  	}
1135  	if (PLDM_SUCCESS != resp_data->completion_code) {
1136  		// Return the CC directly without decoding the rest of the payload
1137  		return 0;
1138  	}
1139  
1140  	if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) {
1141  		return -EBADMSG;
1142  	}
1143  
1144  	rc = pldm_msgbuf_extract(buf,
1145  				 resp_data->downstream_device_update_supported);
1146  	if (rc) {
1147  		return rc;
1148  	}
1149  
1150  	if (!is_downstream_device_update_support_valid(
1151  		    resp_data->downstream_device_update_supported)) {
1152  		return -EINVAL;
1153  	}
1154  
1155  	pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
1156  	pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices);
1157  	pldm_msgbuf_extract(buf, resp_data->capabilities.value);
1158  
1159  	return pldm_msgbuf_destroy_consumed(buf);
1160  }
1161  
1162  LIBPLDM_ABI_STABLE
encode_query_downstream_identifiers_req(uint8_t instance_id,const struct pldm_query_downstream_identifiers_req * params_req,struct pldm_msg * msg,size_t payload_length)1163  int encode_query_downstream_identifiers_req(
1164  	uint8_t instance_id,
1165  	const struct pldm_query_downstream_identifiers_req *params_req,
1166  	struct pldm_msg *msg, size_t payload_length)
1167  {
1168  	struct pldm_msgbuf _buf;
1169  	struct pldm_msgbuf *buf = &_buf;
1170  	int rc;
1171  
1172  	if (!msg || !params_req) {
1173  		return -EINVAL;
1174  	}
1175  
1176  	if (!is_transfer_operation_flag_valid(
1177  		    (enum transfer_op_flag)
1178  			    params_req->transfer_operation_flag)) {
1179  		return -EINVAL;
1180  	}
1181  
1182  	struct pldm_header_info header = { 0 };
1183  	header.instance = instance_id;
1184  	header.msg_type = PLDM_REQUEST;
1185  	header.pldm_type = PLDM_FWUP;
1186  	header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS;
1187  	rc = pack_pldm_header_errno(&header, &(msg->hdr));
1188  	if (rc) {
1189  		return rc;
1190  	}
1191  
1192  	rc = pldm_msgbuf_init_errno(buf,
1193  				    PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES,
1194  				    msg->payload, payload_length);
1195  	if (rc) {
1196  		return rc;
1197  	}
1198  
1199  	pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
1200  	// Data correctness has been verified, cast it to 1-byte data directly.
1201  	pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
1202  
1203  	return pldm_msgbuf_destroy(buf);
1204  }
1205  
1206  LIBPLDM_ABI_STABLE
decode_query_downstream_identifiers_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_query_downstream_identifiers_resp * resp_data,struct pldm_downstream_device_iter * iter)1207  int decode_query_downstream_identifiers_resp(
1208  	const struct pldm_msg *msg, size_t payload_length,
1209  	struct pldm_query_downstream_identifiers_resp *resp_data,
1210  	struct pldm_downstream_device_iter *iter)
1211  {
1212  	struct pldm_msgbuf _buf;
1213  	struct pldm_msgbuf *buf = &_buf;
1214  	void *remaining = NULL;
1215  	int rc = 0;
1216  
1217  	if (msg == NULL || resp_data == NULL || iter == NULL ||
1218  	    !payload_length) {
1219  		return -EINVAL;
1220  	}
1221  
1222  	rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1223  				    msg->payload, payload_length);
1224  	if (rc) {
1225  		return rc;
1226  	}
1227  
1228  	rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1229  	if (rc) {
1230  		return rc;
1231  	}
1232  	if (PLDM_SUCCESS != resp_data->completion_code) {
1233  		return 0;
1234  	}
1235  
1236  	if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) {
1237  		return -EBADMSG;
1238  	}
1239  
1240  	pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1241  	pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1242  
1243  	rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length);
1244  	if (rc) {
1245  		return rc;
1246  	}
1247  
1248  	pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
1249  	rc = pldm_msgbuf_span_required(
1250  		buf, resp_data->downstream_devices_length, &remaining);
1251  	if (rc) {
1252  		return rc;
1253  	}
1254  
1255  	rc = pldm_msgbuf_destroy(buf);
1256  	if (rc) {
1257  		return rc;
1258  	}
1259  
1260  	iter->field.ptr = remaining;
1261  	iter->field.length = resp_data->downstream_devices_length;
1262  	iter->devs = resp_data->number_of_downstream_devices;
1263  
1264  	return 0;
1265  }
1266  
1267  LIBPLDM_ABI_STABLE
decode_pldm_downstream_device_from_iter(struct pldm_downstream_device_iter * iter,struct pldm_downstream_device * dev)1268  int decode_pldm_downstream_device_from_iter(
1269  	struct pldm_downstream_device_iter *iter,
1270  	struct pldm_downstream_device *dev)
1271  {
1272  	struct pldm_msgbuf _buf;
1273  	struct pldm_msgbuf *buf = &_buf;
1274  	int rc;
1275  
1276  	if (!iter || !dev) {
1277  		return -EINVAL;
1278  	}
1279  
1280  	rc = pldm_msgbuf_init_errno(buf, 3, iter->field.ptr,
1281  				    iter->field.length);
1282  	if (rc) {
1283  		return rc;
1284  	}
1285  
1286  	pldm_msgbuf_extract(buf, dev->downstream_device_index);
1287  	pldm_msgbuf_extract(buf, dev->downstream_descriptor_count);
1288  	iter->field.ptr = NULL;
1289  	pldm_msgbuf_span_remaining(buf, (void **)&iter->field.ptr,
1290  				   &iter->field.length);
1291  
1292  	return pldm_msgbuf_destroy(buf);
1293  }
1294  
1295  LIBPLDM_ABI_STABLE
encode_get_downstream_firmware_parameters_req(uint8_t instance_id,const struct pldm_get_downstream_firmware_parameters_req * params_req,struct pldm_msg * msg,size_t payload_length)1296  int encode_get_downstream_firmware_parameters_req(
1297  	uint8_t instance_id,
1298  	const struct pldm_get_downstream_firmware_parameters_req *params_req,
1299  	struct pldm_msg *msg, size_t payload_length)
1300  {
1301  	struct pldm_msgbuf _buf;
1302  	struct pldm_msgbuf *buf = &_buf;
1303  	int rc;
1304  
1305  	if (!msg || !params_req) {
1306  		return -EINVAL;
1307  	}
1308  
1309  	rc = pldm_msgbuf_init_errno(
1310  		buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES,
1311  		msg->payload, payload_length);
1312  	if (rc < 0) {
1313  		return rc;
1314  	}
1315  
1316  	if (!is_transfer_operation_flag_valid(
1317  		    (enum transfer_op_flag)
1318  			    params_req->transfer_operation_flag)) {
1319  		return -EBADMSG;
1320  	}
1321  
1322  	struct pldm_header_info header = { 0 };
1323  	header.instance = instance_id;
1324  	header.msg_type = PLDM_REQUEST;
1325  	header.pldm_type = PLDM_FWUP;
1326  	header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS;
1327  	rc = pack_pldm_header_errno(&header, &msg->hdr);
1328  	if (rc < 0) {
1329  		return rc;
1330  	}
1331  
1332  	pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
1333  	// Data correctness has been verified, cast it to 1-byte data directly.
1334  	pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
1335  
1336  	return pldm_msgbuf_destroy(buf);
1337  }
1338  
1339  LIBPLDM_ABI_STABLE
decode_get_downstream_firmware_parameters_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_get_downstream_firmware_parameters_resp * resp_data,struct pldm_downstream_device_parameters_iter * iter)1340  int decode_get_downstream_firmware_parameters_resp(
1341  	const struct pldm_msg *msg, size_t payload_length,
1342  	struct pldm_get_downstream_firmware_parameters_resp *resp_data,
1343  	struct pldm_downstream_device_parameters_iter *iter)
1344  {
1345  	struct pldm_msgbuf _buf;
1346  	struct pldm_msgbuf *buf = &_buf;
1347  	void *remaining = NULL;
1348  	size_t length;
1349  	int rc;
1350  
1351  	if (msg == NULL || resp_data == NULL || iter == NULL) {
1352  		return -EINVAL;
1353  	}
1354  
1355  	rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1356  				    msg->payload, payload_length);
1357  	if (rc < 0) {
1358  		return rc;
1359  	}
1360  
1361  	rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1362  	if (rc < 0) {
1363  		return rc;
1364  	}
1365  	if (PLDM_SUCCESS != resp_data->completion_code) {
1366  		return 0;
1367  	}
1368  
1369  	if (payload_length <
1370  	    PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN) {
1371  		return -EBADMSG;
1372  	}
1373  
1374  	pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1375  	pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1376  	pldm_msgbuf_extract(buf,
1377  			    resp_data->fdp_capabilities_during_update.value);
1378  	pldm_msgbuf_extract(buf, resp_data->downstream_device_count);
1379  
1380  	rc = pldm_msgbuf_span_remaining(buf, &remaining, &length);
1381  	if (rc) {
1382  		return rc;
1383  	}
1384  
1385  	rc = pldm_msgbuf_destroy(buf);
1386  	if (rc) {
1387  		return rc;
1388  	}
1389  
1390  	iter->field.ptr = remaining;
1391  	iter->field.length = length;
1392  	iter->entries = resp_data->downstream_device_count;
1393  
1394  	return 0;
1395  }
1396  
1397  LIBPLDM_ABI_STABLE
decode_pldm_downstream_device_parameters_entry_from_iter(struct pldm_downstream_device_parameters_iter * iter,struct pldm_downstream_device_parameters_entry * entry)1398  int decode_pldm_downstream_device_parameters_entry_from_iter(
1399  	struct pldm_downstream_device_parameters_iter *iter,
1400  	struct pldm_downstream_device_parameters_entry *entry)
1401  {
1402  	struct pldm_msgbuf _buf;
1403  	struct pldm_msgbuf *buf = &_buf;
1404  	void *comp_ver_str;
1405  	size_t remaining;
1406  	void *cursor;
1407  	int rc;
1408  
1409  	if (iter == NULL || entry == NULL) {
1410  		return -EINVAL;
1411  	}
1412  
1413  	rc = pldm_msgbuf_init_errno(
1414  		buf, PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN,
1415  		iter->field.ptr, iter->field.length);
1416  	if (rc < 0) {
1417  		return rc;
1418  	}
1419  
1420  	pldm_msgbuf_extract(buf, entry->downstream_device_index);
1421  	pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp);
1422  	pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type);
1423  	rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len);
1424  	if (rc < 0) {
1425  		return rc;
1426  	}
1427  	rc = pldm_msgbuf_extract_array(buf,
1428  				       PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1429  				       entry->active_comp_release_date,
1430  				       sizeof(entry->active_comp_release_date));
1431  	if (rc < 0) {
1432  		return rc;
1433  	}
1434  
1435  	// Fill the last byte with NULL character
1436  	entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1437  		'\0';
1438  
1439  	pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp);
1440  	pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type);
1441  	rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len);
1442  	if (rc < 0) {
1443  		return rc;
1444  	}
1445  
1446  	rc = pldm_msgbuf_extract_array(
1447  		buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1448  		entry->pending_comp_release_date,
1449  		sizeof(entry->pending_comp_release_date));
1450  	if (rc < 0) {
1451  		return rc;
1452  	}
1453  
1454  	// Fill the last byte with NULL character
1455  	entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1456  		'\0';
1457  
1458  	pldm_msgbuf_extract(buf, entry->comp_activation_methods.value);
1459  	pldm_msgbuf_extract(buf, entry->capabilities_during_update.value);
1460  
1461  	comp_ver_str = NULL;
1462  	pldm_msgbuf_span_required(buf, entry->active_comp_ver_str_len,
1463  				  &comp_ver_str);
1464  	entry->active_comp_ver_str = comp_ver_str;
1465  
1466  	comp_ver_str = NULL;
1467  	pldm_msgbuf_span_required(buf, entry->pending_comp_ver_str_len,
1468  				  &comp_ver_str);
1469  	entry->pending_comp_ver_str = comp_ver_str;
1470  
1471  	cursor = NULL;
1472  	rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining);
1473  	if (rc < 0) {
1474  		return rc;
1475  	}
1476  
1477  	iter->field.ptr = cursor;
1478  	iter->field.length = remaining;
1479  
1480  	return 0;
1481  }
1482  
1483  LIBPLDM_ABI_STABLE
encode_request_update_req(uint8_t instance_id,uint32_t max_transfer_size,uint16_t num_of_comp,uint8_t max_outstanding_transfer_req,uint16_t pkg_data_len,uint8_t comp_image_set_ver_str_type,uint8_t comp_image_set_ver_str_len,const struct variable_field * comp_img_set_ver_str,struct pldm_msg * msg,size_t payload_length)1484  int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
1485  			      uint16_t num_of_comp,
1486  			      uint8_t max_outstanding_transfer_req,
1487  			      uint16_t pkg_data_len,
1488  			      uint8_t comp_image_set_ver_str_type,
1489  			      uint8_t comp_image_set_ver_str_len,
1490  			      const struct variable_field *comp_img_set_ver_str,
1491  			      struct pldm_msg *msg, size_t payload_length)
1492  {
1493  	if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
1494  	    msg == NULL) {
1495  		return PLDM_ERROR_INVALID_DATA;
1496  	}
1497  
1498  	if (payload_length != sizeof(struct pldm_request_update_req) +
1499  				      comp_img_set_ver_str->length) {
1500  		return PLDM_ERROR_INVALID_LENGTH;
1501  	}
1502  
1503  	if ((comp_image_set_ver_str_len == 0) ||
1504  	    (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
1505  		return PLDM_ERROR_INVALID_DATA;
1506  	}
1507  
1508  	if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
1509  	    (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
1510  		return PLDM_ERROR_INVALID_DATA;
1511  	}
1512  
1513  	if (!is_string_type_valid(comp_image_set_ver_str_type)) {
1514  		return PLDM_ERROR_INVALID_DATA;
1515  	}
1516  
1517  	struct pldm_header_info header = { 0 };
1518  	header.instance = instance_id;
1519  	header.msg_type = PLDM_REQUEST;
1520  	header.pldm_type = PLDM_FWUP;
1521  	header.command = PLDM_REQUEST_UPDATE;
1522  	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1523  	if (rc) {
1524  		return rc;
1525  	}
1526  
1527  	struct pldm_request_update_req *request =
1528  		(struct pldm_request_update_req *)msg->payload;
1529  
1530  	request->max_transfer_size = htole32(max_transfer_size);
1531  	request->num_of_comp = htole16(num_of_comp);
1532  	request->max_outstanding_transfer_req = max_outstanding_transfer_req;
1533  	request->pkg_data_len = htole16(pkg_data_len);
1534  	request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
1535  	request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
1536  
1537  	memcpy(msg->payload + sizeof(struct pldm_request_update_req),
1538  	       comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
1539  
1540  	return PLDM_SUCCESS;
1541  }
1542  
1543  LIBPLDM_ABI_TESTING
decode_request_update_req(const struct pldm_msg * msg,size_t payload_length,struct pldm_request_update_req_full * req)1544  int decode_request_update_req(const struct pldm_msg *msg, size_t payload_length,
1545  			      struct pldm_request_update_req_full *req)
1546  {
1547  	int rc;
1548  	uint8_t t;
1549  	struct pldm_msgbuf _buf;
1550  	struct pldm_msgbuf *buf = &_buf;
1551  
1552  	if (msg == NULL || req == NULL) {
1553  		return -EINVAL;
1554  	}
1555  
1556  	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
1557  	if (rc) {
1558  		return rc;
1559  	}
1560  
1561  	pldm_msgbuf_extract(buf, req->max_transfer_size);
1562  	pldm_msgbuf_extract(buf, req->num_of_comp);
1563  	pldm_msgbuf_extract(buf, req->max_outstanding_transfer_req);
1564  	pldm_msgbuf_extract(buf, req->pkg_data_len);
1565  	rc = pldm_msgbuf_extract(buf, t);
1566  	if (rc) {
1567  		return rc;
1568  	}
1569  	if (t > PLDM_STR_TYPE_UTF_16BE) {
1570  		return -EBADMSG;
1571  	}
1572  	req->image_set_ver.str_type = (enum pldm_firmware_update_string_type)t;
1573  	pldm_msgbuf_extract(buf, req->image_set_ver.str_len);
1574  	if (rc) {
1575  		return rc;
1576  	}
1577  
1578  	rc = pldm_msgbuf_extract_array(buf, req->image_set_ver.str_len,
1579  				       req->image_set_ver.str_data,
1580  				       PLDM_FIRMWARE_MAX_STRING);
1581  	if (rc) {
1582  		return rc;
1583  	}
1584  
1585  	return pldm_msgbuf_destroy_consumed(buf);
1586  }
1587  
1588  LIBPLDM_ABI_STABLE
decode_request_update_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint16_t * fd_meta_data_len,uint8_t * fd_will_send_pkg_data)1589  int decode_request_update_resp(const struct pldm_msg *msg,
1590  			       size_t payload_length, uint8_t *completion_code,
1591  			       uint16_t *fd_meta_data_len,
1592  			       uint8_t *fd_will_send_pkg_data)
1593  {
1594  	if (msg == NULL || completion_code == NULL ||
1595  	    fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
1596  	    !payload_length) {
1597  		return PLDM_ERROR_INVALID_DATA;
1598  	}
1599  
1600  	*completion_code = msg->payload[0];
1601  	if (*completion_code != PLDM_SUCCESS) {
1602  		return PLDM_SUCCESS;
1603  	}
1604  
1605  	if (payload_length != sizeof(struct pldm_request_update_resp)) {
1606  		return PLDM_ERROR_INVALID_LENGTH;
1607  	}
1608  
1609  	struct pldm_request_update_resp *response =
1610  		(struct pldm_request_update_resp *)msg->payload;
1611  
1612  	*fd_meta_data_len = le16toh(response->fd_meta_data_len);
1613  	*fd_will_send_pkg_data = response->fd_will_send_pkg_data;
1614  
1615  	return PLDM_SUCCESS;
1616  }
1617  
1618  LIBPLDM_ABI_TESTING
encode_request_update_resp(uint8_t instance_id,const struct pldm_request_update_resp * resp_data,struct pldm_msg * msg,size_t * payload_length)1619  int encode_request_update_resp(uint8_t instance_id,
1620  			       const struct pldm_request_update_resp *resp_data,
1621  			       struct pldm_msg *msg, size_t *payload_length)
1622  {
1623  	int rc;
1624  	struct pldm_msgbuf _buf;
1625  	struct pldm_msgbuf *buf = &_buf;
1626  
1627  	if (msg == NULL || payload_length == NULL) {
1628  		return -EINVAL;
1629  	}
1630  
1631  	struct pldm_header_info header = {
1632  		.instance = instance_id,
1633  		.msg_type = PLDM_RESPONSE,
1634  		.pldm_type = PLDM_FWUP,
1635  		.command = PLDM_REQUEST_UPDATE,
1636  	};
1637  	rc = pack_pldm_header(&header, &(msg->hdr));
1638  	if (rc) {
1639  		return -EINVAL;
1640  	}
1641  
1642  	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1643  	if (rc) {
1644  		return rc;
1645  	}
1646  
1647  	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
1648  	pldm_msgbuf_insert(buf, resp_data->fd_meta_data_len);
1649  	pldm_msgbuf_insert(buf, resp_data->fd_will_send_pkg_data);
1650  
1651  	/* TODO: DSP0267 1.3.0 adds GetPackageDataMaximumTransferSize */
1652  
1653  	return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
1654  }
1655  
1656  LIBPLDM_ABI_STABLE
encode_pass_component_table_req(uint8_t instance_id,uint8_t transfer_flag,uint16_t comp_classification,uint16_t comp_identifier,uint8_t comp_classification_index,uint32_t comp_comparison_stamp,uint8_t comp_ver_str_type,uint8_t comp_ver_str_len,const struct variable_field * comp_ver_str,struct pldm_msg * msg,size_t payload_length)1657  int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
1658  				    uint16_t comp_classification,
1659  				    uint16_t comp_identifier,
1660  				    uint8_t comp_classification_index,
1661  				    uint32_t comp_comparison_stamp,
1662  				    uint8_t comp_ver_str_type,
1663  				    uint8_t comp_ver_str_len,
1664  				    const struct variable_field *comp_ver_str,
1665  				    struct pldm_msg *msg, size_t payload_length)
1666  {
1667  	if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1668  		return PLDM_ERROR_INVALID_DATA;
1669  	}
1670  
1671  	if (payload_length != sizeof(struct pldm_pass_component_table_req) +
1672  				      comp_ver_str->length) {
1673  		return PLDM_ERROR_INVALID_LENGTH;
1674  	}
1675  
1676  	if ((comp_ver_str_len == 0) ||
1677  	    (comp_ver_str_len != comp_ver_str->length)) {
1678  		return PLDM_ERROR_INVALID_DATA;
1679  	}
1680  
1681  	if (!is_transfer_flag_valid(transfer_flag)) {
1682  		return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
1683  	}
1684  
1685  	if (!is_string_type_valid(comp_ver_str_type)) {
1686  		return PLDM_ERROR_INVALID_DATA;
1687  	}
1688  
1689  	struct pldm_header_info header = { 0 };
1690  	header.instance = instance_id;
1691  	header.msg_type = PLDM_REQUEST;
1692  	header.pldm_type = PLDM_FWUP;
1693  	header.command = PLDM_PASS_COMPONENT_TABLE;
1694  	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1695  	if (rc) {
1696  		return rc;
1697  	}
1698  
1699  	struct pldm_pass_component_table_req *request =
1700  		(struct pldm_pass_component_table_req *)msg->payload;
1701  
1702  	request->transfer_flag = transfer_flag;
1703  	request->comp_classification = htole16(comp_classification);
1704  	request->comp_identifier = htole16(comp_identifier);
1705  	request->comp_classification_index = comp_classification_index;
1706  	request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1707  	request->comp_ver_str_type = comp_ver_str_type;
1708  	request->comp_ver_str_len = comp_ver_str_len;
1709  
1710  	memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
1711  	       comp_ver_str->ptr, comp_ver_str->length);
1712  
1713  	return PLDM_SUCCESS;
1714  }
1715  
1716  LIBPLDM_ABI_TESTING
decode_pass_component_table_req(const struct pldm_msg * msg,size_t payload_length,struct pldm_pass_component_table_req_full * pcomp)1717  int decode_pass_component_table_req(
1718  	const struct pldm_msg *msg, size_t payload_length,
1719  	struct pldm_pass_component_table_req_full *pcomp)
1720  {
1721  	int rc;
1722  	uint8_t t;
1723  	struct pldm_msgbuf _buf;
1724  	struct pldm_msgbuf *buf = &_buf;
1725  
1726  	if (msg == NULL || pcomp == NULL) {
1727  		return -EINVAL;
1728  	}
1729  
1730  	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
1731  	if (rc) {
1732  		return rc;
1733  	}
1734  
1735  	pldm_msgbuf_extract(buf, pcomp->transfer_flag);
1736  	pldm_msgbuf_extract(buf, pcomp->comp_classification);
1737  	pldm_msgbuf_extract(buf, pcomp->comp_identifier);
1738  	pldm_msgbuf_extract(buf, pcomp->comp_classification_index);
1739  	pldm_msgbuf_extract(buf, pcomp->comp_comparison_stamp);
1740  	rc = pldm_msgbuf_extract(buf, t);
1741  	if (rc) {
1742  		return rc;
1743  	}
1744  	if (t > PLDM_STR_TYPE_UTF_16BE) {
1745  		return -EBADMSG;
1746  	}
1747  	pcomp->version.str_type = (enum pldm_firmware_update_string_type)t;
1748  	rc = pldm_msgbuf_extract(buf, pcomp->version.str_len);
1749  	if (rc) {
1750  		return rc;
1751  	}
1752  	rc = pldm_msgbuf_extract_array(buf, pcomp->version.str_len,
1753  				       pcomp->version.str_data,
1754  				       PLDM_FIRMWARE_MAX_STRING);
1755  	if (rc) {
1756  		return rc;
1757  	}
1758  
1759  	return pldm_msgbuf_destroy_consumed(buf);
1760  }
1761  
1762  LIBPLDM_ABI_STABLE
decode_pass_component_table_resp(const struct pldm_msg * msg,const size_t payload_length,uint8_t * completion_code,uint8_t * comp_resp,uint8_t * comp_resp_code)1763  int decode_pass_component_table_resp(const struct pldm_msg *msg,
1764  				     const size_t payload_length,
1765  				     uint8_t *completion_code,
1766  				     uint8_t *comp_resp,
1767  				     uint8_t *comp_resp_code)
1768  {
1769  	if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
1770  	    comp_resp_code == NULL || !payload_length) {
1771  		return PLDM_ERROR_INVALID_DATA;
1772  	}
1773  
1774  	*completion_code = msg->payload[0];
1775  	if (*completion_code != PLDM_SUCCESS) {
1776  		return PLDM_SUCCESS;
1777  	}
1778  
1779  	if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1780  		return PLDM_ERROR_INVALID_LENGTH;
1781  	}
1782  
1783  	struct pldm_pass_component_table_resp *response =
1784  		(struct pldm_pass_component_table_resp *)msg->payload;
1785  
1786  	if (!is_comp_resp_valid(response->comp_resp)) {
1787  		return PLDM_ERROR_INVALID_DATA;
1788  	}
1789  
1790  	if (!is_comp_resp_code_valid(response->comp_resp_code)) {
1791  		return PLDM_ERROR_INVALID_DATA;
1792  	}
1793  
1794  	*comp_resp = response->comp_resp;
1795  	*comp_resp_code = response->comp_resp_code;
1796  
1797  	return PLDM_SUCCESS;
1798  }
1799  
1800  LIBPLDM_ABI_TESTING
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)1801  int encode_pass_component_table_resp(
1802  	uint8_t instance_id,
1803  	const struct pldm_pass_component_table_resp *resp_data,
1804  	struct pldm_msg *msg, size_t *payload_length)
1805  {
1806  	int rc;
1807  	struct pldm_msgbuf _buf;
1808  	struct pldm_msgbuf *buf = &_buf;
1809  
1810  	if (msg == NULL || payload_length == NULL) {
1811  		return -EINVAL;
1812  	}
1813  
1814  	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
1815  				     PLDM_PASS_COMPONENT_TABLE, msg);
1816  	if (rc) {
1817  		return -EINVAL;
1818  	}
1819  
1820  	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1821  	if (rc) {
1822  		return rc;
1823  	}
1824  
1825  	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
1826  	pldm_msgbuf_insert(buf, resp_data->comp_resp);
1827  	pldm_msgbuf_insert(buf, resp_data->comp_resp_code);
1828  
1829  	return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
1830  }
1831  
1832  LIBPLDM_ABI_STABLE
encode_update_component_req(uint8_t instance_id,uint16_t comp_classification,uint16_t comp_identifier,uint8_t comp_classification_index,uint32_t comp_comparison_stamp,uint32_t comp_image_size,bitfield32_t update_option_flags,uint8_t comp_ver_str_type,uint8_t comp_ver_str_len,const struct variable_field * comp_ver_str,struct pldm_msg * msg,size_t payload_length)1833  int encode_update_component_req(
1834  	uint8_t instance_id, uint16_t comp_classification,
1835  	uint16_t comp_identifier, uint8_t comp_classification_index,
1836  	uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1837  	bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1838  	uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1839  	struct pldm_msg *msg, size_t payload_length)
1840  {
1841  	if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1842  		return PLDM_ERROR_INVALID_DATA;
1843  	}
1844  
1845  	if (payload_length !=
1846  	    sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
1847  		return PLDM_ERROR_INVALID_LENGTH;
1848  	}
1849  
1850  	if (!comp_image_size) {
1851  		return PLDM_ERROR_INVALID_DATA;
1852  	}
1853  
1854  	if ((comp_ver_str_len == 0) ||
1855  	    (comp_ver_str_len != comp_ver_str->length)) {
1856  		return PLDM_ERROR_INVALID_DATA;
1857  	}
1858  
1859  	if (!is_string_type_valid(comp_ver_str_type)) {
1860  		return PLDM_ERROR_INVALID_DATA;
1861  	}
1862  
1863  	struct pldm_header_info header = { 0 };
1864  	header.instance = instance_id;
1865  	header.msg_type = PLDM_REQUEST;
1866  	header.pldm_type = PLDM_FWUP;
1867  	header.command = PLDM_UPDATE_COMPONENT;
1868  	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1869  	if (rc) {
1870  		return rc;
1871  	}
1872  
1873  	struct pldm_update_component_req *request =
1874  		(struct pldm_update_component_req *)msg->payload;
1875  
1876  	request->comp_classification = htole16(comp_classification);
1877  	request->comp_identifier = htole16(comp_identifier);
1878  	request->comp_classification_index = comp_classification_index;
1879  	request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1880  	request->comp_image_size = htole32(comp_image_size);
1881  	request->update_option_flags.value = htole32(update_option_flags.value);
1882  	request->comp_ver_str_type = comp_ver_str_type;
1883  	request->comp_ver_str_len = comp_ver_str_len;
1884  
1885  	memcpy(msg->payload + sizeof(struct pldm_update_component_req),
1886  	       comp_ver_str->ptr, comp_ver_str->length);
1887  
1888  	return PLDM_SUCCESS;
1889  }
1890  
1891  LIBPLDM_ABI_TESTING
decode_update_component_req(const struct pldm_msg * msg,size_t payload_length,struct pldm_update_component_req_full * up)1892  int decode_update_component_req(const struct pldm_msg *msg,
1893  				size_t payload_length,
1894  				struct pldm_update_component_req_full *up)
1895  {
1896  	int rc;
1897  	uint8_t t;
1898  	struct pldm_msgbuf _buf;
1899  	struct pldm_msgbuf *buf = &_buf;
1900  
1901  	if (msg == NULL || up == NULL) {
1902  		return -EINVAL;
1903  	}
1904  
1905  	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
1906  	if (rc) {
1907  		return rc;
1908  	}
1909  
1910  	pldm_msgbuf_extract(buf, up->comp_classification);
1911  	pldm_msgbuf_extract(buf, up->comp_identifier);
1912  	pldm_msgbuf_extract(buf, up->comp_classification_index);
1913  	pldm_msgbuf_extract(buf, up->comp_comparison_stamp);
1914  	pldm_msgbuf_extract(buf, up->comp_image_size);
1915  	pldm_msgbuf_extract(buf, up->update_option_flags.value);
1916  	rc = pldm_msgbuf_extract(buf, t);
1917  	if (rc) {
1918  		return rc;
1919  	}
1920  	if (t > PLDM_STR_TYPE_UTF_16BE) {
1921  		return -EBADMSG;
1922  	}
1923  	up->version.str_type = (enum pldm_firmware_update_string_type)t;
1924  	rc = pldm_msgbuf_extract(buf, up->version.str_len);
1925  	if (rc) {
1926  		return rc;
1927  	}
1928  	rc = pldm_msgbuf_extract_array(buf, up->version.str_len,
1929  				       up->version.str_data,
1930  				       PLDM_FIRMWARE_MAX_STRING);
1931  	if (rc) {
1932  		return rc;
1933  	}
1934  
1935  	if (buf->remaining != 0) {
1936  		return -EINVAL;
1937  	}
1938  
1939  	return 0;
1940  }
1941  
1942  LIBPLDM_ABI_STABLE
decode_update_component_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint8_t * comp_compatibility_resp,uint8_t * comp_compatibility_resp_code,bitfield32_t * update_option_flags_enabled,uint16_t * time_before_req_fw_data)1943  int decode_update_component_resp(const struct pldm_msg *msg,
1944  				 size_t payload_length,
1945  				 uint8_t *completion_code,
1946  				 uint8_t *comp_compatibility_resp,
1947  				 uint8_t *comp_compatibility_resp_code,
1948  				 bitfield32_t *update_option_flags_enabled,
1949  				 uint16_t *time_before_req_fw_data)
1950  {
1951  	if (msg == NULL || completion_code == NULL ||
1952  	    comp_compatibility_resp == NULL ||
1953  	    comp_compatibility_resp_code == NULL ||
1954  	    update_option_flags_enabled == NULL ||
1955  	    time_before_req_fw_data == NULL || !payload_length) {
1956  		return PLDM_ERROR_INVALID_DATA;
1957  	}
1958  
1959  	*completion_code = msg->payload[0];
1960  	if (*completion_code != PLDM_SUCCESS) {
1961  		return PLDM_SUCCESS;
1962  	}
1963  
1964  	if (payload_length != sizeof(struct pldm_update_component_resp)) {
1965  		return PLDM_ERROR_INVALID_LENGTH;
1966  	}
1967  
1968  	struct pldm_update_component_resp *response =
1969  		(struct pldm_update_component_resp *)msg->payload;
1970  
1971  	if (!is_comp_compatibility_resp_valid(
1972  		    response->comp_compatibility_resp)) {
1973  		return PLDM_ERROR_INVALID_DATA;
1974  	}
1975  
1976  	if (!is_comp_compatibility_resp_code_valid(
1977  		    response->comp_compatibility_resp_code)) {
1978  		return PLDM_ERROR_INVALID_DATA;
1979  	}
1980  
1981  	*comp_compatibility_resp = response->comp_compatibility_resp;
1982  	*comp_compatibility_resp_code = response->comp_compatibility_resp_code;
1983  	update_option_flags_enabled->value =
1984  		le32toh(response->update_option_flags_enabled.value);
1985  	*time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
1986  
1987  	return PLDM_SUCCESS;
1988  }
1989  
1990  LIBPLDM_ABI_TESTING
encode_update_component_resp(uint8_t instance_id,const struct pldm_update_component_resp * resp_data,struct pldm_msg * msg,size_t * payload_length)1991  int encode_update_component_resp(
1992  	uint8_t instance_id, const struct pldm_update_component_resp *resp_data,
1993  	struct pldm_msg *msg, size_t *payload_length)
1994  {
1995  	int rc;
1996  	struct pldm_msgbuf _buf;
1997  	struct pldm_msgbuf *buf = &_buf;
1998  
1999  	if (msg == NULL || payload_length == NULL) {
2000  		return -EINVAL;
2001  	}
2002  
2003  	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2004  				     PLDM_UPDATE_COMPONENT, msg);
2005  	if (rc) {
2006  		return -EINVAL;
2007  	}
2008  
2009  	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2010  	if (rc) {
2011  		return rc;
2012  	}
2013  
2014  	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2015  	pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp);
2016  	pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp_code);
2017  	pldm_msgbuf_insert(buf, resp_data->update_option_flags_enabled.value);
2018  	pldm_msgbuf_insert(buf, resp_data->time_before_req_fw_data);
2019  
2020  	return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2021  }
2022  
2023  LIBPLDM_ABI_STABLE
decode_request_firmware_data_req(const struct pldm_msg * msg,size_t payload_length,uint32_t * offset,uint32_t * length)2024  int decode_request_firmware_data_req(const struct pldm_msg *msg,
2025  				     size_t payload_length, uint32_t *offset,
2026  				     uint32_t *length)
2027  {
2028  	if (msg == NULL || offset == NULL || length == NULL) {
2029  		return PLDM_ERROR_INVALID_DATA;
2030  	}
2031  	if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
2032  		return PLDM_ERROR_INVALID_LENGTH;
2033  	}
2034  	struct pldm_request_firmware_data_req *request =
2035  		(struct pldm_request_firmware_data_req *)msg->payload;
2036  	*offset = le32toh(request->offset);
2037  	*length = le32toh(request->length);
2038  
2039  	if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
2040  		return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
2041  	}
2042  
2043  	return PLDM_SUCCESS;
2044  }
2045  
2046  LIBPLDM_ABI_TESTING
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)2047  int encode_request_firmware_data_req(
2048  	uint8_t instance_id,
2049  	const struct pldm_request_firmware_data_req *req_params,
2050  	struct pldm_msg *msg, size_t *payload_length)
2051  {
2052  	int rc;
2053  	struct pldm_msgbuf _buf;
2054  	struct pldm_msgbuf *buf = &_buf;
2055  
2056  	if (msg == NULL || payload_length == NULL) {
2057  		return -EINVAL;
2058  	}
2059  
2060  	rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2061  				     PLDM_REQUEST_FIRMWARE_DATA, msg);
2062  	if (rc) {
2063  		return -EINVAL;
2064  	}
2065  
2066  	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2067  	if (rc) {
2068  		return rc;
2069  	}
2070  
2071  	pldm_msgbuf_insert(buf, req_params->offset);
2072  	pldm_msgbuf_insert(buf, req_params->length);
2073  
2074  	return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2075  }
2076  
2077  LIBPLDM_ABI_STABLE
encode_request_firmware_data_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2078  int encode_request_firmware_data_resp(uint8_t instance_id,
2079  				      uint8_t completion_code,
2080  				      struct pldm_msg *msg,
2081  				      size_t payload_length)
2082  {
2083  	if (msg == NULL || !payload_length) {
2084  		return PLDM_ERROR_INVALID_DATA;
2085  	}
2086  
2087  	struct pldm_header_info header = { 0 };
2088  	header.instance = instance_id;
2089  	header.msg_type = PLDM_RESPONSE;
2090  	header.pldm_type = PLDM_FWUP;
2091  	header.command = PLDM_REQUEST_FIRMWARE_DATA;
2092  	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2093  	if (rc) {
2094  		return rc;
2095  	}
2096  
2097  	msg->payload[0] = completion_code;
2098  
2099  	return PLDM_SUCCESS;
2100  }
2101  
2102  LIBPLDM_ABI_STABLE
decode_transfer_complete_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * transfer_result)2103  int decode_transfer_complete_req(const struct pldm_msg *msg,
2104  				 size_t payload_length,
2105  				 uint8_t *transfer_result)
2106  {
2107  	if (msg == NULL || transfer_result == NULL) {
2108  		return PLDM_ERROR_INVALID_DATA;
2109  	}
2110  
2111  	if (payload_length != sizeof(*transfer_result)) {
2112  		return PLDM_ERROR_INVALID_LENGTH;
2113  	}
2114  
2115  	*transfer_result = msg->payload[0];
2116  	return PLDM_SUCCESS;
2117  }
2118  
2119  LIBPLDM_ABI_TESTING
encode_transfer_complete_req(uint8_t instance_id,uint8_t transfer_result,struct pldm_msg * msg,size_t * payload_length)2120  int encode_transfer_complete_req(uint8_t instance_id, uint8_t transfer_result,
2121  				 struct pldm_msg *msg, size_t *payload_length)
2122  {
2123  	int rc;
2124  	struct pldm_msgbuf _buf;
2125  	struct pldm_msgbuf *buf = &_buf;
2126  
2127  	if (msg == NULL || payload_length == NULL) {
2128  		return -EINVAL;
2129  	}
2130  
2131  	rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2132  				     PLDM_TRANSFER_COMPLETE, msg);
2133  	if (rc) {
2134  		return -EINVAL;
2135  	}
2136  
2137  	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2138  	if (rc) {
2139  		return rc;
2140  	}
2141  
2142  	rc = pldm_msgbuf_insert(buf, transfer_result);
2143  	if (rc) {
2144  		return rc;
2145  	}
2146  
2147  	return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2148  }
2149  
2150  LIBPLDM_ABI_STABLE
encode_transfer_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2151  int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
2152  				  struct pldm_msg *msg, size_t payload_length)
2153  {
2154  	if (msg == NULL) {
2155  		return PLDM_ERROR_INVALID_DATA;
2156  	}
2157  
2158  	if (payload_length != sizeof(completion_code)) {
2159  		return PLDM_ERROR_INVALID_LENGTH;
2160  	}
2161  
2162  	struct pldm_header_info header = { 0 };
2163  	header.instance = instance_id;
2164  	header.msg_type = PLDM_RESPONSE;
2165  	header.pldm_type = PLDM_FWUP;
2166  	header.command = PLDM_TRANSFER_COMPLETE;
2167  	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2168  	if (rc) {
2169  		return rc;
2170  	}
2171  
2172  	msg->payload[0] = completion_code;
2173  
2174  	return PLDM_SUCCESS;
2175  }
2176  
2177  LIBPLDM_ABI_STABLE
decode_verify_complete_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * verify_result)2178  int decode_verify_complete_req(const struct pldm_msg *msg,
2179  			       size_t payload_length, uint8_t *verify_result)
2180  {
2181  	if (msg == NULL || verify_result == NULL) {
2182  		return PLDM_ERROR_INVALID_DATA;
2183  	}
2184  
2185  	if (payload_length != sizeof(*verify_result)) {
2186  		return PLDM_ERROR_INVALID_LENGTH;
2187  	}
2188  
2189  	*verify_result = msg->payload[0];
2190  	return PLDM_SUCCESS;
2191  }
2192  
2193  LIBPLDM_ABI_TESTING
encode_verify_complete_req(uint8_t instance_id,uint8_t verify_result,struct pldm_msg * msg,size_t * payload_length)2194  int encode_verify_complete_req(uint8_t instance_id, uint8_t verify_result,
2195  			       struct pldm_msg *msg, size_t *payload_length)
2196  {
2197  	int rc;
2198  	struct pldm_msgbuf _buf;
2199  	struct pldm_msgbuf *buf = &_buf;
2200  
2201  	if (msg == NULL || payload_length == NULL) {
2202  		return -EINVAL;
2203  	}
2204  
2205  	rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2206  				     PLDM_VERIFY_COMPLETE, msg);
2207  	if (rc) {
2208  		return EINVAL;
2209  	}
2210  
2211  	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2212  	if (rc) {
2213  		return rc;
2214  	}
2215  
2216  	rc = pldm_msgbuf_insert(buf, verify_result);
2217  	if (rc) {
2218  		return rc;
2219  	}
2220  
2221  	return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2222  }
2223  
2224  LIBPLDM_ABI_STABLE
encode_verify_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2225  int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
2226  				struct pldm_msg *msg, size_t payload_length)
2227  {
2228  	if (msg == NULL) {
2229  		return PLDM_ERROR_INVALID_DATA;
2230  	}
2231  
2232  	if (payload_length != sizeof(completion_code)) {
2233  		return PLDM_ERROR_INVALID_LENGTH;
2234  	}
2235  
2236  	struct pldm_header_info header = { 0 };
2237  	header.instance = instance_id;
2238  	header.msg_type = PLDM_RESPONSE;
2239  	header.pldm_type = PLDM_FWUP;
2240  	header.command = PLDM_VERIFY_COMPLETE;
2241  	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2242  	if (rc) {
2243  		return rc;
2244  	}
2245  
2246  	msg->payload[0] = completion_code;
2247  
2248  	return PLDM_SUCCESS;
2249  }
2250  
2251  LIBPLDM_ABI_STABLE
decode_apply_complete_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * apply_result,bitfield16_t * comp_activation_methods_modification)2252  int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
2253  			      uint8_t *apply_result,
2254  			      bitfield16_t *comp_activation_methods_modification)
2255  {
2256  	if (msg == NULL || apply_result == NULL ||
2257  	    comp_activation_methods_modification == NULL) {
2258  		return PLDM_ERROR_INVALID_DATA;
2259  	}
2260  
2261  	if (payload_length != sizeof(struct pldm_apply_complete_req)) {
2262  		return PLDM_ERROR_INVALID_LENGTH;
2263  	}
2264  
2265  	struct pldm_apply_complete_req *request =
2266  		(struct pldm_apply_complete_req *)msg->payload;
2267  
2268  	*apply_result = request->apply_result;
2269  	comp_activation_methods_modification->value =
2270  		le16toh(request->comp_activation_methods_modification.value);
2271  
2272  	if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
2273  	    comp_activation_methods_modification->value) {
2274  		return PLDM_ERROR_INVALID_DATA;
2275  	}
2276  
2277  	return PLDM_SUCCESS;
2278  }
2279  
2280  LIBPLDM_ABI_TESTING
encode_apply_complete_req(uint8_t instance_id,const struct pldm_apply_complete_req * req_data,struct pldm_msg * msg,size_t * payload_length)2281  int encode_apply_complete_req(uint8_t instance_id,
2282  			      const struct pldm_apply_complete_req *req_data,
2283  			      struct pldm_msg *msg, size_t *payload_length)
2284  {
2285  	int rc;
2286  	struct pldm_msgbuf _buf;
2287  	struct pldm_msgbuf *buf = &_buf;
2288  
2289  	if (msg == NULL || payload_length == NULL) {
2290  		return -EINVAL;
2291  	}
2292  
2293  	rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2294  				     PLDM_APPLY_COMPLETE, msg);
2295  	if (rc) {
2296  		return -EINVAL;
2297  	}
2298  
2299  	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2300  	if (rc) {
2301  		return rc;
2302  	}
2303  
2304  	pldm_msgbuf_insert(buf, req_data->apply_result);
2305  	pldm_msgbuf_insert(
2306  		buf, req_data->comp_activation_methods_modification.value);
2307  
2308  	return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2309  }
2310  
2311  LIBPLDM_ABI_STABLE
encode_apply_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2312  int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
2313  			       struct pldm_msg *msg, size_t payload_length)
2314  {
2315  	if (msg == NULL) {
2316  		return PLDM_ERROR_INVALID_DATA;
2317  	}
2318  
2319  	if (payload_length != sizeof(completion_code)) {
2320  		return PLDM_ERROR_INVALID_LENGTH;
2321  	}
2322  
2323  	struct pldm_header_info header = { 0 };
2324  	header.instance = instance_id;
2325  	header.msg_type = PLDM_RESPONSE;
2326  	header.pldm_type = PLDM_FWUP;
2327  	header.command = PLDM_APPLY_COMPLETE;
2328  	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2329  	if (rc) {
2330  		return rc;
2331  	}
2332  
2333  	msg->payload[0] = completion_code;
2334  
2335  	return PLDM_SUCCESS;
2336  }
2337  
2338  LIBPLDM_ABI_TESTING
decode_activate_firmware_req(const struct pldm_msg * msg,size_t payload_length,bool * self_contained)2339  int decode_activate_firmware_req(const struct pldm_msg *msg,
2340  				 size_t payload_length, bool *self_contained)
2341  {
2342  	int rc;
2343  	struct pldm_msgbuf _buf;
2344  	struct pldm_msgbuf *buf = &_buf;
2345  
2346  	if (msg == NULL || self_contained == NULL) {
2347  		return -EINVAL;
2348  	}
2349  
2350  	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
2351  	if (rc) {
2352  		return 0;
2353  	}
2354  
2355  	uint8_t self_contained_u8 = 0;
2356  	rc = pldm_msgbuf_extract(buf, self_contained_u8);
2357  	if (rc) {
2358  		return rc;
2359  	}
2360  	if (buf->remaining != 0) {
2361  		return -EOVERFLOW;
2362  	}
2363  	*self_contained = (bool)self_contained_u8;
2364  	return 0;
2365  }
2366  
2367  LIBPLDM_ABI_STABLE
encode_activate_firmware_req(uint8_t instance_id,bool8_t self_contained_activation_req,struct pldm_msg * msg,size_t payload_length)2368  int encode_activate_firmware_req(uint8_t instance_id,
2369  				 bool8_t self_contained_activation_req,
2370  				 struct pldm_msg *msg, size_t payload_length)
2371  {
2372  	if (msg == NULL) {
2373  		return PLDM_ERROR_INVALID_DATA;
2374  	}
2375  
2376  	if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
2377  		return PLDM_ERROR_INVALID_LENGTH;
2378  	}
2379  
2380  	if (!is_self_contained_activation_req_valid(
2381  		    self_contained_activation_req)) {
2382  		return PLDM_ERROR_INVALID_DATA;
2383  	}
2384  
2385  	struct pldm_header_info header = { 0 };
2386  	header.instance = instance_id;
2387  	header.msg_type = PLDM_REQUEST;
2388  	header.pldm_type = PLDM_FWUP;
2389  	header.command = PLDM_ACTIVATE_FIRMWARE;
2390  	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2391  	if (rc) {
2392  		return rc;
2393  	}
2394  
2395  	struct pldm_activate_firmware_req *request =
2396  		(struct pldm_activate_firmware_req *)msg->payload;
2397  
2398  	request->self_contained_activation_req = self_contained_activation_req;
2399  
2400  	return PLDM_SUCCESS;
2401  }
2402  
2403  LIBPLDM_ABI_STABLE
decode_activate_firmware_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint16_t * estimated_time_activation)2404  int decode_activate_firmware_resp(const struct pldm_msg *msg,
2405  				  size_t payload_length,
2406  				  uint8_t *completion_code,
2407  				  uint16_t *estimated_time_activation)
2408  {
2409  	if (msg == NULL || completion_code == NULL ||
2410  	    estimated_time_activation == NULL || !payload_length) {
2411  		return PLDM_ERROR_INVALID_DATA;
2412  	}
2413  
2414  	*completion_code = msg->payload[0];
2415  	if (*completion_code != PLDM_SUCCESS) {
2416  		return PLDM_SUCCESS;
2417  	}
2418  
2419  	if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
2420  		return PLDM_ERROR_INVALID_LENGTH;
2421  	}
2422  
2423  	struct pldm_activate_firmware_resp *response =
2424  		(struct pldm_activate_firmware_resp *)msg->payload;
2425  
2426  	*estimated_time_activation =
2427  		le16toh(response->estimated_time_activation);
2428  
2429  	return PLDM_SUCCESS;
2430  }
2431  
2432  LIBPLDM_ABI_TESTING
encode_activate_firmware_resp(uint8_t instance_id,const struct pldm_activate_firmware_resp * resp_data,struct pldm_msg * msg,size_t * payload_length)2433  int encode_activate_firmware_resp(
2434  	uint8_t instance_id,
2435  	const struct pldm_activate_firmware_resp *resp_data,
2436  	struct pldm_msg *msg, size_t *payload_length)
2437  {
2438  	int rc;
2439  	struct pldm_msgbuf _buf;
2440  	struct pldm_msgbuf *buf = &_buf;
2441  
2442  	if (msg == NULL || payload_length == NULL) {
2443  		return -EINVAL;
2444  	}
2445  
2446  	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2447  				     PLDM_ACTIVATE_FIRMWARE, msg);
2448  	if (rc) {
2449  		return -EINVAL;
2450  	}
2451  
2452  	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2453  	if (rc) {
2454  		return rc;
2455  	}
2456  
2457  	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2458  	pldm_msgbuf_insert(buf, resp_data->estimated_time_activation);
2459  
2460  	return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2461  }
2462  
2463  LIBPLDM_ABI_STABLE
encode_get_status_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)2464  int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
2465  			  size_t payload_length)
2466  {
2467  	if (msg == NULL) {
2468  		return PLDM_ERROR_INVALID_DATA;
2469  	}
2470  
2471  	if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
2472  		return PLDM_ERROR_INVALID_LENGTH;
2473  	}
2474  
2475  	struct pldm_header_info header = { 0 };
2476  	header.instance = instance_id;
2477  	header.msg_type = PLDM_REQUEST;
2478  	header.pldm_type = PLDM_FWUP;
2479  	header.command = PLDM_GET_STATUS;
2480  	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2481  	if (rc) {
2482  		return rc;
2483  	}
2484  
2485  	return PLDM_SUCCESS;
2486  }
2487  
2488  LIBPLDM_ABI_STABLE
decode_get_status_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,uint8_t * current_state,uint8_t * previous_state,uint8_t * aux_state,uint8_t * aux_state_status,uint8_t * progress_percent,uint8_t * reason_code,bitfield32_t * update_option_flags_enabled)2489  int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
2490  			   uint8_t *completion_code, uint8_t *current_state,
2491  			   uint8_t *previous_state, uint8_t *aux_state,
2492  			   uint8_t *aux_state_status, uint8_t *progress_percent,
2493  			   uint8_t *reason_code,
2494  			   bitfield32_t *update_option_flags_enabled)
2495  {
2496  	if (msg == NULL || completion_code == NULL || current_state == NULL ||
2497  	    previous_state == NULL || aux_state == NULL ||
2498  	    aux_state_status == NULL || progress_percent == NULL ||
2499  	    reason_code == NULL || update_option_flags_enabled == NULL ||
2500  	    !payload_length) {
2501  		return PLDM_ERROR_INVALID_DATA;
2502  	}
2503  
2504  	*completion_code = msg->payload[0];
2505  	if (*completion_code != PLDM_SUCCESS) {
2506  		return PLDM_SUCCESS;
2507  	}
2508  
2509  	if (payload_length != sizeof(struct pldm_get_status_resp)) {
2510  		return PLDM_ERROR_INVALID_LENGTH;
2511  	}
2512  	struct pldm_get_status_resp *response =
2513  		(struct pldm_get_status_resp *)msg->payload;
2514  
2515  	if (!is_state_valid(response->current_state)) {
2516  		return PLDM_ERROR_INVALID_DATA;
2517  	}
2518  	if (!is_state_valid(response->previous_state)) {
2519  		return PLDM_ERROR_INVALID_DATA;
2520  	}
2521  	if (!is_aux_state_valid(response->aux_state)) {
2522  		return PLDM_ERROR_INVALID_DATA;
2523  	}
2524  	if (!is_aux_state_status_valid(response->aux_state_status)) {
2525  		return PLDM_ERROR_INVALID_DATA;
2526  	}
2527  	if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
2528  		return PLDM_ERROR_INVALID_DATA;
2529  	}
2530  	if (!is_reason_code_valid(response->reason_code)) {
2531  		return PLDM_ERROR_INVALID_DATA;
2532  	}
2533  
2534  	if ((response->current_state == PLDM_FD_STATE_IDLE) ||
2535  	    (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
2536  	    (response->current_state == PLDM_FD_STATE_READY_XFER)) {
2537  		if (response->aux_state !=
2538  		    PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
2539  			return PLDM_ERROR_INVALID_DATA;
2540  		}
2541  	}
2542  
2543  	*current_state = response->current_state;
2544  	*previous_state = response->previous_state;
2545  	*aux_state = response->aux_state;
2546  	*aux_state_status = response->aux_state_status;
2547  	*progress_percent = response->progress_percent;
2548  	*reason_code = response->reason_code;
2549  	update_option_flags_enabled->value =
2550  		le32toh(response->update_option_flags_enabled.value);
2551  
2552  	return PLDM_SUCCESS;
2553  }
2554  
2555  LIBPLDM_ABI_TESTING
encode_get_status_resp(uint8_t instance_id,const struct pldm_get_status_resp * status,struct pldm_msg * msg,size_t * payload_length)2556  int encode_get_status_resp(uint8_t instance_id,
2557  			   const struct pldm_get_status_resp *status,
2558  			   struct pldm_msg *msg, size_t *payload_length)
2559  {
2560  	int rc;
2561  	struct pldm_msgbuf _buf;
2562  	struct pldm_msgbuf *buf = &_buf;
2563  
2564  	if (status == NULL || msg == NULL || payload_length == NULL) {
2565  		return -EINVAL;
2566  	}
2567  
2568  	if (status->completion_code != PLDM_SUCCESS) {
2569  		return -EINVAL;
2570  	}
2571  
2572  	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2573  				     PLDM_GET_STATUS, msg);
2574  	if (rc) {
2575  		return -EINVAL;
2576  	}
2577  
2578  	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2579  	if (rc) {
2580  		return rc;
2581  	}
2582  
2583  	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2584  	pldm_msgbuf_insert(buf, status->current_state);
2585  	pldm_msgbuf_insert(buf, status->previous_state);
2586  	pldm_msgbuf_insert(buf, status->aux_state);
2587  	pldm_msgbuf_insert(buf, status->aux_state_status);
2588  	pldm_msgbuf_insert(buf, status->progress_percent);
2589  	pldm_msgbuf_insert(buf, status->reason_code);
2590  	pldm_msgbuf_insert(buf, status->update_option_flags_enabled.value);
2591  
2592  	return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2593  }
2594  
2595  LIBPLDM_ABI_STABLE
encode_cancel_update_component_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)2596  int encode_cancel_update_component_req(uint8_t instance_id,
2597  				       struct pldm_msg *msg,
2598  				       size_t payload_length)
2599  {
2600  	if (msg == NULL) {
2601  		return PLDM_ERROR_INVALID_DATA;
2602  	}
2603  
2604  	if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
2605  		return PLDM_ERROR_INVALID_LENGTH;
2606  	}
2607  
2608  	struct pldm_header_info header = { 0 };
2609  	header.instance = instance_id;
2610  	header.msg_type = PLDM_REQUEST;
2611  	header.pldm_type = PLDM_FWUP;
2612  	header.command = PLDM_CANCEL_UPDATE_COMPONENT;
2613  	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2614  	if (rc) {
2615  		return rc;
2616  	}
2617  
2618  	return PLDM_SUCCESS;
2619  }
2620  
2621  LIBPLDM_ABI_STABLE
decode_cancel_update_component_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code)2622  int decode_cancel_update_component_resp(const struct pldm_msg *msg,
2623  					size_t payload_length,
2624  					uint8_t *completion_code)
2625  {
2626  	if (msg == NULL || completion_code == NULL) {
2627  		return PLDM_ERROR_INVALID_DATA;
2628  	}
2629  
2630  	if (payload_length != sizeof(*completion_code)) {
2631  		return PLDM_ERROR_INVALID_LENGTH;
2632  	}
2633  
2634  	*completion_code = msg->payload[0];
2635  	return PLDM_SUCCESS;
2636  }
2637  
2638  LIBPLDM_ABI_STABLE
encode_cancel_update_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)2639  int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
2640  			     size_t payload_length)
2641  {
2642  	if (msg == NULL) {
2643  		return PLDM_ERROR_INVALID_DATA;
2644  	}
2645  
2646  	if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
2647  		return PLDM_ERROR_INVALID_LENGTH;
2648  	}
2649  
2650  	struct pldm_header_info header = { 0 };
2651  	header.instance = instance_id;
2652  	header.msg_type = PLDM_REQUEST;
2653  	header.pldm_type = PLDM_FWUP;
2654  	header.command = PLDM_CANCEL_UPDATE;
2655  	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2656  	if (rc) {
2657  		return rc;
2658  	}
2659  
2660  	return PLDM_SUCCESS;
2661  }
2662  
2663  LIBPLDM_ABI_STABLE
decode_cancel_update_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code,bool8_t * non_functioning_component_indication,bitfield64_t * non_functioning_component_bitmap)2664  int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
2665  			      uint8_t *completion_code,
2666  			      bool8_t *non_functioning_component_indication,
2667  			      bitfield64_t *non_functioning_component_bitmap)
2668  {
2669  	if (msg == NULL || completion_code == NULL ||
2670  	    non_functioning_component_indication == NULL ||
2671  	    non_functioning_component_bitmap == NULL || !payload_length) {
2672  		return PLDM_ERROR_INVALID_DATA;
2673  	}
2674  
2675  	*completion_code = msg->payload[0];
2676  	if (*completion_code != PLDM_SUCCESS) {
2677  		return PLDM_SUCCESS;
2678  	}
2679  
2680  	if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
2681  		return PLDM_ERROR_INVALID_LENGTH;
2682  	}
2683  	struct pldm_cancel_update_resp *response =
2684  		(struct pldm_cancel_update_resp *)msg->payload;
2685  
2686  	if (!is_non_functioning_component_indication_valid(
2687  		    response->non_functioning_component_indication)) {
2688  		return PLDM_ERROR_INVALID_DATA;
2689  	}
2690  
2691  	*non_functioning_component_indication =
2692  		response->non_functioning_component_indication;
2693  
2694  	if (*non_functioning_component_indication) {
2695  		non_functioning_component_bitmap->value =
2696  			le64toh(response->non_functioning_component_bitmap);
2697  	}
2698  
2699  	return PLDM_SUCCESS;
2700  }
2701  
2702  LIBPLDM_ABI_TESTING
encode_cancel_update_resp(uint8_t instance_id,const struct pldm_cancel_update_resp * resp_data,struct pldm_msg * msg,size_t * payload_length)2703  int encode_cancel_update_resp(uint8_t instance_id,
2704  			      const struct pldm_cancel_update_resp *resp_data,
2705  			      struct pldm_msg *msg, size_t *payload_length)
2706  {
2707  	int rc;
2708  	struct pldm_msgbuf _buf;
2709  	struct pldm_msgbuf *buf = &_buf;
2710  
2711  	if (msg == NULL || payload_length == NULL) {
2712  		return -EINVAL;
2713  	}
2714  
2715  	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2716  				     PLDM_CANCEL_UPDATE, msg);
2717  	if (rc) {
2718  		return -EINVAL;
2719  	}
2720  
2721  	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2722  	if (rc) {
2723  		return rc;
2724  	}
2725  
2726  	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2727  	pldm_msgbuf_insert(buf,
2728  			   resp_data->non_functioning_component_indication);
2729  	pldm_msgbuf_insert(buf, resp_data->non_functioning_component_bitmap);
2730  
2731  	return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length);
2732  }
2733