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