xref: /openbmc/libpldm/src/dsp/firmware_update.c (revision 412fa270c3999a38a911e84088a6b7a8ccf59121)
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  */
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  */
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 
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
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  */
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  */
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  */
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
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
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  */
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  */
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  */
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  */
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  */
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 static int decode_pldm_package_header_info_errno(
330 	const void *data, size_t length,
331 	struct pldm_package_header_information *package_header_info,
332 	struct variable_field *package_version_str)
333 {
334 	if (data == NULL || package_header_info == NULL ||
335 	    package_version_str == NULL) {
336 		return -EINVAL;
337 	}
338 
339 	if (length < sizeof(struct pldm_package_header_information)) {
340 		return -EOVERFLOW;
341 	}
342 
343 	struct pldm_package_header_information *data_header =
344 		(struct pldm_package_header_information *)(data);
345 
346 	if (!is_string_type_valid(data_header->package_version_string_type) ||
347 	    (data_header->package_version_string_length == 0)) {
348 		return -EBADMSG;
349 	}
350 
351 	if (length < sizeof(struct pldm_package_header_information) +
352 			     data_header->package_version_string_length) {
353 		return -EOVERFLOW;
354 	}
355 
356 	if ((data_header->component_bitmap_bit_length %
357 	     PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
358 		return -EBADMSG;
359 	}
360 
361 	memcpy(package_header_info->uuid, data_header->uuid,
362 	       sizeof(data_header->uuid));
363 	package_header_info->package_header_format_version =
364 		data_header->package_header_format_version;
365 	package_header_info->package_header_size =
366 		le16toh(data_header->package_header_size);
367 	memcpy(package_header_info->package_release_date_time,
368 	       data_header->package_release_date_time,
369 	       sizeof(data_header->package_release_date_time));
370 	package_header_info->component_bitmap_bit_length =
371 		le16toh(data_header->component_bitmap_bit_length);
372 	package_header_info->package_version_string_type =
373 		data_header->package_version_string_type;
374 	package_header_info->package_version_string_length =
375 		data_header->package_version_string_length;
376 	package_version_str->ptr =
377 		(const uint8_t *)data +
378 		sizeof(struct pldm_package_header_information);
379 	package_version_str->length =
380 		package_header_info->package_version_string_length;
381 
382 	return 0;
383 }
384 
385 LIBPLDM_ABI_STABLE
386 int decode_pldm_package_header_info(
387 	const uint8_t *data, size_t length,
388 	struct pldm_package_header_information *package_header_info,
389 	struct variable_field *package_version_str)
390 {
391 	int rc;
392 
393 	rc = decode_pldm_package_header_info_errno(
394 		data, length, package_header_info, package_version_str);
395 	if (rc < 0) {
396 		return pldm_xlate_errno(rc);
397 	}
398 
399 	return PLDM_SUCCESS;
400 }
401 
402 static int decode_firmware_device_id_record_errno(
403 	const void *data, size_t length, uint16_t component_bitmap_bit_length,
404 	struct pldm_firmware_device_id_record *fw_device_id_record,
405 	struct variable_field *applicable_components,
406 	struct variable_field *comp_image_set_version_str,
407 	struct variable_field *record_descriptors,
408 	struct variable_field *fw_device_pkg_data)
409 {
410 	if (data == NULL || fw_device_id_record == NULL ||
411 	    applicable_components == NULL ||
412 	    comp_image_set_version_str == NULL || record_descriptors == NULL ||
413 	    fw_device_pkg_data == NULL) {
414 		return -EINVAL;
415 	}
416 
417 	if (length < sizeof(struct pldm_firmware_device_id_record)) {
418 		return -EOVERFLOW;
419 	}
420 
421 	if ((component_bitmap_bit_length %
422 	     PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
423 		return -EBADMSG;
424 	}
425 
426 	struct pldm_firmware_device_id_record *data_record =
427 		(struct pldm_firmware_device_id_record *)(data);
428 
429 	if (!is_string_type_valid(
430 		    data_record->comp_image_set_version_string_type) ||
431 	    (data_record->comp_image_set_version_string_length == 0)) {
432 		return -EBADMSG;
433 	}
434 
435 	fw_device_id_record->record_length =
436 		le16toh(data_record->record_length);
437 	fw_device_id_record->descriptor_count = data_record->descriptor_count;
438 	fw_device_id_record->device_update_option_flags.value =
439 		le32toh(data_record->device_update_option_flags.value);
440 	fw_device_id_record->comp_image_set_version_string_type =
441 		data_record->comp_image_set_version_string_type;
442 	fw_device_id_record->comp_image_set_version_string_length =
443 		data_record->comp_image_set_version_string_length;
444 	fw_device_id_record->fw_device_pkg_data_length =
445 		le16toh(data_record->fw_device_pkg_data_length);
446 
447 	if (length < fw_device_id_record->record_length) {
448 		return -EOVERFLOW;
449 	}
450 
451 	uint16_t applicable_components_length =
452 		component_bitmap_bit_length /
453 		PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
454 	size_t calc_min_record_length =
455 		sizeof(struct pldm_firmware_device_id_record) +
456 		applicable_components_length +
457 		data_record->comp_image_set_version_string_length +
458 		PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
459 		fw_device_id_record->fw_device_pkg_data_length;
460 
461 	if (fw_device_id_record->record_length < calc_min_record_length) {
462 		return -EOVERFLOW;
463 	}
464 
465 	applicable_components->ptr =
466 		(const uint8_t *)data +
467 		sizeof(struct pldm_firmware_device_id_record);
468 	applicable_components->length = applicable_components_length;
469 
470 	comp_image_set_version_str->ptr =
471 		applicable_components->ptr + applicable_components->length;
472 	comp_image_set_version_str->length =
473 		fw_device_id_record->comp_image_set_version_string_length;
474 
475 	record_descriptors->ptr = comp_image_set_version_str->ptr +
476 				  comp_image_set_version_str->length;
477 	record_descriptors->length =
478 		fw_device_id_record->record_length -
479 		sizeof(struct pldm_firmware_device_id_record) -
480 		applicable_components_length -
481 		fw_device_id_record->comp_image_set_version_string_length -
482 		fw_device_id_record->fw_device_pkg_data_length;
483 
484 	if (fw_device_id_record->fw_device_pkg_data_length) {
485 		fw_device_pkg_data->ptr =
486 			record_descriptors->ptr + record_descriptors->length;
487 		fw_device_pkg_data->length =
488 			fw_device_id_record->fw_device_pkg_data_length;
489 	}
490 
491 	return 0;
492 }
493 
494 LIBPLDM_ABI_STABLE
495 int decode_firmware_device_id_record(
496 	const uint8_t *data, size_t length,
497 	uint16_t component_bitmap_bit_length,
498 	struct pldm_firmware_device_id_record *fw_device_id_record,
499 	struct variable_field *applicable_components,
500 	struct variable_field *comp_image_set_version_str,
501 	struct variable_field *record_descriptors,
502 	struct variable_field *fw_device_pkg_data)
503 {
504 	int rc;
505 
506 	rc = decode_firmware_device_id_record_errno(
507 		data, length, component_bitmap_bit_length, fw_device_id_record,
508 		applicable_components, comp_image_set_version_str,
509 		record_descriptors, fw_device_pkg_data);
510 	if (rc < 0) {
511 		return pldm_xlate_errno(rc);
512 	}
513 
514 	return PLDM_SUCCESS;
515 }
516 
517 LIBPLDM_ABI_STABLE
518 int decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter *iter,
519 				     struct pldm_descriptor *desc)
520 {
521 	PLDM_MSGBUF_DEFINE_P(buf);
522 	int rc;
523 
524 	if (!iter || !iter->field || !desc) {
525 		return -EINVAL;
526 	}
527 
528 	rc = pldm_msgbuf_init_errno(buf, PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN,
529 				    iter->field->ptr, iter->field->length);
530 	if (rc) {
531 		return rc;
532 	}
533 
534 	pldm_msgbuf_extract(buf, desc->descriptor_type);
535 	rc = pldm_msgbuf_extract(buf, desc->descriptor_length);
536 	if (rc) {
537 		return pldm_msgbuf_discard(buf, rc);
538 	}
539 
540 	desc->descriptor_data = NULL;
541 	pldm_msgbuf_span_required(buf, desc->descriptor_length,
542 				  (void **)&desc->descriptor_data);
543 	iter->field->ptr = NULL;
544 	pldm_msgbuf_span_remaining(buf, (void **)&iter->field->ptr,
545 				   &iter->field->length);
546 
547 	return pldm_msgbuf_complete(buf);
548 }
549 
550 static int decode_descriptor_type_length_value_errno(
551 	const void *data, size_t length, uint16_t *descriptor_type,
552 	struct variable_field *descriptor_data)
553 {
554 	uint16_t descriptor_length = 0;
555 
556 	if (data == NULL || descriptor_type == NULL ||
557 	    descriptor_data == NULL) {
558 		return -EINVAL;
559 	}
560 
561 	if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
562 		return -EOVERFLOW;
563 	}
564 
565 	struct pldm_descriptor_tlv *entry =
566 		(struct pldm_descriptor_tlv *)(data);
567 
568 	*descriptor_type = le16toh(entry->descriptor_type);
569 	descriptor_length = le16toh(entry->descriptor_length);
570 	if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
571 		if (descriptor_length !=
572 		    get_descriptor_type_length(*descriptor_type)) {
573 			return -EBADMSG;
574 		}
575 	}
576 
577 	if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
578 		      descriptor_length)) {
579 		return -EOVERFLOW;
580 	}
581 
582 	descriptor_data->ptr = entry->descriptor_data;
583 	descriptor_data->length = descriptor_length;
584 
585 	return 0;
586 }
587 
588 LIBPLDM_ABI_STABLE
589 int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
590 					uint16_t *descriptor_type,
591 					struct variable_field *descriptor_data)
592 {
593 	int rc;
594 
595 	rc = decode_descriptor_type_length_value_errno(
596 		data, length, descriptor_type, descriptor_data);
597 	if (rc < 0) {
598 		return pldm_xlate_errno(rc);
599 	}
600 
601 	return PLDM_SUCCESS;
602 }
603 
604 static int decode_vendor_defined_descriptor_value_errno(
605 	const void *data, size_t length, uint8_t *descriptor_title_str_type,
606 	struct variable_field *descriptor_title_str,
607 	struct variable_field *descriptor_data)
608 {
609 	if (data == NULL || descriptor_title_str_type == NULL ||
610 	    descriptor_title_str == NULL || descriptor_data == NULL) {
611 		return -EINVAL;
612 	}
613 
614 	if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
615 		return -EOVERFLOW;
616 	}
617 
618 	struct pldm_vendor_defined_descriptor_title_data *entry =
619 		(struct pldm_vendor_defined_descriptor_title_data *)(data);
620 	if (!is_string_type_valid(
621 		    entry->vendor_defined_descriptor_title_str_type) ||
622 	    (entry->vendor_defined_descriptor_title_str_len == 0)) {
623 		return -EBADMSG;
624 	}
625 
626 	// Assuming at least 1 byte of VendorDefinedDescriptorData
627 	if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
628 		      entry->vendor_defined_descriptor_title_str_len)) {
629 		return -EOVERFLOW;
630 	}
631 
632 	*descriptor_title_str_type =
633 		entry->vendor_defined_descriptor_title_str_type;
634 	descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
635 	descriptor_title_str->length =
636 		entry->vendor_defined_descriptor_title_str_len;
637 
638 	descriptor_data->ptr =
639 		descriptor_title_str->ptr + descriptor_title_str->length;
640 	descriptor_data->length =
641 		length -
642 		sizeof(entry->vendor_defined_descriptor_title_str_type) -
643 		sizeof(entry->vendor_defined_descriptor_title_str_len) -
644 		descriptor_title_str->length;
645 
646 	return 0;
647 }
648 
649 LIBPLDM_ABI_STABLE
650 int decode_vendor_defined_descriptor_value(
651 	const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
652 	struct variable_field *descriptor_title_str,
653 	struct variable_field *descriptor_data)
654 {
655 	int rc;
656 
657 	rc = decode_vendor_defined_descriptor_value_errno(
658 		data, length, descriptor_title_str_type, descriptor_title_str,
659 		descriptor_data);
660 	if (rc < 0) {
661 		return pldm_xlate_errno(rc);
662 	}
663 
664 	return PLDM_SUCCESS;
665 }
666 
667 static int decode_pldm_comp_image_info_errno(
668 	const void *data, size_t length,
669 	struct pldm_component_image_information *pldm_comp_image_info,
670 	struct variable_field *comp_version_str)
671 {
672 	if (data == NULL || pldm_comp_image_info == NULL ||
673 	    comp_version_str == NULL) {
674 		return -EINVAL;
675 	}
676 
677 	if (length < sizeof(struct pldm_component_image_information)) {
678 		return -EOVERFLOW;
679 	}
680 
681 	struct pldm_component_image_information *data_header =
682 		(struct pldm_component_image_information *)(data);
683 
684 	if (!is_string_type_valid(data_header->comp_version_string_type) ||
685 	    (data_header->comp_version_string_length == 0)) {
686 		return -EBADMSG;
687 	}
688 
689 	if (length < sizeof(struct pldm_component_image_information) +
690 			     data_header->comp_version_string_length) {
691 		return -EOVERFLOW;
692 	}
693 
694 	pldm_comp_image_info->comp_classification =
695 		le16toh(data_header->comp_classification);
696 	pldm_comp_image_info->comp_identifier =
697 		le16toh(data_header->comp_identifier);
698 	pldm_comp_image_info->comp_comparison_stamp =
699 		le32toh(data_header->comp_comparison_stamp);
700 	pldm_comp_image_info->comp_options.value =
701 		le16toh(data_header->comp_options.value);
702 	pldm_comp_image_info->requested_comp_activation_method.value =
703 		le16toh(data_header->requested_comp_activation_method.value);
704 	pldm_comp_image_info->comp_location_offset =
705 		le32toh(data_header->comp_location_offset);
706 	pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
707 	pldm_comp_image_info->comp_version_string_type =
708 		data_header->comp_version_string_type;
709 	pldm_comp_image_info->comp_version_string_length =
710 		data_header->comp_version_string_length;
711 
712 	if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
713 	     pldm_comp_image_info->comp_comparison_stamp !=
714 		     PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
715 		return -EBADMSG;
716 	}
717 
718 	if (pldm_comp_image_info->comp_location_offset == 0 ||
719 	    pldm_comp_image_info->comp_size == 0) {
720 		return -EBADMSG;
721 	}
722 
723 	comp_version_str->ptr = (const uint8_t *)data +
724 				sizeof(struct pldm_component_image_information);
725 	comp_version_str->length =
726 		pldm_comp_image_info->comp_version_string_length;
727 
728 	return 0;
729 }
730 
731 LIBPLDM_ABI_STABLE
732 int decode_pldm_comp_image_info(
733 	const uint8_t *data, size_t length,
734 	struct pldm_component_image_information *pldm_comp_image_info,
735 	struct variable_field *comp_version_str)
736 {
737 	int rc;
738 
739 	rc = decode_pldm_comp_image_info_errno(
740 		data, length, pldm_comp_image_info, comp_version_str);
741 	if (rc < 0) {
742 		return pldm_xlate_errno(rc);
743 	}
744 
745 	return PLDM_SUCCESS;
746 }
747 
748 LIBPLDM_ABI_STABLE
749 int encode_query_device_identifiers_req(uint8_t instance_id,
750 					size_t payload_length,
751 					struct pldm_msg *msg)
752 {
753 	if (msg == NULL) {
754 		return PLDM_ERROR_INVALID_DATA;
755 	}
756 
757 	if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
758 		return PLDM_ERROR_INVALID_LENGTH;
759 	}
760 
761 	return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
762 				       PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
763 }
764 
765 LIBPLDM_ABI_STABLE
766 int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
767 					 size_t payload_length,
768 					 uint8_t *completion_code,
769 					 uint32_t *device_identifiers_len,
770 					 uint8_t *descriptor_count,
771 					 uint8_t **descriptor_data)
772 {
773 	if (msg == NULL || completion_code == NULL ||
774 	    device_identifiers_len == NULL || descriptor_count == NULL ||
775 	    descriptor_data == NULL) {
776 		return PLDM_ERROR_INVALID_DATA;
777 	}
778 
779 	*completion_code = msg->payload[0];
780 	if (PLDM_SUCCESS != *completion_code) {
781 		return PLDM_SUCCESS;
782 	}
783 
784 	if (payload_length <
785 	    sizeof(struct pldm_query_device_identifiers_resp)) {
786 		return PLDM_ERROR_INVALID_LENGTH;
787 	}
788 
789 	struct pldm_query_device_identifiers_resp *response =
790 		(struct pldm_query_device_identifiers_resp *)msg->payload;
791 	*device_identifiers_len = le32toh(response->device_identifiers_len);
792 
793 	if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
794 		return PLDM_ERROR_INVALID_LENGTH;
795 	}
796 
797 	if (payload_length !=
798 	    sizeof(struct pldm_query_device_identifiers_resp) +
799 		    *device_identifiers_len) {
800 		return PLDM_ERROR_INVALID_LENGTH;
801 	}
802 	*descriptor_count = response->descriptor_count;
803 
804 	if (*descriptor_count == 0) {
805 		return PLDM_ERROR_INVALID_DATA;
806 	}
807 	*descriptor_data =
808 		(uint8_t *)(msg->payload +
809 			    sizeof(struct pldm_query_device_identifiers_resp));
810 	return PLDM_SUCCESS;
811 }
812 
813 LIBPLDM_ABI_TESTING
814 int encode_query_device_identifiers_resp(
815 	uint8_t instance_id, uint8_t descriptor_count,
816 	const struct pldm_descriptor *descriptors, struct pldm_msg *msg,
817 	size_t *payload_length)
818 {
819 	PLDM_MSGBUF_DEFINE_P(buf);
820 	int rc;
821 
822 	if (descriptors == NULL || msg == NULL || payload_length == NULL) {
823 		return -EINVAL;
824 	}
825 
826 	if (descriptor_count < 1) {
827 		return -EINVAL;
828 	}
829 
830 	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
831 				     PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
832 	if (rc) {
833 		return -EINVAL;
834 	}
835 
836 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
837 	if (rc) {
838 		return rc;
839 	}
840 
841 	/* Determine total length */
842 	uint32_t device_identifiers_len = 0;
843 	for (uint8_t i = 0; i < descriptor_count; i++) {
844 		const struct pldm_descriptor *d = &descriptors[i];
845 		device_identifiers_len +=
846 			2 * sizeof(uint16_t) + d->descriptor_length;
847 	}
848 
849 	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
850 	pldm_msgbuf_insert(buf, device_identifiers_len);
851 	pldm_msgbuf_insert(buf, descriptor_count);
852 
853 	for (uint8_t i = 0; i < descriptor_count; i++) {
854 		const struct pldm_descriptor *d = &descriptors[i];
855 		pldm_msgbuf_insert(buf, d->descriptor_type);
856 		pldm_msgbuf_insert(buf, d->descriptor_length);
857 		if (d->descriptor_data == NULL) {
858 			return pldm_msgbuf_discard(buf, -EINVAL);
859 		}
860 		rc = pldm_msgbuf_insert_array(
861 			buf, d->descriptor_length,
862 			(const uint8_t *)d->descriptor_data,
863 			d->descriptor_length);
864 		if (rc) {
865 			return pldm_msgbuf_discard(buf, rc);
866 		}
867 	}
868 
869 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
870 }
871 
872 LIBPLDM_ABI_STABLE
873 int encode_get_firmware_parameters_req(uint8_t instance_id,
874 				       size_t payload_length,
875 				       struct pldm_msg *msg)
876 {
877 	if (msg == NULL) {
878 		return PLDM_ERROR_INVALID_DATA;
879 	}
880 
881 	if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
882 		return PLDM_ERROR_INVALID_LENGTH;
883 	}
884 
885 	return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
886 				       PLDM_GET_FIRMWARE_PARAMETERS, msg);
887 }
888 
889 LIBPLDM_ABI_STABLE
890 int decode_get_firmware_parameters_resp(
891 	const struct pldm_msg *msg, size_t payload_length,
892 	struct pldm_get_firmware_parameters_resp *resp_data,
893 	struct variable_field *active_comp_image_set_ver_str,
894 	struct variable_field *pending_comp_image_set_ver_str,
895 	struct variable_field *comp_parameter_table)
896 {
897 	if (msg == NULL || resp_data == NULL ||
898 	    active_comp_image_set_ver_str == NULL ||
899 	    pending_comp_image_set_ver_str == NULL ||
900 	    comp_parameter_table == NULL || !payload_length) {
901 		return PLDM_ERROR_INVALID_DATA;
902 	}
903 
904 	resp_data->completion_code = msg->payload[0];
905 	if (PLDM_SUCCESS != resp_data->completion_code) {
906 		return PLDM_SUCCESS;
907 	}
908 
909 	if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
910 		return PLDM_ERROR_INVALID_LENGTH;
911 	}
912 
913 	struct pldm_get_firmware_parameters_resp *response =
914 		(struct pldm_get_firmware_parameters_resp *)msg->payload;
915 
916 	if (!is_string_type_valid(
917 		    response->active_comp_image_set_ver_str_type) ||
918 	    (response->active_comp_image_set_ver_str_len == 0)) {
919 		return PLDM_ERROR_INVALID_DATA;
920 	}
921 
922 	if (response->pending_comp_image_set_ver_str_len == 0) {
923 		if (response->pending_comp_image_set_ver_str_type !=
924 		    PLDM_STR_TYPE_UNKNOWN) {
925 			return PLDM_ERROR_INVALID_DATA;
926 		}
927 	} else {
928 		if (!is_string_type_valid(
929 			    response->pending_comp_image_set_ver_str_type)) {
930 			return PLDM_ERROR_INVALID_DATA;
931 		}
932 	}
933 
934 	size_t partial_response_length =
935 		sizeof(struct pldm_get_firmware_parameters_resp) +
936 		response->active_comp_image_set_ver_str_len +
937 		response->pending_comp_image_set_ver_str_len;
938 
939 	if (payload_length < partial_response_length) {
940 		return PLDM_ERROR_INVALID_LENGTH;
941 	}
942 
943 	resp_data->capabilities_during_update.value =
944 		le32toh(response->capabilities_during_update.value);
945 	resp_data->comp_count = le16toh(response->comp_count);
946 	resp_data->active_comp_image_set_ver_str_type =
947 		response->active_comp_image_set_ver_str_type;
948 	resp_data->active_comp_image_set_ver_str_len =
949 		response->active_comp_image_set_ver_str_len;
950 	resp_data->pending_comp_image_set_ver_str_type =
951 		response->pending_comp_image_set_ver_str_type;
952 	resp_data->pending_comp_image_set_ver_str_len =
953 		response->pending_comp_image_set_ver_str_len;
954 
955 	active_comp_image_set_ver_str->ptr =
956 		msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
957 	active_comp_image_set_ver_str->length =
958 		resp_data->active_comp_image_set_ver_str_len;
959 
960 	if (resp_data->pending_comp_image_set_ver_str_len != 0) {
961 		pending_comp_image_set_ver_str->ptr =
962 			msg->payload +
963 			sizeof(struct pldm_get_firmware_parameters_resp) +
964 			resp_data->active_comp_image_set_ver_str_len;
965 		pending_comp_image_set_ver_str->length =
966 			resp_data->pending_comp_image_set_ver_str_len;
967 	} else {
968 		pending_comp_image_set_ver_str->ptr = NULL;
969 		pending_comp_image_set_ver_str->length = 0;
970 	}
971 
972 	if (payload_length > partial_response_length && resp_data->comp_count) {
973 		comp_parameter_table->ptr =
974 			msg->payload +
975 			sizeof(struct pldm_get_firmware_parameters_resp) +
976 			resp_data->active_comp_image_set_ver_str_len +
977 			resp_data->pending_comp_image_set_ver_str_len;
978 		comp_parameter_table->length =
979 			payload_length - partial_response_length;
980 	} else {
981 		comp_parameter_table->ptr = NULL;
982 		comp_parameter_table->length = 0;
983 	}
984 
985 	return PLDM_SUCCESS;
986 }
987 
988 LIBPLDM_ABI_TESTING
989 int encode_get_firmware_parameters_resp(
990 	uint8_t instance_id,
991 	const struct pldm_get_firmware_parameters_resp_full *resp_data,
992 	struct pldm_msg *msg, size_t *payload_length)
993 {
994 	PLDM_MSGBUF_DEFINE_P(buf);
995 	int rc;
996 
997 	if (resp_data == NULL || msg == NULL || payload_length == NULL) {
998 		return -EINVAL;
999 	}
1000 
1001 	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
1002 				     PLDM_GET_FIRMWARE_PARAMETERS, msg);
1003 	if (rc) {
1004 		return -EINVAL;
1005 	}
1006 
1007 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1008 	if (rc) {
1009 		return rc;
1010 	}
1011 
1012 	pldm_msgbuf_insert(buf, resp_data->completion_code);
1013 	pldm_msgbuf_insert(buf, resp_data->capabilities_during_update.value);
1014 	pldm_msgbuf_insert(buf, resp_data->comp_count);
1015 	pldm_msgbuf_insert(buf,
1016 			   resp_data->active_comp_image_set_ver_str.str_type);
1017 	pldm_msgbuf_insert(buf,
1018 			   resp_data->active_comp_image_set_ver_str.str_len);
1019 	pldm_msgbuf_insert(buf,
1020 			   resp_data->pending_comp_image_set_ver_str.str_type);
1021 	pldm_msgbuf_insert(buf,
1022 			   resp_data->pending_comp_image_set_ver_str.str_len);
1023 	/* String data appended */
1024 	rc = pldm_msgbuf_insert_array(
1025 		buf, resp_data->active_comp_image_set_ver_str.str_len,
1026 		resp_data->active_comp_image_set_ver_str.str_data,
1027 		resp_data->active_comp_image_set_ver_str.str_len);
1028 	if (rc) {
1029 		return pldm_msgbuf_discard(buf, rc);
1030 	}
1031 	rc = pldm_msgbuf_insert_array(
1032 		buf, resp_data->pending_comp_image_set_ver_str.str_len,
1033 		resp_data->pending_comp_image_set_ver_str.str_data,
1034 		resp_data->pending_comp_image_set_ver_str.str_len);
1035 	if (rc) {
1036 		return pldm_msgbuf_discard(buf, rc);
1037 	}
1038 
1039 	/* Further calls to encode_get_firmware_parameters_resp_comp_entry
1040 	 * will populate the remainder */
1041 
1042 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1043 }
1044 
1045 LIBPLDM_ABI_TESTING
1046 int encode_get_firmware_parameters_resp_comp_entry(
1047 	const struct pldm_component_parameter_entry_full *comp,
1048 	uint8_t *payload, size_t *payload_length)
1049 {
1050 	PLDM_MSGBUF_DEFINE_P(buf);
1051 	int rc;
1052 
1053 	if (comp == NULL || payload == NULL || payload_length == NULL) {
1054 		return -EINVAL;
1055 	}
1056 
1057 	rc = pldm_msgbuf_init_errno(buf, 0, payload, *payload_length);
1058 	if (rc) {
1059 		return rc;
1060 	}
1061 
1062 	pldm_msgbuf_insert(buf, comp->comp_classification);
1063 	pldm_msgbuf_insert(buf, comp->comp_identifier);
1064 	pldm_msgbuf_insert(buf, comp->comp_classification_index);
1065 
1066 	pldm_msgbuf_insert(buf, comp->active_ver.comparison_stamp);
1067 	pldm_msgbuf_insert(buf, (uint8_t)comp->active_ver.str.str_type);
1068 	pldm_msgbuf_insert(buf, comp->active_ver.str.str_len);
1069 	rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1070 				      comp->active_ver.date,
1071 				      PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
1072 	if (rc) {
1073 		return pldm_msgbuf_discard(buf, rc);
1074 	}
1075 
1076 	pldm_msgbuf_insert(buf, comp->pending_ver.comparison_stamp);
1077 	pldm_msgbuf_insert(buf, (uint8_t)comp->pending_ver.str.str_type);
1078 	pldm_msgbuf_insert(buf, comp->pending_ver.str.str_len);
1079 	rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1080 				      comp->pending_ver.date,
1081 				      PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
1082 	if (rc) {
1083 		return pldm_msgbuf_discard(buf, rc);
1084 	}
1085 
1086 	pldm_msgbuf_insert(buf, comp->comp_activation_methods.value);
1087 	pldm_msgbuf_insert(buf, comp->capabilities_during_update.value);
1088 
1089 	rc = pldm_msgbuf_insert_array(buf, comp->active_ver.str.str_len,
1090 				      comp->active_ver.str.str_data,
1091 				      comp->active_ver.str.str_len);
1092 	if (rc) {
1093 		return pldm_msgbuf_discard(buf, rc);
1094 	}
1095 	rc = pldm_msgbuf_insert_array(buf, comp->pending_ver.str.str_len,
1096 				      comp->pending_ver.str.str_data,
1097 				      comp->pending_ver.str.str_len);
1098 	if (rc) {
1099 		return pldm_msgbuf_discard(buf, rc);
1100 	}
1101 
1102 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1103 }
1104 
1105 LIBPLDM_ABI_STABLE
1106 int decode_get_firmware_parameters_resp_comp_entry(
1107 	const uint8_t *data, size_t length,
1108 	struct pldm_component_parameter_entry *component_data,
1109 	struct variable_field *active_comp_ver_str,
1110 	struct variable_field *pending_comp_ver_str)
1111 {
1112 	if (data == NULL || component_data == NULL ||
1113 	    active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
1114 		return PLDM_ERROR_INVALID_DATA;
1115 	}
1116 
1117 	if (length < sizeof(struct pldm_component_parameter_entry)) {
1118 		return PLDM_ERROR_INVALID_LENGTH;
1119 	}
1120 
1121 	struct pldm_component_parameter_entry *entry =
1122 		(struct pldm_component_parameter_entry *)(data);
1123 
1124 	size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
1125 			      entry->active_comp_ver_str_len +
1126 			      entry->pending_comp_ver_str_len;
1127 
1128 	if (length < entry_length) {
1129 		return PLDM_ERROR_INVALID_LENGTH;
1130 	}
1131 
1132 	component_data->comp_classification =
1133 		le16toh(entry->comp_classification);
1134 	component_data->comp_identifier = le16toh(entry->comp_identifier);
1135 	component_data->comp_classification_index =
1136 		entry->comp_classification_index;
1137 	component_data->active_comp_comparison_stamp =
1138 		le32toh(entry->active_comp_comparison_stamp);
1139 	component_data->active_comp_ver_str_type =
1140 		entry->active_comp_ver_str_type;
1141 	component_data->active_comp_ver_str_len =
1142 		entry->active_comp_ver_str_len;
1143 	memcpy(component_data->active_comp_release_date,
1144 	       entry->active_comp_release_date,
1145 	       sizeof(entry->active_comp_release_date));
1146 	component_data->pending_comp_comparison_stamp =
1147 		le32toh(entry->pending_comp_comparison_stamp);
1148 	component_data->pending_comp_ver_str_type =
1149 		entry->pending_comp_ver_str_type;
1150 	component_data->pending_comp_ver_str_len =
1151 		entry->pending_comp_ver_str_len;
1152 	memcpy(component_data->pending_comp_release_date,
1153 	       entry->pending_comp_release_date,
1154 	       sizeof(entry->pending_comp_release_date));
1155 	component_data->comp_activation_methods.value =
1156 		le16toh(entry->comp_activation_methods.value);
1157 	component_data->capabilities_during_update.value =
1158 		le32toh(entry->capabilities_during_update.value);
1159 
1160 	if (entry->active_comp_ver_str_len != 0) {
1161 		active_comp_ver_str->ptr =
1162 			data + sizeof(struct pldm_component_parameter_entry);
1163 		active_comp_ver_str->length = entry->active_comp_ver_str_len;
1164 	} else {
1165 		active_comp_ver_str->ptr = NULL;
1166 		active_comp_ver_str->length = 0;
1167 	}
1168 
1169 	if (entry->pending_comp_ver_str_len != 0) {
1170 		pending_comp_ver_str->ptr =
1171 			data + sizeof(struct pldm_component_parameter_entry) +
1172 			entry->active_comp_ver_str_len;
1173 		pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
1174 	} else {
1175 		pending_comp_ver_str->ptr = NULL;
1176 		pending_comp_ver_str->length = 0;
1177 	}
1178 	return PLDM_SUCCESS;
1179 }
1180 
1181 LIBPLDM_ABI_STABLE
1182 int encode_query_downstream_devices_req(uint8_t instance_id,
1183 					struct pldm_msg *msg)
1184 {
1185 	if (msg == NULL) {
1186 		return -EINVAL;
1187 	}
1188 
1189 	return encode_pldm_header_only_errno(PLDM_REQUEST, instance_id,
1190 					     PLDM_FWUP,
1191 					     PLDM_QUERY_DOWNSTREAM_DEVICES,
1192 					     msg);
1193 }
1194 
1195 LIBPLDM_ABI_STABLE
1196 int decode_query_downstream_devices_resp(
1197 	const struct pldm_msg *msg, size_t payload_length,
1198 	struct pldm_query_downstream_devices_resp *resp_data)
1199 {
1200 	PLDM_MSGBUF_DEFINE_P(buf);
1201 	int rc;
1202 
1203 	if (msg == NULL || resp_data == NULL || !payload_length) {
1204 		return -EINVAL;
1205 	}
1206 
1207 	rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1208 				    msg->payload, payload_length);
1209 	if (rc) {
1210 		return rc;
1211 	}
1212 
1213 	rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1214 	if (rc) {
1215 		return pldm_msgbuf_discard(buf, rc);
1216 	}
1217 	if (PLDM_SUCCESS != resp_data->completion_code) {
1218 		// Return the CC directly without decoding the rest of the payload
1219 		return pldm_msgbuf_complete(buf);
1220 	}
1221 
1222 	if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) {
1223 		return pldm_msgbuf_discard(buf, -EBADMSG);
1224 	}
1225 
1226 	rc = pldm_msgbuf_extract(buf,
1227 				 resp_data->downstream_device_update_supported);
1228 	if (rc) {
1229 		return pldm_msgbuf_discard(buf, rc);
1230 	}
1231 
1232 	if (!is_downstream_device_update_support_valid(
1233 		    resp_data->downstream_device_update_supported)) {
1234 		return pldm_msgbuf_discard(buf, -EINVAL);
1235 	}
1236 
1237 	pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
1238 	pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices);
1239 	pldm_msgbuf_extract(buf, resp_data->capabilities.value);
1240 
1241 	return pldm_msgbuf_complete_consumed(buf);
1242 }
1243 
1244 LIBPLDM_ABI_STABLE
1245 int encode_query_downstream_identifiers_req(
1246 	uint8_t instance_id,
1247 	const struct pldm_query_downstream_identifiers_req *params_req,
1248 	struct pldm_msg *msg, size_t payload_length)
1249 {
1250 	PLDM_MSGBUF_DEFINE_P(buf);
1251 	int rc;
1252 
1253 	if (!msg || !params_req) {
1254 		return -EINVAL;
1255 	}
1256 
1257 	if (!is_transfer_operation_flag_valid(
1258 		    (enum transfer_op_flag)
1259 			    params_req->transfer_operation_flag)) {
1260 		return -EINVAL;
1261 	}
1262 
1263 	struct pldm_header_info header = { 0 };
1264 	header.instance = instance_id;
1265 	header.msg_type = PLDM_REQUEST;
1266 	header.pldm_type = PLDM_FWUP;
1267 	header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS;
1268 	rc = pack_pldm_header_errno(&header, &(msg->hdr));
1269 	if (rc) {
1270 		return rc;
1271 	}
1272 
1273 	rc = pldm_msgbuf_init_errno(buf,
1274 				    PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES,
1275 				    msg->payload, payload_length);
1276 	if (rc) {
1277 		return rc;
1278 	}
1279 
1280 	pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
1281 	// Data correctness has been verified, cast it to 1-byte data directly.
1282 	pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
1283 
1284 	return pldm_msgbuf_complete(buf);
1285 }
1286 
1287 LIBPLDM_ABI_STABLE
1288 int decode_query_downstream_identifiers_resp(
1289 	const struct pldm_msg *msg, size_t payload_length,
1290 	struct pldm_query_downstream_identifiers_resp *resp_data,
1291 	struct pldm_downstream_device_iter *iter)
1292 {
1293 	PLDM_MSGBUF_DEFINE_P(buf);
1294 	void *remaining = NULL;
1295 	int rc = 0;
1296 
1297 	if (msg == NULL || resp_data == NULL || iter == NULL ||
1298 	    !payload_length) {
1299 		return -EINVAL;
1300 	}
1301 
1302 	rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1303 				    msg->payload, payload_length);
1304 	if (rc) {
1305 		return rc;
1306 	}
1307 
1308 	rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1309 	if (rc) {
1310 		return pldm_msgbuf_discard(buf, rc);
1311 	}
1312 	if (PLDM_SUCCESS != resp_data->completion_code) {
1313 		return pldm_msgbuf_complete(buf);
1314 	}
1315 
1316 	if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) {
1317 		return pldm_msgbuf_discard(buf, -EBADMSG);
1318 	}
1319 
1320 	pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1321 	pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1322 
1323 	rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length);
1324 	if (rc) {
1325 		return pldm_msgbuf_discard(buf, rc);
1326 	}
1327 
1328 	pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
1329 	pldm_msgbuf_span_required(buf, resp_data->downstream_devices_length,
1330 				  &remaining);
1331 
1332 	rc = pldm_msgbuf_complete(buf);
1333 	if (rc) {
1334 		return rc;
1335 	}
1336 
1337 	iter->field.ptr = remaining;
1338 	iter->field.length = resp_data->downstream_devices_length;
1339 	iter->devs = resp_data->number_of_downstream_devices;
1340 
1341 	return 0;
1342 }
1343 
1344 LIBPLDM_ABI_STABLE
1345 int decode_pldm_downstream_device_from_iter(
1346 	struct pldm_downstream_device_iter *iter,
1347 	struct pldm_downstream_device *dev)
1348 {
1349 	PLDM_MSGBUF_DEFINE_P(buf);
1350 	int rc;
1351 
1352 	if (!iter || !iter->field.ptr || !dev) {
1353 		return -EINVAL;
1354 	}
1355 
1356 	rc = pldm_msgbuf_init_errno(buf, 3, iter->field.ptr,
1357 				    iter->field.length);
1358 	if (rc) {
1359 		return rc;
1360 	}
1361 
1362 	pldm_msgbuf_extract(buf, dev->downstream_device_index);
1363 	pldm_msgbuf_extract(buf, dev->downstream_descriptor_count);
1364 	pldm_msgbuf_span_remaining(buf, (void **)&iter->field.ptr,
1365 				   &iter->field.length);
1366 
1367 	return pldm_msgbuf_complete(buf);
1368 }
1369 
1370 LIBPLDM_ABI_STABLE
1371 int encode_get_downstream_firmware_parameters_req(
1372 	uint8_t instance_id,
1373 	const struct pldm_get_downstream_firmware_parameters_req *params_req,
1374 	struct pldm_msg *msg, size_t payload_length)
1375 {
1376 	PLDM_MSGBUF_DEFINE_P(buf);
1377 	int rc;
1378 
1379 	if (!msg || !params_req) {
1380 		return -EINVAL;
1381 	}
1382 
1383 	if (!is_transfer_operation_flag_valid(
1384 		    (enum transfer_op_flag)
1385 			    params_req->transfer_operation_flag)) {
1386 		return -EBADMSG;
1387 	}
1388 
1389 	struct pldm_header_info header = { 0 };
1390 	header.instance = instance_id;
1391 	header.msg_type = PLDM_REQUEST;
1392 	header.pldm_type = PLDM_FWUP;
1393 	header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS;
1394 	rc = pack_pldm_header_errno(&header, &msg->hdr);
1395 	if (rc < 0) {
1396 		return rc;
1397 	}
1398 
1399 	rc = pldm_msgbuf_init_errno(
1400 		buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES,
1401 		msg->payload, payload_length);
1402 	if (rc < 0) {
1403 		return rc;
1404 	}
1405 
1406 	pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
1407 	// Data correctness has been verified, cast it to 1-byte data directly.
1408 	pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
1409 
1410 	return pldm_msgbuf_complete(buf);
1411 }
1412 
1413 LIBPLDM_ABI_STABLE
1414 int decode_get_downstream_firmware_parameters_resp(
1415 	const struct pldm_msg *msg, size_t payload_length,
1416 	struct pldm_get_downstream_firmware_parameters_resp *resp_data,
1417 	struct pldm_downstream_device_parameters_iter *iter)
1418 {
1419 	PLDM_MSGBUF_DEFINE_P(buf);
1420 	void *remaining = NULL;
1421 	size_t length;
1422 	int rc;
1423 
1424 	if (msg == NULL || resp_data == NULL || iter == NULL) {
1425 		return -EINVAL;
1426 	}
1427 
1428 	rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1429 				    msg->payload, payload_length);
1430 	if (rc < 0) {
1431 		return rc;
1432 	}
1433 
1434 	rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1435 	if (rc < 0) {
1436 		return pldm_msgbuf_discard(buf, rc);
1437 	}
1438 	if (PLDM_SUCCESS != resp_data->completion_code) {
1439 		return pldm_msgbuf_complete(buf);
1440 	}
1441 
1442 	if (payload_length <
1443 	    PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN) {
1444 		return pldm_msgbuf_discard(buf, -EBADMSG);
1445 	}
1446 
1447 	pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1448 	pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1449 	pldm_msgbuf_extract(buf,
1450 			    resp_data->fdp_capabilities_during_update.value);
1451 	pldm_msgbuf_extract(buf, resp_data->downstream_device_count);
1452 
1453 	rc = pldm_msgbuf_span_remaining(buf, &remaining, &length);
1454 	if (rc) {
1455 		return pldm_msgbuf_discard(buf, rc);
1456 	}
1457 
1458 	rc = pldm_msgbuf_complete(buf);
1459 	if (rc) {
1460 		return rc;
1461 	}
1462 
1463 	iter->field.ptr = remaining;
1464 	iter->field.length = length;
1465 	iter->entries = resp_data->downstream_device_count;
1466 
1467 	return 0;
1468 }
1469 
1470 LIBPLDM_ABI_STABLE
1471 int decode_pldm_downstream_device_parameters_entry_from_iter(
1472 	struct pldm_downstream_device_parameters_iter *iter,
1473 	struct pldm_downstream_device_parameters_entry *entry)
1474 {
1475 	PLDM_MSGBUF_DEFINE_P(buf);
1476 	void *comp_ver_str;
1477 	size_t remaining;
1478 	void *cursor;
1479 	int rc;
1480 
1481 	if (iter == NULL || iter->field.ptr == NULL || entry == NULL) {
1482 		return -EINVAL;
1483 	}
1484 
1485 	rc = pldm_msgbuf_init_errno(
1486 		buf, PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN,
1487 		iter->field.ptr, iter->field.length);
1488 	if (rc < 0) {
1489 		return rc;
1490 	}
1491 
1492 	pldm_msgbuf_extract(buf, entry->downstream_device_index);
1493 	pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp);
1494 	pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type);
1495 	rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len);
1496 	if (rc < 0) {
1497 		return pldm_msgbuf_discard(buf, rc);
1498 	}
1499 	rc = pldm_msgbuf_extract_array(buf,
1500 				       PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1501 				       entry->active_comp_release_date,
1502 				       sizeof(entry->active_comp_release_date));
1503 	if (rc < 0) {
1504 		return pldm_msgbuf_discard(buf, rc);
1505 	}
1506 
1507 	// Fill the last byte with NULL character
1508 	entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1509 		'\0';
1510 
1511 	pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp);
1512 	pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type);
1513 	rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len);
1514 	if (rc < 0) {
1515 		return pldm_msgbuf_discard(buf, rc);
1516 	}
1517 
1518 	rc = pldm_msgbuf_extract_array(
1519 		buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1520 		entry->pending_comp_release_date,
1521 		sizeof(entry->pending_comp_release_date));
1522 	if (rc < 0) {
1523 		return pldm_msgbuf_discard(buf, rc);
1524 	}
1525 
1526 	// Fill the last byte with NULL character
1527 	entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1528 		'\0';
1529 
1530 	pldm_msgbuf_extract(buf, entry->comp_activation_methods.value);
1531 	pldm_msgbuf_extract(buf, entry->capabilities_during_update.value);
1532 
1533 	rc = pldm_msgbuf_span_required(buf, entry->active_comp_ver_str_len,
1534 				       &comp_ver_str);
1535 	if (rc < 0) {
1536 		return pldm_msgbuf_discard(buf, rc);
1537 	}
1538 	entry->active_comp_ver_str = comp_ver_str;
1539 
1540 	rc = pldm_msgbuf_span_required(buf, entry->pending_comp_ver_str_len,
1541 				       &comp_ver_str);
1542 	if (rc < 0) {
1543 		return pldm_msgbuf_discard(buf, rc);
1544 	}
1545 	entry->pending_comp_ver_str = comp_ver_str;
1546 
1547 	rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining);
1548 	if (rc < 0) {
1549 		return pldm_msgbuf_discard(buf, rc);
1550 	}
1551 
1552 	iter->field.ptr = cursor;
1553 	iter->field.length = remaining;
1554 
1555 	return pldm_msgbuf_complete(buf);
1556 }
1557 
1558 LIBPLDM_ABI_TESTING
1559 int encode_request_downstream_device_update_req(
1560 	uint8_t instance_id,
1561 	const struct pldm_request_downstream_device_update_req *req_data,
1562 	struct pldm_msg *msg, size_t *payload_length)
1563 {
1564 	PLDM_MSGBUF_DEFINE_P(buf);
1565 	int rc;
1566 
1567 	if (!req_data || !msg || !payload_length ||
1568 	    req_data->maximum_downstream_device_transfer_size <
1569 		    PLDM_FWUP_BASELINE_TRANSFER_SIZE ||
1570 	    req_data->maximum_outstanding_transfer_requests <
1571 		    PLDM_FWUP_MIN_OUTSTANDING_REQ) {
1572 		return -EINVAL;
1573 	}
1574 
1575 	rc = encode_pldm_header_only_errno(
1576 		PLDM_REQUEST, instance_id, PLDM_FWUP,
1577 		PLDM_REQUEST_DOWNSTREAM_DEVICE_UPDATE, msg);
1578 	if (rc) {
1579 		return rc;
1580 	}
1581 
1582 	rc = pldm_msgbuf_init_errno(buf,
1583 				    PLDM_DOWNSTREAM_DEVICE_UPDATE_REQUEST_BYTES,
1584 				    msg->payload, *payload_length);
1585 	if (rc) {
1586 		return rc;
1587 	}
1588 
1589 	pldm_msgbuf_insert(buf,
1590 			   req_data->maximum_downstream_device_transfer_size);
1591 	pldm_msgbuf_insert(buf,
1592 			   req_data->maximum_outstanding_transfer_requests);
1593 	pldm_msgbuf_insert(buf,
1594 			   req_data->downstream_device_package_data_length);
1595 
1596 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1597 }
1598 
1599 LIBPLDM_ABI_TESTING
1600 int decode_request_downstream_device_update_req(
1601 	const struct pldm_msg *msg, size_t payload_length,
1602 	struct pldm_request_downstream_device_update_req *req)
1603 {
1604 	int rc;
1605 	PLDM_MSGBUF_DEFINE_P(buf);
1606 
1607 	if (!msg || !req) {
1608 		return -EINVAL;
1609 	}
1610 
1611 	rc = pldm_msgbuf_init_errno(buf,
1612 				    PLDM_DOWNSTREAM_DEVICE_UPDATE_REQUEST_BYTES,
1613 				    msg->payload, payload_length);
1614 	if (rc) {
1615 		return rc;
1616 	}
1617 
1618 	pldm_msgbuf_extract(buf, req->maximum_downstream_device_transfer_size);
1619 	pldm_msgbuf_extract(buf, req->maximum_outstanding_transfer_requests);
1620 	pldm_msgbuf_extract(buf, req->downstream_device_package_data_length);
1621 
1622 	return pldm_msgbuf_complete_consumed(buf);
1623 }
1624 
1625 LIBPLDM_ABI_TESTING
1626 int encode_request_downstream_device_update_resp(
1627 	uint8_t instance_id,
1628 	const struct pldm_request_downstream_device_update_resp *resp_data,
1629 	struct pldm_msg *msg, size_t *payload_length)
1630 {
1631 	PLDM_MSGBUF_DEFINE_P(buf);
1632 	int rc;
1633 
1634 	if (!resp_data || !msg || !payload_length) {
1635 		return -EINVAL;
1636 	}
1637 
1638 	rc = encode_pldm_header_only_errno(
1639 		PLDM_RESPONSE, instance_id, PLDM_FWUP,
1640 		PLDM_REQUEST_DOWNSTREAM_DEVICE_UPDATE, msg);
1641 	if (rc) {
1642 		return rc;
1643 	}
1644 
1645 	rc = pldm_msgbuf_init_errno(
1646 		buf, PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES, msg->payload,
1647 		*payload_length);
1648 	if (rc) {
1649 		return rc;
1650 	}
1651 
1652 	pldm_msgbuf_insert(buf, resp_data->completion_code);
1653 	pldm_msgbuf_insert(buf, resp_data->downstream_device_meta_data_length);
1654 	pldm_msgbuf_insert(
1655 		buf, resp_data->downstream_device_will_send_get_package_data);
1656 	pldm_msgbuf_insert(buf,
1657 			   resp_data->get_package_data_maximum_transfer_size);
1658 
1659 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1660 }
1661 
1662 LIBPLDM_ABI_TESTING
1663 int decode_request_downstream_device_update_resp(
1664 	const struct pldm_msg *msg, size_t payload_length,
1665 	struct pldm_request_downstream_device_update_resp *resp_data)
1666 {
1667 	PLDM_MSGBUF_DEFINE_P(buf);
1668 	int rc;
1669 
1670 	if (!msg || !resp_data) {
1671 		return -EINVAL;
1672 	}
1673 
1674 	rc = pldm_msg_has_error(msg,
1675 				PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES);
1676 	if (rc) {
1677 		resp_data->completion_code = rc;
1678 		return 0;
1679 	}
1680 
1681 	rc = pldm_msgbuf_init_errno(
1682 		buf, PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES, msg->payload,
1683 		payload_length);
1684 	if (rc) {
1685 		return rc;
1686 	}
1687 
1688 	pldm_msgbuf_extract(buf, resp_data->completion_code);
1689 	pldm_msgbuf_extract(buf, resp_data->downstream_device_meta_data_length);
1690 	pldm_msgbuf_extract(
1691 		buf, resp_data->downstream_device_will_send_get_package_data);
1692 	pldm_msgbuf_extract(buf,
1693 			    resp_data->get_package_data_maximum_transfer_size);
1694 
1695 	return pldm_msgbuf_complete_consumed(buf);
1696 }
1697 
1698 LIBPLDM_ABI_STABLE
1699 int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
1700 			      uint16_t num_of_comp,
1701 			      uint8_t max_outstanding_transfer_req,
1702 			      uint16_t pkg_data_len,
1703 			      uint8_t comp_image_set_ver_str_type,
1704 			      uint8_t comp_image_set_ver_str_len,
1705 			      const struct variable_field *comp_img_set_ver_str,
1706 			      struct pldm_msg *msg, size_t payload_length)
1707 {
1708 	if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
1709 	    msg == NULL) {
1710 		return PLDM_ERROR_INVALID_DATA;
1711 	}
1712 
1713 	if (payload_length != sizeof(struct pldm_request_update_req) +
1714 				      comp_img_set_ver_str->length) {
1715 		return PLDM_ERROR_INVALID_LENGTH;
1716 	}
1717 
1718 	if ((comp_image_set_ver_str_len == 0) ||
1719 	    (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
1720 		return PLDM_ERROR_INVALID_DATA;
1721 	}
1722 
1723 	if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
1724 	    (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
1725 		return PLDM_ERROR_INVALID_DATA;
1726 	}
1727 
1728 	if (!is_string_type_valid(comp_image_set_ver_str_type)) {
1729 		return PLDM_ERROR_INVALID_DATA;
1730 	}
1731 
1732 	struct pldm_header_info header = { 0 };
1733 	header.instance = instance_id;
1734 	header.msg_type = PLDM_REQUEST;
1735 	header.pldm_type = PLDM_FWUP;
1736 	header.command = PLDM_REQUEST_UPDATE;
1737 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1738 	if (rc) {
1739 		return rc;
1740 	}
1741 
1742 	struct pldm_request_update_req *request =
1743 		(struct pldm_request_update_req *)msg->payload;
1744 
1745 	request->max_transfer_size = htole32(max_transfer_size);
1746 	request->num_of_comp = htole16(num_of_comp);
1747 	request->max_outstanding_transfer_req = max_outstanding_transfer_req;
1748 	request->pkg_data_len = htole16(pkg_data_len);
1749 	request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
1750 	request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
1751 
1752 	memcpy(msg->payload + sizeof(struct pldm_request_update_req),
1753 	       comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
1754 
1755 	return PLDM_SUCCESS;
1756 }
1757 
1758 LIBPLDM_ABI_TESTING
1759 int decode_request_update_req(const struct pldm_msg *msg, size_t payload_length,
1760 			      struct pldm_request_update_req_full *req)
1761 {
1762 	int rc;
1763 	uint8_t t;
1764 	PLDM_MSGBUF_DEFINE_P(buf);
1765 
1766 	if (msg == NULL || req == NULL) {
1767 		return -EINVAL;
1768 	}
1769 
1770 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
1771 	if (rc) {
1772 		return rc;
1773 	}
1774 
1775 	pldm_msgbuf_extract(buf, req->max_transfer_size);
1776 	pldm_msgbuf_extract(buf, req->num_of_comp);
1777 	pldm_msgbuf_extract(buf, req->max_outstanding_transfer_req);
1778 	pldm_msgbuf_extract(buf, req->pkg_data_len);
1779 	rc = pldm_msgbuf_extract(buf, t);
1780 	if (rc) {
1781 		return pldm_msgbuf_discard(buf, rc);
1782 	}
1783 	if (t > PLDM_STR_TYPE_UTF_16BE) {
1784 		return pldm_msgbuf_discard(buf, -EBADMSG);
1785 	}
1786 	req->image_set_ver.str_type = (enum pldm_firmware_update_string_type)t;
1787 	pldm_msgbuf_extract(buf, req->image_set_ver.str_len);
1788 	if (rc) {
1789 		return pldm_msgbuf_discard(buf, rc);
1790 	}
1791 
1792 	rc = pldm_msgbuf_extract_array(buf, req->image_set_ver.str_len,
1793 				       req->image_set_ver.str_data,
1794 				       PLDM_FIRMWARE_MAX_STRING);
1795 	if (rc) {
1796 		return pldm_msgbuf_discard(buf, rc);
1797 	}
1798 
1799 	return pldm_msgbuf_complete_consumed(buf);
1800 }
1801 
1802 LIBPLDM_ABI_STABLE
1803 int decode_request_update_resp(const struct pldm_msg *msg,
1804 			       size_t payload_length, uint8_t *completion_code,
1805 			       uint16_t *fd_meta_data_len,
1806 			       uint8_t *fd_will_send_pkg_data)
1807 {
1808 	if (msg == NULL || completion_code == NULL ||
1809 	    fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
1810 	    !payload_length) {
1811 		return PLDM_ERROR_INVALID_DATA;
1812 	}
1813 
1814 	*completion_code = msg->payload[0];
1815 	if (*completion_code != PLDM_SUCCESS) {
1816 		return PLDM_SUCCESS;
1817 	}
1818 
1819 	if (payload_length != sizeof(struct pldm_request_update_resp)) {
1820 		return PLDM_ERROR_INVALID_LENGTH;
1821 	}
1822 
1823 	struct pldm_request_update_resp *response =
1824 		(struct pldm_request_update_resp *)msg->payload;
1825 
1826 	*fd_meta_data_len = le16toh(response->fd_meta_data_len);
1827 	*fd_will_send_pkg_data = response->fd_will_send_pkg_data;
1828 
1829 	return PLDM_SUCCESS;
1830 }
1831 
1832 LIBPLDM_ABI_TESTING
1833 int encode_request_update_resp(uint8_t instance_id,
1834 			       const struct pldm_request_update_resp *resp_data,
1835 			       struct pldm_msg *msg, size_t *payload_length)
1836 {
1837 	PLDM_MSGBUF_DEFINE_P(buf);
1838 	int rc;
1839 
1840 	if (msg == NULL || payload_length == NULL) {
1841 		return -EINVAL;
1842 	}
1843 
1844 	struct pldm_header_info header = {
1845 		.instance = instance_id,
1846 		.msg_type = PLDM_RESPONSE,
1847 		.pldm_type = PLDM_FWUP,
1848 		.command = PLDM_REQUEST_UPDATE,
1849 	};
1850 	rc = pack_pldm_header(&header, &(msg->hdr));
1851 	if (rc) {
1852 		return -EINVAL;
1853 	}
1854 
1855 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1856 	if (rc) {
1857 		return rc;
1858 	}
1859 
1860 	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
1861 	pldm_msgbuf_insert(buf, resp_data->fd_meta_data_len);
1862 	pldm_msgbuf_insert(buf, resp_data->fd_will_send_pkg_data);
1863 
1864 	/* TODO: DSP0267 1.3.0 adds GetPackageDataMaximumTransferSize */
1865 
1866 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1867 }
1868 
1869 LIBPLDM_ABI_STABLE
1870 int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
1871 				    uint16_t comp_classification,
1872 				    uint16_t comp_identifier,
1873 				    uint8_t comp_classification_index,
1874 				    uint32_t comp_comparison_stamp,
1875 				    uint8_t comp_ver_str_type,
1876 				    uint8_t comp_ver_str_len,
1877 				    const struct variable_field *comp_ver_str,
1878 				    struct pldm_msg *msg, size_t payload_length)
1879 {
1880 	if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1881 		return PLDM_ERROR_INVALID_DATA;
1882 	}
1883 
1884 	if (payload_length != sizeof(struct pldm_pass_component_table_req) +
1885 				      comp_ver_str->length) {
1886 		return PLDM_ERROR_INVALID_LENGTH;
1887 	}
1888 
1889 	if ((comp_ver_str_len == 0) ||
1890 	    (comp_ver_str_len != comp_ver_str->length)) {
1891 		return PLDM_ERROR_INVALID_DATA;
1892 	}
1893 
1894 	if (!is_transfer_flag_valid(transfer_flag)) {
1895 		return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
1896 	}
1897 
1898 	if (!is_string_type_valid(comp_ver_str_type)) {
1899 		return PLDM_ERROR_INVALID_DATA;
1900 	}
1901 
1902 	struct pldm_header_info header = { 0 };
1903 	header.instance = instance_id;
1904 	header.msg_type = PLDM_REQUEST;
1905 	header.pldm_type = PLDM_FWUP;
1906 	header.command = PLDM_PASS_COMPONENT_TABLE;
1907 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1908 	if (rc) {
1909 		return rc;
1910 	}
1911 
1912 	struct pldm_pass_component_table_req *request =
1913 		(struct pldm_pass_component_table_req *)msg->payload;
1914 
1915 	request->transfer_flag = transfer_flag;
1916 	request->comp_classification = htole16(comp_classification);
1917 	request->comp_identifier = htole16(comp_identifier);
1918 	request->comp_classification_index = comp_classification_index;
1919 	request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1920 	request->comp_ver_str_type = comp_ver_str_type;
1921 	request->comp_ver_str_len = comp_ver_str_len;
1922 
1923 	memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
1924 	       comp_ver_str->ptr, comp_ver_str->length);
1925 
1926 	return PLDM_SUCCESS;
1927 }
1928 
1929 LIBPLDM_ABI_TESTING
1930 int decode_pass_component_table_req(
1931 	const struct pldm_msg *msg, size_t payload_length,
1932 	struct pldm_pass_component_table_req_full *pcomp)
1933 {
1934 	int rc;
1935 	uint8_t t;
1936 	PLDM_MSGBUF_DEFINE_P(buf);
1937 
1938 	if (msg == NULL || pcomp == NULL) {
1939 		return -EINVAL;
1940 	}
1941 
1942 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
1943 	if (rc) {
1944 		return rc;
1945 	}
1946 
1947 	pldm_msgbuf_extract(buf, pcomp->transfer_flag);
1948 	pldm_msgbuf_extract(buf, pcomp->comp_classification);
1949 	pldm_msgbuf_extract(buf, pcomp->comp_identifier);
1950 	pldm_msgbuf_extract(buf, pcomp->comp_classification_index);
1951 	pldm_msgbuf_extract(buf, pcomp->comp_comparison_stamp);
1952 	rc = pldm_msgbuf_extract(buf, t);
1953 	if (rc) {
1954 		return pldm_msgbuf_discard(buf, rc);
1955 	}
1956 	if (t > PLDM_STR_TYPE_UTF_16BE) {
1957 		return pldm_msgbuf_discard(buf, -EBADMSG);
1958 	}
1959 	pcomp->version.str_type = (enum pldm_firmware_update_string_type)t;
1960 	rc = pldm_msgbuf_extract(buf, pcomp->version.str_len);
1961 	if (rc) {
1962 		return pldm_msgbuf_discard(buf, rc);
1963 	}
1964 	rc = pldm_msgbuf_extract_array(buf, pcomp->version.str_len,
1965 				       pcomp->version.str_data,
1966 				       PLDM_FIRMWARE_MAX_STRING);
1967 	if (rc) {
1968 		return pldm_msgbuf_discard(buf, rc);
1969 	}
1970 
1971 	return pldm_msgbuf_complete_consumed(buf);
1972 }
1973 
1974 LIBPLDM_ABI_STABLE
1975 int decode_pass_component_table_resp(const struct pldm_msg *msg,
1976 				     const size_t payload_length,
1977 				     uint8_t *completion_code,
1978 				     uint8_t *comp_resp,
1979 				     uint8_t *comp_resp_code)
1980 {
1981 	if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
1982 	    comp_resp_code == NULL || !payload_length) {
1983 		return PLDM_ERROR_INVALID_DATA;
1984 	}
1985 
1986 	*completion_code = msg->payload[0];
1987 	if (*completion_code != PLDM_SUCCESS) {
1988 		return PLDM_SUCCESS;
1989 	}
1990 
1991 	if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1992 		return PLDM_ERROR_INVALID_LENGTH;
1993 	}
1994 
1995 	struct pldm_pass_component_table_resp *response =
1996 		(struct pldm_pass_component_table_resp *)msg->payload;
1997 
1998 	if (!is_comp_resp_valid(response->comp_resp)) {
1999 		return PLDM_ERROR_INVALID_DATA;
2000 	}
2001 
2002 	if (!is_comp_resp_code_valid(response->comp_resp_code)) {
2003 		return PLDM_ERROR_INVALID_DATA;
2004 	}
2005 
2006 	*comp_resp = response->comp_resp;
2007 	*comp_resp_code = response->comp_resp_code;
2008 
2009 	return PLDM_SUCCESS;
2010 }
2011 
2012 LIBPLDM_ABI_TESTING
2013 int encode_pass_component_table_resp(
2014 	uint8_t instance_id,
2015 	const struct pldm_pass_component_table_resp *resp_data,
2016 	struct pldm_msg *msg, size_t *payload_length)
2017 {
2018 	PLDM_MSGBUF_DEFINE_P(buf);
2019 	int rc;
2020 
2021 	if (msg == NULL || payload_length == NULL) {
2022 		return -EINVAL;
2023 	}
2024 
2025 	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2026 				     PLDM_PASS_COMPONENT_TABLE, msg);
2027 	if (rc) {
2028 		return -EINVAL;
2029 	}
2030 
2031 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2032 	if (rc) {
2033 		return rc;
2034 	}
2035 
2036 	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2037 	pldm_msgbuf_insert(buf, resp_data->comp_resp);
2038 	pldm_msgbuf_insert(buf, resp_data->comp_resp_code);
2039 
2040 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2041 }
2042 
2043 LIBPLDM_ABI_STABLE
2044 int encode_update_component_req(
2045 	uint8_t instance_id, uint16_t comp_classification,
2046 	uint16_t comp_identifier, uint8_t comp_classification_index,
2047 	uint32_t comp_comparison_stamp, uint32_t comp_image_size,
2048 	bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
2049 	uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
2050 	struct pldm_msg *msg, size_t payload_length)
2051 {
2052 	if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
2053 		return PLDM_ERROR_INVALID_DATA;
2054 	}
2055 
2056 	if (payload_length !=
2057 	    sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
2058 		return PLDM_ERROR_INVALID_LENGTH;
2059 	}
2060 
2061 	if (!comp_image_size) {
2062 		return PLDM_ERROR_INVALID_DATA;
2063 	}
2064 
2065 	if ((comp_ver_str_len == 0) ||
2066 	    (comp_ver_str_len != comp_ver_str->length)) {
2067 		return PLDM_ERROR_INVALID_DATA;
2068 	}
2069 
2070 	if (!is_string_type_valid(comp_ver_str_type)) {
2071 		return PLDM_ERROR_INVALID_DATA;
2072 	}
2073 
2074 	struct pldm_header_info header = { 0 };
2075 	header.instance = instance_id;
2076 	header.msg_type = PLDM_REQUEST;
2077 	header.pldm_type = PLDM_FWUP;
2078 	header.command = PLDM_UPDATE_COMPONENT;
2079 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2080 	if (rc) {
2081 		return rc;
2082 	}
2083 
2084 	struct pldm_update_component_req *request =
2085 		(struct pldm_update_component_req *)msg->payload;
2086 
2087 	request->comp_classification = htole16(comp_classification);
2088 	request->comp_identifier = htole16(comp_identifier);
2089 	request->comp_classification_index = comp_classification_index;
2090 	request->comp_comparison_stamp = htole32(comp_comparison_stamp);
2091 	request->comp_image_size = htole32(comp_image_size);
2092 	request->update_option_flags.value = htole32(update_option_flags.value);
2093 	request->comp_ver_str_type = comp_ver_str_type;
2094 	request->comp_ver_str_len = comp_ver_str_len;
2095 
2096 	memcpy(msg->payload + sizeof(struct pldm_update_component_req),
2097 	       comp_ver_str->ptr, comp_ver_str->length);
2098 
2099 	return PLDM_SUCCESS;
2100 }
2101 
2102 LIBPLDM_ABI_TESTING
2103 int decode_update_component_req(const struct pldm_msg *msg,
2104 				size_t payload_length,
2105 				struct pldm_update_component_req_full *up)
2106 {
2107 	int rc;
2108 	uint8_t t;
2109 	PLDM_MSGBUF_DEFINE_P(buf);
2110 
2111 	if (msg == NULL || up == NULL) {
2112 		return -EINVAL;
2113 	}
2114 
2115 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
2116 	if (rc) {
2117 		return rc;
2118 	}
2119 
2120 	pldm_msgbuf_extract(buf, up->comp_classification);
2121 	pldm_msgbuf_extract(buf, up->comp_identifier);
2122 	pldm_msgbuf_extract(buf, up->comp_classification_index);
2123 	pldm_msgbuf_extract(buf, up->comp_comparison_stamp);
2124 	pldm_msgbuf_extract(buf, up->comp_image_size);
2125 	pldm_msgbuf_extract(buf, up->update_option_flags.value);
2126 	rc = pldm_msgbuf_extract(buf, t);
2127 	if (rc) {
2128 		return pldm_msgbuf_discard(buf, rc);
2129 	}
2130 	if (t > PLDM_STR_TYPE_UTF_16BE) {
2131 		return pldm_msgbuf_discard(buf, -EBADMSG);
2132 	}
2133 	up->version.str_type = (enum pldm_firmware_update_string_type)t;
2134 	rc = pldm_msgbuf_extract(buf, up->version.str_len);
2135 	if (rc) {
2136 		return pldm_msgbuf_discard(buf, rc);
2137 	}
2138 	rc = pldm_msgbuf_extract_array(buf, up->version.str_len,
2139 				       up->version.str_data,
2140 				       PLDM_FIRMWARE_MAX_STRING);
2141 	if (rc) {
2142 		return pldm_msgbuf_discard(buf, rc);
2143 	}
2144 
2145 	return pldm_msgbuf_complete_consumed(buf);
2146 }
2147 
2148 LIBPLDM_ABI_STABLE
2149 int decode_update_component_resp(const struct pldm_msg *msg,
2150 				 size_t payload_length,
2151 				 uint8_t *completion_code,
2152 				 uint8_t *comp_compatibility_resp,
2153 				 uint8_t *comp_compatibility_resp_code,
2154 				 bitfield32_t *update_option_flags_enabled,
2155 				 uint16_t *time_before_req_fw_data)
2156 {
2157 	if (msg == NULL || completion_code == NULL ||
2158 	    comp_compatibility_resp == NULL ||
2159 	    comp_compatibility_resp_code == NULL ||
2160 	    update_option_flags_enabled == NULL ||
2161 	    time_before_req_fw_data == NULL || !payload_length) {
2162 		return PLDM_ERROR_INVALID_DATA;
2163 	}
2164 
2165 	*completion_code = msg->payload[0];
2166 	if (*completion_code != PLDM_SUCCESS) {
2167 		return PLDM_SUCCESS;
2168 	}
2169 
2170 	if (payload_length != sizeof(struct pldm_update_component_resp)) {
2171 		return PLDM_ERROR_INVALID_LENGTH;
2172 	}
2173 
2174 	struct pldm_update_component_resp *response =
2175 		(struct pldm_update_component_resp *)msg->payload;
2176 
2177 	if (!is_comp_compatibility_resp_valid(
2178 		    response->comp_compatibility_resp)) {
2179 		return PLDM_ERROR_INVALID_DATA;
2180 	}
2181 
2182 	if (!is_comp_compatibility_resp_code_valid(
2183 		    response->comp_compatibility_resp_code)) {
2184 		return PLDM_ERROR_INVALID_DATA;
2185 	}
2186 
2187 	*comp_compatibility_resp = response->comp_compatibility_resp;
2188 	*comp_compatibility_resp_code = response->comp_compatibility_resp_code;
2189 	update_option_flags_enabled->value =
2190 		le32toh(response->update_option_flags_enabled.value);
2191 	*time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
2192 
2193 	return PLDM_SUCCESS;
2194 }
2195 
2196 LIBPLDM_ABI_TESTING
2197 int encode_update_component_resp(
2198 	uint8_t instance_id, const struct pldm_update_component_resp *resp_data,
2199 	struct pldm_msg *msg, size_t *payload_length)
2200 {
2201 	PLDM_MSGBUF_DEFINE_P(buf);
2202 	int rc;
2203 
2204 	if (msg == NULL || payload_length == NULL) {
2205 		return -EINVAL;
2206 	}
2207 
2208 	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2209 				     PLDM_UPDATE_COMPONENT, msg);
2210 	if (rc) {
2211 		return -EINVAL;
2212 	}
2213 
2214 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2215 	if (rc) {
2216 		return rc;
2217 	}
2218 
2219 	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2220 	pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp);
2221 	pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp_code);
2222 	pldm_msgbuf_insert(buf, resp_data->update_option_flags_enabled.value);
2223 	pldm_msgbuf_insert(buf, resp_data->time_before_req_fw_data);
2224 
2225 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2226 }
2227 
2228 LIBPLDM_ABI_STABLE
2229 int decode_request_firmware_data_req(const struct pldm_msg *msg,
2230 				     size_t payload_length, uint32_t *offset,
2231 				     uint32_t *length)
2232 {
2233 	if (msg == NULL || offset == NULL || length == NULL) {
2234 		return PLDM_ERROR_INVALID_DATA;
2235 	}
2236 	if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
2237 		return PLDM_ERROR_INVALID_LENGTH;
2238 	}
2239 	struct pldm_request_firmware_data_req *request =
2240 		(struct pldm_request_firmware_data_req *)msg->payload;
2241 	*offset = le32toh(request->offset);
2242 	*length = le32toh(request->length);
2243 
2244 	if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
2245 		return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
2246 	}
2247 
2248 	return PLDM_SUCCESS;
2249 }
2250 
2251 LIBPLDM_ABI_TESTING
2252 int encode_request_firmware_data_req(
2253 	uint8_t instance_id,
2254 	const struct pldm_request_firmware_data_req *req_params,
2255 	struct pldm_msg *msg, size_t *payload_length)
2256 {
2257 	PLDM_MSGBUF_DEFINE_P(buf);
2258 	int rc;
2259 
2260 	if (msg == NULL || payload_length == NULL) {
2261 		return -EINVAL;
2262 	}
2263 
2264 	rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2265 				     PLDM_REQUEST_FIRMWARE_DATA, msg);
2266 	if (rc) {
2267 		return -EINVAL;
2268 	}
2269 
2270 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2271 	if (rc) {
2272 		return rc;
2273 	}
2274 
2275 	pldm_msgbuf_insert(buf, req_params->offset);
2276 	pldm_msgbuf_insert(buf, req_params->length);
2277 
2278 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2279 }
2280 
2281 LIBPLDM_ABI_STABLE
2282 int encode_request_firmware_data_resp(uint8_t instance_id,
2283 				      uint8_t completion_code,
2284 				      struct pldm_msg *msg,
2285 				      size_t payload_length)
2286 {
2287 	if (msg == NULL || !payload_length) {
2288 		return PLDM_ERROR_INVALID_DATA;
2289 	}
2290 
2291 	struct pldm_header_info header = { 0 };
2292 	header.instance = instance_id;
2293 	header.msg_type = PLDM_RESPONSE;
2294 	header.pldm_type = PLDM_FWUP;
2295 	header.command = PLDM_REQUEST_FIRMWARE_DATA;
2296 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2297 	if (rc) {
2298 		return rc;
2299 	}
2300 
2301 	msg->payload[0] = completion_code;
2302 
2303 	return PLDM_SUCCESS;
2304 }
2305 
2306 LIBPLDM_ABI_STABLE
2307 int decode_transfer_complete_req(const struct pldm_msg *msg,
2308 				 size_t payload_length,
2309 				 uint8_t *transfer_result)
2310 {
2311 	if (msg == NULL || transfer_result == NULL) {
2312 		return PLDM_ERROR_INVALID_DATA;
2313 	}
2314 
2315 	if (payload_length != sizeof(*transfer_result)) {
2316 		return PLDM_ERROR_INVALID_LENGTH;
2317 	}
2318 
2319 	*transfer_result = msg->payload[0];
2320 	return PLDM_SUCCESS;
2321 }
2322 
2323 LIBPLDM_ABI_TESTING
2324 int encode_transfer_complete_req(uint8_t instance_id, uint8_t transfer_result,
2325 				 struct pldm_msg *msg, size_t *payload_length)
2326 {
2327 	PLDM_MSGBUF_DEFINE_P(buf);
2328 	int rc;
2329 
2330 	if (msg == NULL || payload_length == NULL) {
2331 		return -EINVAL;
2332 	}
2333 
2334 	rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2335 				     PLDM_TRANSFER_COMPLETE, msg);
2336 	if (rc) {
2337 		return -EINVAL;
2338 	}
2339 
2340 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2341 	if (rc) {
2342 		return rc;
2343 	}
2344 
2345 	pldm_msgbuf_insert(buf, transfer_result);
2346 
2347 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2348 }
2349 
2350 LIBPLDM_ABI_STABLE
2351 int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
2352 				  struct pldm_msg *msg, size_t payload_length)
2353 {
2354 	if (msg == NULL) {
2355 		return PLDM_ERROR_INVALID_DATA;
2356 	}
2357 
2358 	if (payload_length != sizeof(completion_code)) {
2359 		return PLDM_ERROR_INVALID_LENGTH;
2360 	}
2361 
2362 	struct pldm_header_info header = { 0 };
2363 	header.instance = instance_id;
2364 	header.msg_type = PLDM_RESPONSE;
2365 	header.pldm_type = PLDM_FWUP;
2366 	header.command = PLDM_TRANSFER_COMPLETE;
2367 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2368 	if (rc) {
2369 		return rc;
2370 	}
2371 
2372 	msg->payload[0] = completion_code;
2373 
2374 	return PLDM_SUCCESS;
2375 }
2376 
2377 LIBPLDM_ABI_STABLE
2378 int decode_verify_complete_req(const struct pldm_msg *msg,
2379 			       size_t payload_length, uint8_t *verify_result)
2380 {
2381 	if (msg == NULL || verify_result == NULL) {
2382 		return PLDM_ERROR_INVALID_DATA;
2383 	}
2384 
2385 	if (payload_length != sizeof(*verify_result)) {
2386 		return PLDM_ERROR_INVALID_LENGTH;
2387 	}
2388 
2389 	*verify_result = msg->payload[0];
2390 	return PLDM_SUCCESS;
2391 }
2392 
2393 LIBPLDM_ABI_TESTING
2394 int encode_verify_complete_req(uint8_t instance_id, uint8_t verify_result,
2395 			       struct pldm_msg *msg, size_t *payload_length)
2396 {
2397 	PLDM_MSGBUF_DEFINE_P(buf);
2398 	int rc;
2399 
2400 	if (msg == NULL || payload_length == NULL) {
2401 		return -EINVAL;
2402 	}
2403 
2404 	rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2405 				     PLDM_VERIFY_COMPLETE, msg);
2406 	if (rc) {
2407 		return EINVAL;
2408 	}
2409 
2410 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2411 	if (rc) {
2412 		return rc;
2413 	}
2414 
2415 	pldm_msgbuf_insert(buf, verify_result);
2416 
2417 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2418 }
2419 
2420 LIBPLDM_ABI_STABLE
2421 int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
2422 				struct pldm_msg *msg, size_t payload_length)
2423 {
2424 	if (msg == NULL) {
2425 		return PLDM_ERROR_INVALID_DATA;
2426 	}
2427 
2428 	if (payload_length != sizeof(completion_code)) {
2429 		return PLDM_ERROR_INVALID_LENGTH;
2430 	}
2431 
2432 	struct pldm_header_info header = { 0 };
2433 	header.instance = instance_id;
2434 	header.msg_type = PLDM_RESPONSE;
2435 	header.pldm_type = PLDM_FWUP;
2436 	header.command = PLDM_VERIFY_COMPLETE;
2437 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2438 	if (rc) {
2439 		return rc;
2440 	}
2441 
2442 	msg->payload[0] = completion_code;
2443 
2444 	return PLDM_SUCCESS;
2445 }
2446 
2447 LIBPLDM_ABI_STABLE
2448 int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
2449 			      uint8_t *apply_result,
2450 			      bitfield16_t *comp_activation_methods_modification)
2451 {
2452 	if (msg == NULL || apply_result == NULL ||
2453 	    comp_activation_methods_modification == NULL) {
2454 		return PLDM_ERROR_INVALID_DATA;
2455 	}
2456 
2457 	if (payload_length != sizeof(struct pldm_apply_complete_req)) {
2458 		return PLDM_ERROR_INVALID_LENGTH;
2459 	}
2460 
2461 	struct pldm_apply_complete_req *request =
2462 		(struct pldm_apply_complete_req *)msg->payload;
2463 
2464 	*apply_result = request->apply_result;
2465 	comp_activation_methods_modification->value =
2466 		le16toh(request->comp_activation_methods_modification.value);
2467 
2468 	if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
2469 	    comp_activation_methods_modification->value) {
2470 		return PLDM_ERROR_INVALID_DATA;
2471 	}
2472 
2473 	return PLDM_SUCCESS;
2474 }
2475 
2476 LIBPLDM_ABI_TESTING
2477 int encode_apply_complete_req(uint8_t instance_id,
2478 			      const struct pldm_apply_complete_req *req_data,
2479 			      struct pldm_msg *msg, size_t *payload_length)
2480 {
2481 	PLDM_MSGBUF_DEFINE_P(buf);
2482 	int rc;
2483 
2484 	if (msg == NULL || payload_length == NULL) {
2485 		return -EINVAL;
2486 	}
2487 
2488 	rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2489 				     PLDM_APPLY_COMPLETE, msg);
2490 	if (rc) {
2491 		return -EINVAL;
2492 	}
2493 
2494 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2495 	if (rc) {
2496 		return rc;
2497 	}
2498 
2499 	pldm_msgbuf_insert(buf, req_data->apply_result);
2500 	pldm_msgbuf_insert(
2501 		buf, req_data->comp_activation_methods_modification.value);
2502 
2503 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2504 }
2505 
2506 LIBPLDM_ABI_STABLE
2507 int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
2508 			       struct pldm_msg *msg, size_t payload_length)
2509 {
2510 	if (msg == NULL) {
2511 		return PLDM_ERROR_INVALID_DATA;
2512 	}
2513 
2514 	if (payload_length != sizeof(completion_code)) {
2515 		return PLDM_ERROR_INVALID_LENGTH;
2516 	}
2517 
2518 	struct pldm_header_info header = { 0 };
2519 	header.instance = instance_id;
2520 	header.msg_type = PLDM_RESPONSE;
2521 	header.pldm_type = PLDM_FWUP;
2522 	header.command = PLDM_APPLY_COMPLETE;
2523 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2524 	if (rc) {
2525 		return rc;
2526 	}
2527 
2528 	msg->payload[0] = completion_code;
2529 
2530 	return PLDM_SUCCESS;
2531 }
2532 
2533 LIBPLDM_ABI_TESTING
2534 int decode_activate_firmware_req(const struct pldm_msg *msg,
2535 				 size_t payload_length, bool *self_contained)
2536 {
2537 	uint8_t self_contained_u8 = 0;
2538 	PLDM_MSGBUF_DEFINE_P(buf);
2539 	int rc;
2540 
2541 	if (msg == NULL || self_contained == NULL) {
2542 		return -EINVAL;
2543 	}
2544 
2545 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
2546 	if (rc) {
2547 		return 0;
2548 	}
2549 
2550 	pldm_msgbuf_extract(buf, self_contained_u8);
2551 
2552 	rc = pldm_msgbuf_complete_consumed(buf);
2553 	if (rc) {
2554 		return rc;
2555 	}
2556 
2557 	*self_contained = (bool)self_contained_u8;
2558 	return 0;
2559 }
2560 
2561 LIBPLDM_ABI_STABLE
2562 int encode_activate_firmware_req(uint8_t instance_id,
2563 				 bool8_t self_contained_activation_req,
2564 				 struct pldm_msg *msg, size_t payload_length)
2565 {
2566 	if (msg == NULL) {
2567 		return PLDM_ERROR_INVALID_DATA;
2568 	}
2569 
2570 	if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
2571 		return PLDM_ERROR_INVALID_LENGTH;
2572 	}
2573 
2574 	if (!is_self_contained_activation_req_valid(
2575 		    self_contained_activation_req)) {
2576 		return PLDM_ERROR_INVALID_DATA;
2577 	}
2578 
2579 	struct pldm_header_info header = { 0 };
2580 	header.instance = instance_id;
2581 	header.msg_type = PLDM_REQUEST;
2582 	header.pldm_type = PLDM_FWUP;
2583 	header.command = PLDM_ACTIVATE_FIRMWARE;
2584 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2585 	if (rc) {
2586 		return rc;
2587 	}
2588 
2589 	struct pldm_activate_firmware_req *request =
2590 		(struct pldm_activate_firmware_req *)msg->payload;
2591 
2592 	request->self_contained_activation_req = self_contained_activation_req;
2593 
2594 	return PLDM_SUCCESS;
2595 }
2596 
2597 LIBPLDM_ABI_STABLE
2598 int decode_activate_firmware_resp(const struct pldm_msg *msg,
2599 				  size_t payload_length,
2600 				  uint8_t *completion_code,
2601 				  uint16_t *estimated_time_activation)
2602 {
2603 	if (msg == NULL || completion_code == NULL ||
2604 	    estimated_time_activation == NULL || !payload_length) {
2605 		return PLDM_ERROR_INVALID_DATA;
2606 	}
2607 
2608 	*completion_code = msg->payload[0];
2609 	if (*completion_code != PLDM_SUCCESS) {
2610 		return PLDM_SUCCESS;
2611 	}
2612 
2613 	if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
2614 		return PLDM_ERROR_INVALID_LENGTH;
2615 	}
2616 
2617 	struct pldm_activate_firmware_resp *response =
2618 		(struct pldm_activate_firmware_resp *)msg->payload;
2619 
2620 	*estimated_time_activation =
2621 		le16toh(response->estimated_time_activation);
2622 
2623 	return PLDM_SUCCESS;
2624 }
2625 
2626 LIBPLDM_ABI_TESTING
2627 int encode_activate_firmware_resp(
2628 	uint8_t instance_id,
2629 	const struct pldm_activate_firmware_resp *resp_data,
2630 	struct pldm_msg *msg, size_t *payload_length)
2631 {
2632 	PLDM_MSGBUF_DEFINE_P(buf);
2633 	int rc;
2634 
2635 	if (msg == NULL || payload_length == NULL) {
2636 		return -EINVAL;
2637 	}
2638 
2639 	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2640 				     PLDM_ACTIVATE_FIRMWARE, msg);
2641 	if (rc) {
2642 		return -EINVAL;
2643 	}
2644 
2645 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2646 	if (rc) {
2647 		return rc;
2648 	}
2649 
2650 	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2651 	pldm_msgbuf_insert(buf, resp_data->estimated_time_activation);
2652 
2653 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2654 }
2655 
2656 LIBPLDM_ABI_STABLE
2657 int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
2658 			  size_t payload_length)
2659 {
2660 	if (msg == NULL) {
2661 		return PLDM_ERROR_INVALID_DATA;
2662 	}
2663 
2664 	if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
2665 		return PLDM_ERROR_INVALID_LENGTH;
2666 	}
2667 
2668 	struct pldm_header_info header = { 0 };
2669 	header.instance = instance_id;
2670 	header.msg_type = PLDM_REQUEST;
2671 	header.pldm_type = PLDM_FWUP;
2672 	header.command = PLDM_GET_STATUS;
2673 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2674 	if (rc) {
2675 		return rc;
2676 	}
2677 
2678 	return PLDM_SUCCESS;
2679 }
2680 
2681 LIBPLDM_ABI_STABLE
2682 int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
2683 			   uint8_t *completion_code, uint8_t *current_state,
2684 			   uint8_t *previous_state, uint8_t *aux_state,
2685 			   uint8_t *aux_state_status, uint8_t *progress_percent,
2686 			   uint8_t *reason_code,
2687 			   bitfield32_t *update_option_flags_enabled)
2688 {
2689 	if (msg == NULL || completion_code == NULL || current_state == NULL ||
2690 	    previous_state == NULL || aux_state == NULL ||
2691 	    aux_state_status == NULL || progress_percent == NULL ||
2692 	    reason_code == NULL || update_option_flags_enabled == NULL ||
2693 	    !payload_length) {
2694 		return PLDM_ERROR_INVALID_DATA;
2695 	}
2696 
2697 	*completion_code = msg->payload[0];
2698 	if (*completion_code != PLDM_SUCCESS) {
2699 		return PLDM_SUCCESS;
2700 	}
2701 
2702 	if (payload_length != sizeof(struct pldm_get_status_resp)) {
2703 		return PLDM_ERROR_INVALID_LENGTH;
2704 	}
2705 	struct pldm_get_status_resp *response =
2706 		(struct pldm_get_status_resp *)msg->payload;
2707 
2708 	if (!is_state_valid(response->current_state)) {
2709 		return PLDM_ERROR_INVALID_DATA;
2710 	}
2711 	if (!is_state_valid(response->previous_state)) {
2712 		return PLDM_ERROR_INVALID_DATA;
2713 	}
2714 	if (!is_aux_state_valid(response->aux_state)) {
2715 		return PLDM_ERROR_INVALID_DATA;
2716 	}
2717 	if (!is_aux_state_status_valid(response->aux_state_status)) {
2718 		return PLDM_ERROR_INVALID_DATA;
2719 	}
2720 	if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
2721 		return PLDM_ERROR_INVALID_DATA;
2722 	}
2723 	if (!is_reason_code_valid(response->reason_code)) {
2724 		return PLDM_ERROR_INVALID_DATA;
2725 	}
2726 
2727 	if ((response->current_state == PLDM_FD_STATE_IDLE) ||
2728 	    (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
2729 	    (response->current_state == PLDM_FD_STATE_READY_XFER)) {
2730 		if (response->aux_state !=
2731 		    PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
2732 			return PLDM_ERROR_INVALID_DATA;
2733 		}
2734 	}
2735 
2736 	*current_state = response->current_state;
2737 	*previous_state = response->previous_state;
2738 	*aux_state = response->aux_state;
2739 	*aux_state_status = response->aux_state_status;
2740 	*progress_percent = response->progress_percent;
2741 	*reason_code = response->reason_code;
2742 	update_option_flags_enabled->value =
2743 		le32toh(response->update_option_flags_enabled.value);
2744 
2745 	return PLDM_SUCCESS;
2746 }
2747 
2748 LIBPLDM_ABI_TESTING
2749 int encode_get_status_resp(uint8_t instance_id,
2750 			   const struct pldm_get_status_resp *status,
2751 			   struct pldm_msg *msg, size_t *payload_length)
2752 {
2753 	PLDM_MSGBUF_DEFINE_P(buf);
2754 	int rc;
2755 
2756 	if (status == NULL || msg == NULL || payload_length == NULL) {
2757 		return -EINVAL;
2758 	}
2759 
2760 	if (status->completion_code != PLDM_SUCCESS) {
2761 		return -EINVAL;
2762 	}
2763 
2764 	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2765 				     PLDM_GET_STATUS, msg);
2766 	if (rc) {
2767 		return -EINVAL;
2768 	}
2769 
2770 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2771 	if (rc) {
2772 		return rc;
2773 	}
2774 
2775 	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2776 	pldm_msgbuf_insert(buf, status->current_state);
2777 	pldm_msgbuf_insert(buf, status->previous_state);
2778 	pldm_msgbuf_insert(buf, status->aux_state);
2779 	pldm_msgbuf_insert(buf, status->aux_state_status);
2780 	pldm_msgbuf_insert(buf, status->progress_percent);
2781 	pldm_msgbuf_insert(buf, status->reason_code);
2782 	pldm_msgbuf_insert(buf, status->update_option_flags_enabled.value);
2783 
2784 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2785 }
2786 
2787 LIBPLDM_ABI_STABLE
2788 int encode_cancel_update_component_req(uint8_t instance_id,
2789 				       struct pldm_msg *msg,
2790 				       size_t payload_length)
2791 {
2792 	if (msg == NULL) {
2793 		return PLDM_ERROR_INVALID_DATA;
2794 	}
2795 
2796 	if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
2797 		return PLDM_ERROR_INVALID_LENGTH;
2798 	}
2799 
2800 	struct pldm_header_info header = { 0 };
2801 	header.instance = instance_id;
2802 	header.msg_type = PLDM_REQUEST;
2803 	header.pldm_type = PLDM_FWUP;
2804 	header.command = PLDM_CANCEL_UPDATE_COMPONENT;
2805 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2806 	if (rc) {
2807 		return rc;
2808 	}
2809 
2810 	return PLDM_SUCCESS;
2811 }
2812 
2813 LIBPLDM_ABI_STABLE
2814 int decode_cancel_update_component_resp(const struct pldm_msg *msg,
2815 					size_t payload_length,
2816 					uint8_t *completion_code)
2817 {
2818 	if (msg == NULL || completion_code == NULL) {
2819 		return PLDM_ERROR_INVALID_DATA;
2820 	}
2821 
2822 	if (payload_length != sizeof(*completion_code)) {
2823 		return PLDM_ERROR_INVALID_LENGTH;
2824 	}
2825 
2826 	*completion_code = msg->payload[0];
2827 	return PLDM_SUCCESS;
2828 }
2829 
2830 LIBPLDM_ABI_STABLE
2831 int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
2832 			     size_t payload_length)
2833 {
2834 	if (msg == NULL) {
2835 		return PLDM_ERROR_INVALID_DATA;
2836 	}
2837 
2838 	if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
2839 		return PLDM_ERROR_INVALID_LENGTH;
2840 	}
2841 
2842 	struct pldm_header_info header = { 0 };
2843 	header.instance = instance_id;
2844 	header.msg_type = PLDM_REQUEST;
2845 	header.pldm_type = PLDM_FWUP;
2846 	header.command = PLDM_CANCEL_UPDATE;
2847 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2848 	if (rc) {
2849 		return rc;
2850 	}
2851 
2852 	return PLDM_SUCCESS;
2853 }
2854 
2855 LIBPLDM_ABI_STABLE
2856 int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
2857 			      uint8_t *completion_code,
2858 			      bool8_t *non_functioning_component_indication,
2859 			      bitfield64_t *non_functioning_component_bitmap)
2860 {
2861 	if (msg == NULL || completion_code == NULL ||
2862 	    non_functioning_component_indication == NULL ||
2863 	    non_functioning_component_bitmap == NULL || !payload_length) {
2864 		return PLDM_ERROR_INVALID_DATA;
2865 	}
2866 
2867 	*completion_code = msg->payload[0];
2868 	if (*completion_code != PLDM_SUCCESS) {
2869 		return PLDM_SUCCESS;
2870 	}
2871 
2872 	if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
2873 		return PLDM_ERROR_INVALID_LENGTH;
2874 	}
2875 	struct pldm_cancel_update_resp *response =
2876 		(struct pldm_cancel_update_resp *)msg->payload;
2877 
2878 	if (!is_non_functioning_component_indication_valid(
2879 		    response->non_functioning_component_indication)) {
2880 		return PLDM_ERROR_INVALID_DATA;
2881 	}
2882 
2883 	*non_functioning_component_indication =
2884 		response->non_functioning_component_indication;
2885 
2886 	if (*non_functioning_component_indication) {
2887 		non_functioning_component_bitmap->value =
2888 			le64toh(response->non_functioning_component_bitmap);
2889 	}
2890 
2891 	return PLDM_SUCCESS;
2892 }
2893 
2894 LIBPLDM_ABI_TESTING
2895 int encode_cancel_update_resp(uint8_t instance_id,
2896 			      const struct pldm_cancel_update_resp *resp_data,
2897 			      struct pldm_msg *msg, size_t *payload_length)
2898 {
2899 	PLDM_MSGBUF_DEFINE_P(buf);
2900 	int rc;
2901 
2902 	if (msg == NULL || payload_length == NULL) {
2903 		return -EINVAL;
2904 	}
2905 
2906 	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2907 				     PLDM_CANCEL_UPDATE, msg);
2908 	if (rc) {
2909 		return -EINVAL;
2910 	}
2911 
2912 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2913 	if (rc) {
2914 		return rc;
2915 	}
2916 
2917 	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2918 	pldm_msgbuf_insert(buf,
2919 			   resp_data->non_functioning_component_indication);
2920 	pldm_msgbuf_insert(buf, resp_data->non_functioning_component_bitmap);
2921 
2922 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2923 }
2924