xref: /openbmc/libpldm/src/dsp/firmware_update.c (revision 5befd128)
1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 #include "dsp/base.h"
3 #include "msgbuf.h"
4 #include <libpldm/firmware_update.h>
5 #include <libpldm/utils.h>
6 
7 #include <endian.h>
8 #include <stdbool.h>
9 #include <string.h>
10 
11 /** @brief Check whether string type value is valid
12  *
13  *  @return true if string type value is valid, false if not
14  */
15 static bool is_string_type_valid(uint8_t string_type)
16 {
17 	switch (string_type) {
18 	case PLDM_STR_TYPE_UNKNOWN:
19 		return false;
20 	case PLDM_STR_TYPE_ASCII:
21 	case PLDM_STR_TYPE_UTF_8:
22 	case PLDM_STR_TYPE_UTF_16:
23 	case PLDM_STR_TYPE_UTF_16LE:
24 	case PLDM_STR_TYPE_UTF_16BE:
25 		return true;
26 	default:
27 		return false;
28 	}
29 }
30 
31 /** @brief Return the length of the descriptor type described in firmware update
32  *         specification
33  *
34  *  @return length of the descriptor type if descriptor type is valid else
35  *          return 0
36  */
37 static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
38 {
39 	switch (descriptor_type) {
40 	case PLDM_FWUP_PCI_VENDOR_ID:
41 		return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
42 	case PLDM_FWUP_IANA_ENTERPRISE_ID:
43 		return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
44 	case PLDM_FWUP_UUID:
45 		return PLDM_FWUP_UUID_LENGTH;
46 	case PLDM_FWUP_PNP_VENDOR_ID:
47 		return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
48 	case PLDM_FWUP_ACPI_VENDOR_ID:
49 		return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
50 	case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
51 		return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
52 	case PLDM_FWUP_SCSI_VENDOR_ID:
53 		return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
54 	case PLDM_FWUP_PCI_DEVICE_ID:
55 		return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
56 	case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
57 		return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
58 	case PLDM_FWUP_PCI_SUBSYSTEM_ID:
59 		return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
60 	case PLDM_FWUP_PCI_REVISION_ID:
61 		return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
62 	case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
63 		return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
64 	case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
65 		return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
66 	case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
67 		return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
68 	case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
69 		return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
70 	case PLDM_FWUP_SCSI_PRODUCT_ID:
71 		return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
72 	case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
73 		return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
74 	default:
75 		return 0;
76 	}
77 }
78 
79 static bool is_downstream_device_update_support_valid(uint8_t resp)
80 {
81 	switch (resp) {
82 	case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED:
83 	case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED:
84 		return true;
85 	default:
86 		return false;
87 	}
88 }
89 
90 static bool
91 is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag)
92 {
93 	switch (transfer_op_flag) {
94 	case PLDM_GET_NEXTPART:
95 	case PLDM_GET_FIRSTPART:
96 		return true;
97 	default:
98 		return false;
99 	}
100 }
101 
102 /** @brief Check whether ComponentResponse is valid
103  *
104  *  @return true if ComponentResponse is valid, false if not
105  */
106 static bool is_comp_resp_valid(uint8_t comp_resp)
107 {
108 	switch (comp_resp) {
109 	case PLDM_CR_COMP_CAN_BE_UPDATED:
110 	case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
111 		return true;
112 
113 	default:
114 		return false;
115 	}
116 }
117 
118 /** @brief Check whether ComponentResponseCode is valid
119  *
120  *  @return true if ComponentResponseCode is valid, false if not
121  */
122 static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
123 {
124 	switch (comp_resp_code) {
125 	case PLDM_CRC_COMP_CAN_BE_UPDATED:
126 	case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
127 	case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
128 	case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
129 	case PLDM_CRC_COMP_CONFLICT:
130 	case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
131 	case PLDM_CRC_COMP_NOT_SUPPORTED:
132 	case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
133 	case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
134 	case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
135 	case PLDM_CRC_COMP_VER_STR_IDENTICAL:
136 	case PLDM_CRC_COMP_VER_STR_LOWER:
137 		return true;
138 
139 	default:
140 		if (comp_resp_code >=
141 			    PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
142 		    comp_resp_code <=
143 			    PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
144 			return true;
145 		}
146 		return false;
147 	}
148 }
149 
150 /** @brief Check whether ComponentCompatibilityResponse is valid
151  *
152  *  @return true if ComponentCompatibilityResponse is valid, false if not
153  */
154 static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
155 {
156 	switch (comp_compatibility_resp) {
157 	case PLDM_CCR_COMP_CAN_BE_UPDATED:
158 	case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
159 		return true;
160 
161 	default:
162 		return false;
163 	}
164 }
165 
166 /** @brief Check whether ComponentCompatibilityResponse Code is valid
167  *
168  *  @return true if ComponentCompatibilityResponse Code is valid, false if not
169  */
170 static bool
171 is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
172 {
173 	switch (comp_compatibility_resp_code) {
174 	case PLDM_CCRC_NO_RESPONSE_CODE:
175 	case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
176 	case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
177 	case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
178 	case PLDM_CCRC_COMP_CONFLICT:
179 	case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
180 	case PLDM_CCRC_COMP_NOT_SUPPORTED:
181 	case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
182 	case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
183 	case PLDM_CCRC_COMP_INFO_NO_MATCH:
184 	case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
185 	case PLDM_CCRC_COMP_VER_STR_LOWER:
186 		return true;
187 
188 	default:
189 		if (comp_compatibility_resp_code >=
190 			    PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
191 		    comp_compatibility_resp_code <=
192 			    PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
193 			return true;
194 		}
195 		return false;
196 	}
197 }
198 
199 /** @brief Check whether SelfContainedActivationRequest is valid
200  *
201  *  @return true if SelfContainedActivationRequest is valid, false if not
202  */
203 static bool
204 is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
205 {
206 	switch (self_contained_activation_req) {
207 	case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
208 	case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
209 		return true;
210 
211 	default:
212 		return false;
213 	}
214 }
215 
216 /** @brief Check if current or previous status in GetStatus command response is
217  *         valid
218  *
219  *	@param[in] state - current or previous different state machine state of
220  *                     the FD
221  *	@return true if state is valid, false if not
222  */
223 static bool is_state_valid(uint8_t state)
224 {
225 	switch (state) {
226 	case PLDM_FD_STATE_IDLE:
227 	case PLDM_FD_STATE_LEARN_COMPONENTS:
228 	case PLDM_FD_STATE_READY_XFER:
229 	case PLDM_FD_STATE_DOWNLOAD:
230 	case PLDM_FD_STATE_VERIFY:
231 	case PLDM_FD_STATE_APPLY:
232 	case PLDM_FD_STATE_ACTIVATE:
233 		return true;
234 
235 	default:
236 		return false;
237 	}
238 }
239 
240 /** @brief Check if aux state in GetStatus command response is valid
241  *
242  *  @param[in] aux_state - provides additional information to the UA to describe
243  *                         the current operation state of the FD/FDP
244  *
245  *	@return true if aux state is valid, false if not
246  */
247 static bool is_aux_state_valid(uint8_t aux_state)
248 {
249 	switch (aux_state) {
250 	case PLDM_FD_OPERATION_IN_PROGRESS:
251 	case PLDM_FD_OPERATION_SUCCESSFUL:
252 	case PLDM_FD_OPERATION_FAILED:
253 	case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER:
254 		return true;
255 
256 	default:
257 		return false;
258 	}
259 }
260 
261 /** @brief Check if aux state status in GetStatus command response is valid
262  *
263  *	@param[in] aux_state_status - aux state status
264  *
265  *	@return true if aux state status is valid, false if not
266  */
267 static bool is_aux_state_status_valid(uint8_t aux_state_status)
268 {
269 	if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS ||
270 	    aux_state_status == PLDM_FD_TIMEOUT ||
271 	    aux_state_status == PLDM_FD_GENERIC_ERROR ||
272 	    (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
273 	     aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) {
274 		return true;
275 	}
276 
277 	return false;
278 }
279 
280 /** @brief Check if reason code in GetStatus command response is valid
281  *
282  *	@param[in] reason_code - provides the reason for why the current state
283  *                           entered the IDLE state
284  *
285  *	@return true if reason code is valid, false if not
286  */
287 static bool is_reason_code_valid(uint8_t reason_code)
288 {
289 	switch (reason_code) {
290 	case PLDM_FD_INITIALIZATION:
291 	case PLDM_FD_ACTIVATE_FW:
292 	case PLDM_FD_CANCEL_UPDATE:
293 	case PLDM_FD_TIMEOUT_LEARN_COMPONENT:
294 	case PLDM_FD_TIMEOUT_READY_XFER:
295 	case PLDM_FD_TIMEOUT_DOWNLOAD:
296 	case PLDM_FD_TIMEOUT_VERIFY:
297 	case PLDM_FD_TIMEOUT_APPLY:
298 		return true;
299 
300 	default:
301 		if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) {
302 			return true;
303 		}
304 		return false;
305 	}
306 }
307 
308 /** @brief Check if non functioning component indication in CancelUpdate
309  *         response is valid
310  *
311  *  @return true if non functioning component indication is valid, false if not
312  */
313 static bool is_non_functioning_component_indication_valid(
314 	bool8_t non_functioning_component_indication)
315 {
316 	switch (non_functioning_component_indication) {
317 	case PLDM_FWUP_COMPONENTS_FUNCTIONING:
318 	case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING:
319 		return true;
320 
321 	default:
322 		return false;
323 	}
324 }
325 
326 LIBPLDM_ABI_STABLE
327 int decode_pldm_package_header_info(
328 	const uint8_t *data, size_t length,
329 	struct pldm_package_header_information *package_header_info,
330 	struct variable_field *package_version_str)
331 {
332 	if (data == NULL || package_header_info == NULL ||
333 	    package_version_str == NULL) {
334 		return PLDM_ERROR_INVALID_DATA;
335 	}
336 
337 	if (length < sizeof(struct pldm_package_header_information)) {
338 		return PLDM_ERROR_INVALID_LENGTH;
339 	}
340 
341 	struct pldm_package_header_information *data_header =
342 		(struct pldm_package_header_information *)(data);
343 
344 	if (!is_string_type_valid(data_header->package_version_string_type) ||
345 	    (data_header->package_version_string_length == 0)) {
346 		return PLDM_ERROR_INVALID_DATA;
347 	}
348 
349 	if (length < sizeof(struct pldm_package_header_information) +
350 			     data_header->package_version_string_length) {
351 		return PLDM_ERROR_INVALID_LENGTH;
352 	}
353 
354 	if ((data_header->component_bitmap_bit_length %
355 	     PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
356 		return PLDM_ERROR_INVALID_DATA;
357 	}
358 
359 	memcpy(package_header_info->uuid, data_header->uuid,
360 	       sizeof(data_header->uuid));
361 	package_header_info->package_header_format_version =
362 		data_header->package_header_format_version;
363 	package_header_info->package_header_size =
364 		le16toh(data_header->package_header_size);
365 	memcpy(package_header_info->package_release_date_time,
366 	       data_header->package_release_date_time,
367 	       sizeof(data_header->package_release_date_time));
368 	package_header_info->component_bitmap_bit_length =
369 		le16toh(data_header->component_bitmap_bit_length);
370 	package_header_info->package_version_string_type =
371 		data_header->package_version_string_type;
372 	package_header_info->package_version_string_length =
373 		data_header->package_version_string_length;
374 	package_version_str->ptr =
375 		data + sizeof(struct pldm_package_header_information);
376 	package_version_str->length =
377 		package_header_info->package_version_string_length;
378 
379 	return PLDM_SUCCESS;
380 }
381 
382 LIBPLDM_ABI_STABLE
383 int decode_firmware_device_id_record(
384 	const uint8_t *data, size_t length,
385 	uint16_t component_bitmap_bit_length,
386 	struct pldm_firmware_device_id_record *fw_device_id_record,
387 	struct variable_field *applicable_components,
388 	struct variable_field *comp_image_set_version_str,
389 	struct variable_field *record_descriptors,
390 	struct variable_field *fw_device_pkg_data)
391 {
392 	if (data == NULL || fw_device_id_record == NULL ||
393 	    applicable_components == NULL ||
394 	    comp_image_set_version_str == NULL || record_descriptors == NULL ||
395 	    fw_device_pkg_data == NULL) {
396 		return PLDM_ERROR_INVALID_DATA;
397 	}
398 
399 	if (length < sizeof(struct pldm_firmware_device_id_record)) {
400 		return PLDM_ERROR_INVALID_LENGTH;
401 	}
402 
403 	if ((component_bitmap_bit_length %
404 	     PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) {
405 		return PLDM_ERROR_INVALID_DATA;
406 	}
407 
408 	struct pldm_firmware_device_id_record *data_record =
409 		(struct pldm_firmware_device_id_record *)(data);
410 
411 	if (!is_string_type_valid(
412 		    data_record->comp_image_set_version_string_type) ||
413 	    (data_record->comp_image_set_version_string_length == 0)) {
414 		return PLDM_ERROR_INVALID_DATA;
415 	}
416 
417 	fw_device_id_record->record_length =
418 		le16toh(data_record->record_length);
419 	fw_device_id_record->descriptor_count = data_record->descriptor_count;
420 	fw_device_id_record->device_update_option_flags.value =
421 		le32toh(data_record->device_update_option_flags.value);
422 	fw_device_id_record->comp_image_set_version_string_type =
423 		data_record->comp_image_set_version_string_type;
424 	fw_device_id_record->comp_image_set_version_string_length =
425 		data_record->comp_image_set_version_string_length;
426 	fw_device_id_record->fw_device_pkg_data_length =
427 		le16toh(data_record->fw_device_pkg_data_length);
428 
429 	if (length < fw_device_id_record->record_length) {
430 		return PLDM_ERROR_INVALID_LENGTH;
431 	}
432 
433 	uint16_t applicable_components_length =
434 		component_bitmap_bit_length /
435 		PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE;
436 	uint16_t calc_min_record_length =
437 		sizeof(struct pldm_firmware_device_id_record) +
438 		applicable_components_length +
439 		data_record->comp_image_set_version_string_length +
440 		PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN +
441 		fw_device_id_record->fw_device_pkg_data_length;
442 
443 	if (fw_device_id_record->record_length < calc_min_record_length) {
444 		return PLDM_ERROR_INVALID_LENGTH;
445 	}
446 
447 	applicable_components->ptr =
448 		data + sizeof(struct pldm_firmware_device_id_record);
449 	applicable_components->length = applicable_components_length;
450 
451 	comp_image_set_version_str->ptr =
452 		applicable_components->ptr + applicable_components->length;
453 	comp_image_set_version_str->length =
454 		fw_device_id_record->comp_image_set_version_string_length;
455 
456 	record_descriptors->ptr = comp_image_set_version_str->ptr +
457 				  comp_image_set_version_str->length;
458 	record_descriptors->length =
459 		fw_device_id_record->record_length -
460 		sizeof(struct pldm_firmware_device_id_record) -
461 		applicable_components_length -
462 		fw_device_id_record->comp_image_set_version_string_length -
463 		fw_device_id_record->fw_device_pkg_data_length;
464 
465 	if (fw_device_id_record->fw_device_pkg_data_length) {
466 		fw_device_pkg_data->ptr =
467 			record_descriptors->ptr + record_descriptors->length;
468 		fw_device_pkg_data->length =
469 			fw_device_id_record->fw_device_pkg_data_length;
470 	}
471 
472 	return PLDM_SUCCESS;
473 }
474 
475 LIBPLDM_ABI_STABLE
476 int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
477 					uint16_t *descriptor_type,
478 					struct variable_field *descriptor_data)
479 {
480 	uint16_t descriptor_length = 0;
481 
482 	if (data == NULL || descriptor_type == NULL ||
483 	    descriptor_data == NULL) {
484 		return PLDM_ERROR_INVALID_DATA;
485 	}
486 
487 	if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
488 		return PLDM_ERROR_INVALID_LENGTH;
489 	}
490 
491 	struct pldm_descriptor_tlv *entry =
492 		(struct pldm_descriptor_tlv *)(data);
493 
494 	*descriptor_type = le16toh(entry->descriptor_type);
495 	descriptor_length = le16toh(entry->descriptor_length);
496 	if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
497 		if (descriptor_length !=
498 		    get_descriptor_type_length(*descriptor_type)) {
499 			return PLDM_ERROR_INVALID_LENGTH;
500 		}
501 	}
502 
503 	if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
504 		      descriptor_length)) {
505 		return PLDM_ERROR_INVALID_LENGTH;
506 	}
507 
508 	descriptor_data->ptr = entry->descriptor_data;
509 	descriptor_data->length = descriptor_length;
510 
511 	return PLDM_SUCCESS;
512 }
513 
514 LIBPLDM_ABI_STABLE
515 int decode_vendor_defined_descriptor_value(
516 	const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
517 	struct variable_field *descriptor_title_str,
518 	struct variable_field *descriptor_data)
519 {
520 	if (data == NULL || descriptor_title_str_type == NULL ||
521 	    descriptor_title_str == NULL || descriptor_data == NULL) {
522 		return PLDM_ERROR_INVALID_DATA;
523 	}
524 
525 	if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
526 		return PLDM_ERROR_INVALID_LENGTH;
527 	}
528 
529 	struct pldm_vendor_defined_descriptor_title_data *entry =
530 		(struct pldm_vendor_defined_descriptor_title_data *)(data);
531 	if (!is_string_type_valid(
532 		    entry->vendor_defined_descriptor_title_str_type) ||
533 	    (entry->vendor_defined_descriptor_title_str_len == 0)) {
534 		return PLDM_ERROR_INVALID_DATA;
535 	}
536 
537 	// Assuming at least 1 byte of VendorDefinedDescriptorData
538 	if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
539 		      entry->vendor_defined_descriptor_title_str_len)) {
540 		return PLDM_ERROR_INVALID_LENGTH;
541 	}
542 
543 	*descriptor_title_str_type =
544 		entry->vendor_defined_descriptor_title_str_type;
545 	descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
546 	descriptor_title_str->length =
547 		entry->vendor_defined_descriptor_title_str_len;
548 
549 	descriptor_data->ptr =
550 		descriptor_title_str->ptr + descriptor_title_str->length;
551 	descriptor_data->length =
552 		length -
553 		sizeof(entry->vendor_defined_descriptor_title_str_type) -
554 		sizeof(entry->vendor_defined_descriptor_title_str_len) -
555 		descriptor_title_str->length;
556 
557 	return PLDM_SUCCESS;
558 }
559 
560 LIBPLDM_ABI_STABLE
561 int decode_pldm_comp_image_info(
562 	const uint8_t *data, size_t length,
563 	struct pldm_component_image_information *pldm_comp_image_info,
564 	struct variable_field *comp_version_str)
565 {
566 	if (data == NULL || pldm_comp_image_info == NULL ||
567 	    comp_version_str == NULL) {
568 		return PLDM_ERROR_INVALID_DATA;
569 	}
570 
571 	if (length < sizeof(struct pldm_component_image_information)) {
572 		return PLDM_ERROR_INVALID_LENGTH;
573 	}
574 
575 	struct pldm_component_image_information *data_header =
576 		(struct pldm_component_image_information *)(data);
577 
578 	if (!is_string_type_valid(data_header->comp_version_string_type) ||
579 	    (data_header->comp_version_string_length == 0)) {
580 		return PLDM_ERROR_INVALID_DATA;
581 	}
582 
583 	if (length < sizeof(struct pldm_component_image_information) +
584 			     data_header->comp_version_string_length) {
585 		return PLDM_ERROR_INVALID_LENGTH;
586 	}
587 
588 	pldm_comp_image_info->comp_classification =
589 		le16toh(data_header->comp_classification);
590 	pldm_comp_image_info->comp_identifier =
591 		le16toh(data_header->comp_identifier);
592 	pldm_comp_image_info->comp_comparison_stamp =
593 		le32toh(data_header->comp_comparison_stamp);
594 	pldm_comp_image_info->comp_options.value =
595 		le16toh(data_header->comp_options.value);
596 	pldm_comp_image_info->requested_comp_activation_method.value =
597 		le16toh(data_header->requested_comp_activation_method.value);
598 	pldm_comp_image_info->comp_location_offset =
599 		le32toh(data_header->comp_location_offset);
600 	pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
601 	pldm_comp_image_info->comp_version_string_type =
602 		data_header->comp_version_string_type;
603 	pldm_comp_image_info->comp_version_string_length =
604 		data_header->comp_version_string_length;
605 
606 	if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
607 	     pldm_comp_image_info->comp_comparison_stamp !=
608 		     PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
609 		return PLDM_ERROR_INVALID_DATA;
610 	}
611 
612 	if (pldm_comp_image_info->comp_location_offset == 0 ||
613 	    pldm_comp_image_info->comp_size == 0) {
614 		return PLDM_ERROR_INVALID_DATA;
615 	}
616 
617 	comp_version_str->ptr =
618 		data + sizeof(struct pldm_component_image_information);
619 	comp_version_str->length =
620 		pldm_comp_image_info->comp_version_string_length;
621 
622 	return PLDM_SUCCESS;
623 }
624 
625 LIBPLDM_ABI_STABLE
626 int encode_query_device_identifiers_req(uint8_t instance_id,
627 					size_t payload_length,
628 					struct pldm_msg *msg)
629 {
630 	if (msg == NULL) {
631 		return PLDM_ERROR_INVALID_DATA;
632 	}
633 
634 	if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
635 		return PLDM_ERROR_INVALID_LENGTH;
636 	}
637 
638 	return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
639 				       PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
640 }
641 
642 LIBPLDM_ABI_STABLE
643 int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
644 					 size_t payload_length,
645 					 uint8_t *completion_code,
646 					 uint32_t *device_identifiers_len,
647 					 uint8_t *descriptor_count,
648 					 uint8_t **descriptor_data)
649 {
650 	if (msg == NULL || completion_code == NULL ||
651 	    device_identifiers_len == NULL || descriptor_count == NULL ||
652 	    descriptor_data == NULL) {
653 		return PLDM_ERROR_INVALID_DATA;
654 	}
655 
656 	*completion_code = msg->payload[0];
657 	if (PLDM_SUCCESS != *completion_code) {
658 		return PLDM_SUCCESS;
659 	}
660 
661 	if (payload_length <
662 	    sizeof(struct pldm_query_device_identifiers_resp)) {
663 		return PLDM_ERROR_INVALID_LENGTH;
664 	}
665 
666 	struct pldm_query_device_identifiers_resp *response =
667 		(struct pldm_query_device_identifiers_resp *)msg->payload;
668 	*device_identifiers_len = le32toh(response->device_identifiers_len);
669 
670 	if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
671 		return PLDM_ERROR_INVALID_LENGTH;
672 	}
673 
674 	if (payload_length !=
675 	    sizeof(struct pldm_query_device_identifiers_resp) +
676 		    *device_identifiers_len) {
677 		return PLDM_ERROR_INVALID_LENGTH;
678 	}
679 	*descriptor_count = response->descriptor_count;
680 
681 	if (*descriptor_count == 0) {
682 		return PLDM_ERROR_INVALID_DATA;
683 	}
684 	*descriptor_data =
685 		(uint8_t *)(msg->payload +
686 			    sizeof(struct pldm_query_device_identifiers_resp));
687 	return PLDM_SUCCESS;
688 }
689 
690 LIBPLDM_ABI_STABLE
691 int encode_get_firmware_parameters_req(uint8_t instance_id,
692 				       size_t payload_length,
693 				       struct pldm_msg *msg)
694 {
695 	if (msg == NULL) {
696 		return PLDM_ERROR_INVALID_DATA;
697 	}
698 
699 	if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
700 		return PLDM_ERROR_INVALID_LENGTH;
701 	}
702 
703 	return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
704 				       PLDM_GET_FIRMWARE_PARAMETERS, msg);
705 }
706 
707 LIBPLDM_ABI_STABLE
708 int decode_get_firmware_parameters_resp(
709 	const struct pldm_msg *msg, size_t payload_length,
710 	struct pldm_get_firmware_parameters_resp *resp_data,
711 	struct variable_field *active_comp_image_set_ver_str,
712 	struct variable_field *pending_comp_image_set_ver_str,
713 	struct variable_field *comp_parameter_table)
714 {
715 	if (msg == NULL || resp_data == NULL ||
716 	    active_comp_image_set_ver_str == NULL ||
717 	    pending_comp_image_set_ver_str == NULL ||
718 	    comp_parameter_table == NULL || !payload_length) {
719 		return PLDM_ERROR_INVALID_DATA;
720 	}
721 
722 	resp_data->completion_code = msg->payload[0];
723 	if (PLDM_SUCCESS != resp_data->completion_code) {
724 		return PLDM_SUCCESS;
725 	}
726 
727 	if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
728 		return PLDM_ERROR_INVALID_LENGTH;
729 	}
730 
731 	struct pldm_get_firmware_parameters_resp *response =
732 		(struct pldm_get_firmware_parameters_resp *)msg->payload;
733 
734 	if (!is_string_type_valid(
735 		    response->active_comp_image_set_ver_str_type) ||
736 	    (response->active_comp_image_set_ver_str_len == 0)) {
737 		return PLDM_ERROR_INVALID_DATA;
738 	}
739 
740 	if (response->pending_comp_image_set_ver_str_len == 0) {
741 		if (response->pending_comp_image_set_ver_str_type !=
742 		    PLDM_STR_TYPE_UNKNOWN) {
743 			return PLDM_ERROR_INVALID_DATA;
744 		}
745 	} else {
746 		if (!is_string_type_valid(
747 			    response->pending_comp_image_set_ver_str_type)) {
748 			return PLDM_ERROR_INVALID_DATA;
749 		}
750 	}
751 
752 	size_t partial_response_length =
753 		sizeof(struct pldm_get_firmware_parameters_resp) +
754 		response->active_comp_image_set_ver_str_len +
755 		response->pending_comp_image_set_ver_str_len;
756 
757 	if (payload_length < partial_response_length) {
758 		return PLDM_ERROR_INVALID_LENGTH;
759 	}
760 
761 	resp_data->capabilities_during_update.value =
762 		le32toh(response->capabilities_during_update.value);
763 	resp_data->comp_count = le16toh(response->comp_count);
764 	resp_data->active_comp_image_set_ver_str_type =
765 		response->active_comp_image_set_ver_str_type;
766 	resp_data->active_comp_image_set_ver_str_len =
767 		response->active_comp_image_set_ver_str_len;
768 	resp_data->pending_comp_image_set_ver_str_type =
769 		response->pending_comp_image_set_ver_str_type;
770 	resp_data->pending_comp_image_set_ver_str_len =
771 		response->pending_comp_image_set_ver_str_len;
772 
773 	active_comp_image_set_ver_str->ptr =
774 		msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
775 	active_comp_image_set_ver_str->length =
776 		resp_data->active_comp_image_set_ver_str_len;
777 
778 	if (resp_data->pending_comp_image_set_ver_str_len != 0) {
779 		pending_comp_image_set_ver_str->ptr =
780 			msg->payload +
781 			sizeof(struct pldm_get_firmware_parameters_resp) +
782 			resp_data->active_comp_image_set_ver_str_len;
783 		pending_comp_image_set_ver_str->length =
784 			resp_data->pending_comp_image_set_ver_str_len;
785 	} else {
786 		pending_comp_image_set_ver_str->ptr = NULL;
787 		pending_comp_image_set_ver_str->length = 0;
788 	}
789 
790 	if (payload_length > partial_response_length && resp_data->comp_count) {
791 		comp_parameter_table->ptr =
792 			msg->payload +
793 			sizeof(struct pldm_get_firmware_parameters_resp) +
794 			resp_data->active_comp_image_set_ver_str_len +
795 			resp_data->pending_comp_image_set_ver_str_len;
796 		comp_parameter_table->length =
797 			payload_length - partial_response_length;
798 	} else {
799 		comp_parameter_table->ptr = NULL;
800 		comp_parameter_table->length = 0;
801 	}
802 
803 	return PLDM_SUCCESS;
804 }
805 
806 LIBPLDM_ABI_STABLE
807 int decode_get_firmware_parameters_resp_comp_entry(
808 	const uint8_t *data, size_t length,
809 	struct pldm_component_parameter_entry *component_data,
810 	struct variable_field *active_comp_ver_str,
811 	struct variable_field *pending_comp_ver_str)
812 {
813 	if (data == NULL || component_data == NULL ||
814 	    active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
815 		return PLDM_ERROR_INVALID_DATA;
816 	}
817 
818 	if (length < sizeof(struct pldm_component_parameter_entry)) {
819 		return PLDM_ERROR_INVALID_LENGTH;
820 	}
821 
822 	struct pldm_component_parameter_entry *entry =
823 		(struct pldm_component_parameter_entry *)(data);
824 
825 	size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
826 			      entry->active_comp_ver_str_len +
827 			      entry->pending_comp_ver_str_len;
828 
829 	if (length < entry_length) {
830 		return PLDM_ERROR_INVALID_LENGTH;
831 	}
832 
833 	component_data->comp_classification =
834 		le16toh(entry->comp_classification);
835 	component_data->comp_identifier = le16toh(entry->comp_identifier);
836 	component_data->comp_classification_index =
837 		entry->comp_classification_index;
838 	component_data->active_comp_comparison_stamp =
839 		le32toh(entry->active_comp_comparison_stamp);
840 	component_data->active_comp_ver_str_type =
841 		entry->active_comp_ver_str_type;
842 	component_data->active_comp_ver_str_len =
843 		entry->active_comp_ver_str_len;
844 	memcpy(component_data->active_comp_release_date,
845 	       entry->active_comp_release_date,
846 	       sizeof(entry->active_comp_release_date));
847 	component_data->pending_comp_comparison_stamp =
848 		le32toh(entry->pending_comp_comparison_stamp);
849 	component_data->pending_comp_ver_str_type =
850 		entry->pending_comp_ver_str_type;
851 	component_data->pending_comp_ver_str_len =
852 		entry->pending_comp_ver_str_len;
853 	memcpy(component_data->pending_comp_release_date,
854 	       entry->pending_comp_release_date,
855 	       sizeof(entry->pending_comp_release_date));
856 	component_data->comp_activation_methods.value =
857 		le16toh(entry->comp_activation_methods.value);
858 	component_data->capabilities_during_update.value =
859 		le32toh(entry->capabilities_during_update.value);
860 
861 	if (entry->active_comp_ver_str_len != 0) {
862 		active_comp_ver_str->ptr =
863 			data + sizeof(struct pldm_component_parameter_entry);
864 		active_comp_ver_str->length = entry->active_comp_ver_str_len;
865 	} else {
866 		active_comp_ver_str->ptr = NULL;
867 		active_comp_ver_str->length = 0;
868 	}
869 
870 	if (entry->pending_comp_ver_str_len != 0) {
871 		pending_comp_ver_str->ptr =
872 			data + sizeof(struct pldm_component_parameter_entry) +
873 			entry->active_comp_ver_str_len;
874 		pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
875 	} else {
876 		pending_comp_ver_str->ptr = NULL;
877 		pending_comp_ver_str->length = 0;
878 	}
879 	return PLDM_SUCCESS;
880 }
881 
882 LIBPLDM_ABI_TESTING
883 int encode_query_downstream_devices_req(uint8_t instance_id,
884 					struct pldm_msg *msg)
885 {
886 	if (msg == NULL) {
887 		return PLDM_ERROR_INVALID_DATA;
888 	}
889 
890 	return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
891 				       PLDM_QUERY_DOWNSTREAM_DEVICES, msg);
892 }
893 
894 LIBPLDM_ABI_TESTING
895 int decode_query_downstream_devices_resp(
896 	const struct pldm_msg *msg, size_t payload_length,
897 	struct pldm_query_downstream_devices_resp *resp_data)
898 {
899 	struct pldm_msgbuf _buf;
900 	struct pldm_msgbuf *buf = &_buf;
901 	int rc;
902 
903 	if (msg == NULL || resp_data == NULL || !payload_length) {
904 		return PLDM_ERROR_INVALID_DATA;
905 	}
906 
907 	rc = pldm_msgbuf_init_cc(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
908 				 msg->payload, payload_length);
909 	if (rc) {
910 		return rc;
911 	}
912 
913 	rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
914 	if (rc) {
915 		return rc;
916 	}
917 	if (PLDM_SUCCESS != resp_data->completion_code) {
918 		// Return the CC directly without decoding the rest of the payload
919 		return PLDM_SUCCESS;
920 	}
921 
922 	if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) {
923 		return PLDM_ERROR_INVALID_LENGTH;
924 	}
925 
926 	rc = pldm_msgbuf_extract(buf,
927 				 resp_data->downstream_device_update_supported);
928 	if (rc) {
929 		return rc;
930 	}
931 
932 	if (!is_downstream_device_update_support_valid(
933 		    resp_data->downstream_device_update_supported)) {
934 		return PLDM_ERROR_INVALID_DATA;
935 	}
936 
937 	pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
938 	pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices);
939 	pldm_msgbuf_extract(buf, resp_data->capabilities.value);
940 
941 	return pldm_msgbuf_destroy_consumed(buf);
942 }
943 
944 LIBPLDM_ABI_TESTING
945 int encode_query_downstream_identifiers_req(
946 	uint8_t instance_id, uint32_t data_transfer_handle,
947 	enum transfer_op_flag transfer_operation_flag, struct pldm_msg *msg,
948 	size_t payload_length)
949 {
950 	struct pldm_msgbuf _buf;
951 	struct pldm_msgbuf *buf = &_buf;
952 	int rc;
953 
954 	if (msg == NULL) {
955 		return PLDM_ERROR_INVALID_DATA;
956 	}
957 
958 	if (!is_transfer_operation_flag_valid(transfer_operation_flag)) {
959 		return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
960 	}
961 
962 	struct pldm_header_info header = { 0 };
963 	header.instance = instance_id;
964 	header.msg_type = PLDM_REQUEST;
965 	header.pldm_type = PLDM_FWUP;
966 	header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS;
967 	rc = pack_pldm_header(&header, &(msg->hdr));
968 	if (rc) {
969 		return rc;
970 	}
971 
972 	rc = pldm_msgbuf_init_cc(buf,
973 				 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES,
974 				 msg->payload, payload_length);
975 	if (rc) {
976 		return rc;
977 	}
978 
979 	pldm_msgbuf_insert(buf, data_transfer_handle);
980 	// Data correctness has been verified, cast it to 1-byte data directly.
981 	pldm_msgbuf_insert(buf, (uint8_t)transfer_operation_flag);
982 
983 	return pldm_msgbuf_destroy(buf);
984 }
985 
986 LIBPLDM_ABI_TESTING
987 int decode_query_downstream_identifiers_resp(
988 	const struct pldm_msg *msg, size_t payload_length,
989 	struct pldm_query_downstream_identifiers_resp *resp_data,
990 	struct variable_field *downstream_devices)
991 {
992 	struct pldm_msgbuf _buf;
993 	struct pldm_msgbuf *buf = &_buf;
994 	int rc = PLDM_ERROR;
995 
996 	if (msg == NULL || resp_data == NULL || downstream_devices == NULL ||
997 	    !payload_length) {
998 		return PLDM_ERROR_INVALID_DATA;
999 	}
1000 
1001 	rc = pldm_msgbuf_init_cc(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1002 				 msg->payload, payload_length);
1003 	if (rc) {
1004 		return rc;
1005 	}
1006 
1007 	rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1008 	if (rc) {
1009 		return rc;
1010 	}
1011 	if (PLDM_SUCCESS != resp_data->completion_code) {
1012 		return PLDM_SUCCESS;
1013 	}
1014 
1015 	if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) {
1016 		return PLDM_ERROR_INVALID_LENGTH;
1017 	}
1018 
1019 	pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1020 	pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1021 
1022 	rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length);
1023 	if (rc) {
1024 		return rc;
1025 	}
1026 
1027 	pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
1028 	rc = pldm_msgbuf_span_required(buf,
1029 				       resp_data->downstream_devices_length,
1030 				       (void **)&downstream_devices->ptr);
1031 	if (rc) {
1032 		return rc;
1033 	}
1034 	downstream_devices->length = resp_data->downstream_devices_length;
1035 
1036 	return pldm_msgbuf_destroy(buf);
1037 }
1038 
1039 LIBPLDM_ABI_TESTING
1040 int encode_get_downstream_firmware_params_req(
1041 	uint8_t instance_id, uint32_t data_transfer_handle,
1042 	enum transfer_op_flag transfer_operation_flag, struct pldm_msg *msg,
1043 	size_t payload_length)
1044 {
1045 	struct pldm_msgbuf _buf;
1046 	struct pldm_msgbuf *buf = &_buf;
1047 	int rc;
1048 
1049 	if (msg == NULL) {
1050 		return -EINVAL;
1051 	}
1052 
1053 	rc = pldm_msgbuf_init_errno(
1054 		buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_REQ_BYTES,
1055 		msg->payload, payload_length);
1056 	if (rc < 0) {
1057 		return rc;
1058 	}
1059 
1060 	if (!is_transfer_operation_flag_valid(transfer_operation_flag)) {
1061 		return -EBADMSG;
1062 	}
1063 
1064 	struct pldm_header_info header = { 0 };
1065 	header.instance = instance_id;
1066 	header.msg_type = PLDM_REQUEST;
1067 	header.pldm_type = PLDM_FWUP;
1068 	header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS;
1069 	rc = pack_pldm_header_errno(&header, &msg->hdr);
1070 	if (rc < 0) {
1071 		return rc;
1072 	}
1073 
1074 	pldm_msgbuf_insert(buf, data_transfer_handle);
1075 	// Data correctness has been verified, cast it to 1-byte data directly.
1076 	pldm_msgbuf_insert(buf, (uint8_t)transfer_operation_flag);
1077 
1078 	return pldm_msgbuf_destroy(buf);
1079 }
1080 
1081 LIBPLDM_ABI_TESTING
1082 int decode_get_downstream_firmware_params_resp(
1083 	const struct pldm_msg *msg, size_t payload_length,
1084 	struct pldm_get_downstream_firmware_params_resp *resp_data,
1085 	struct variable_field *downstream_device_param_table)
1086 {
1087 	struct pldm_msgbuf _buf;
1088 	struct pldm_msgbuf *buf = &_buf;
1089 	int rc;
1090 
1091 	if (msg == NULL || resp_data == NULL ||
1092 	    downstream_device_param_table == NULL) {
1093 		return -EINVAL;
1094 	}
1095 
1096 	rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1097 				    msg->payload, payload_length);
1098 	if (rc < 0) {
1099 		return rc;
1100 	}
1101 
1102 	rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1103 	if (rc < 0) {
1104 		return rc;
1105 	}
1106 	if (PLDM_SUCCESS != resp_data->completion_code) {
1107 		return 0;
1108 	}
1109 
1110 	if (payload_length < PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_RESP_MIN_LEN) {
1111 		return -EBADMSG;
1112 	}
1113 
1114 	pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1115 	pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1116 	pldm_msgbuf_extract(buf,
1117 			    resp_data->fdp_capabilities_during_update.value);
1118 	pldm_msgbuf_extract(buf, resp_data->downstream_device_count);
1119 
1120 	return pldm_msgbuf_span_remaining(
1121 		buf, (void **)&downstream_device_param_table->ptr,
1122 		&downstream_device_param_table->length);
1123 }
1124 
1125 LIBPLDM_ABI_TESTING
1126 int decode_downstream_device_parameter_table_entry(
1127 	struct variable_field *data,
1128 	struct pldm_downstream_device_parameter_entry *entry,
1129 	struct variable_field *versions)
1130 {
1131 	struct pldm_msgbuf _buf;
1132 	struct pldm_msgbuf *buf = &_buf;
1133 	void *cursor = NULL;
1134 	size_t remaining;
1135 	int rc;
1136 
1137 	if (data == NULL || entry == NULL || versions == NULL) {
1138 		return -EINVAL;
1139 	}
1140 
1141 	rc = pldm_msgbuf_init_errno(
1142 		buf, PLDM_DOWNSTREAM_DEVICE_PARAMETER_ENTRY_MIN_LEN, data->ptr,
1143 		data->length);
1144 	if (rc < 0) {
1145 		return rc;
1146 	}
1147 
1148 	pldm_msgbuf_extract(buf, entry->downstream_device_index);
1149 	pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp);
1150 	pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type);
1151 	rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len);
1152 	if (rc < 0) {
1153 		return rc;
1154 	}
1155 	pldm_msgbuf_extract_array(buf, entry->active_comp_release_date,
1156 				  PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
1157 	// Fill the last byte with NULL character
1158 	entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1159 		'\0';
1160 
1161 	pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp);
1162 	pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type);
1163 	rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len);
1164 	if (rc < 0) {
1165 		return rc;
1166 	}
1167 	pldm_msgbuf_extract_array(buf, entry->pending_comp_release_date,
1168 				  PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
1169 	// Fill the last byte with NULL character
1170 	entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1171 		'\0';
1172 
1173 	pldm_msgbuf_extract(buf, entry->comp_activation_methods.value);
1174 	pldm_msgbuf_extract(buf, entry->capabilities_during_update.value);
1175 	const size_t versions_len = entry->active_comp_ver_str_len +
1176 				    entry->pending_comp_ver_str_len;
1177 	rc = pldm_msgbuf_span_required(buf, versions_len,
1178 				       (void **)&versions->ptr);
1179 	if (rc < 0) {
1180 		return rc;
1181 	}
1182 	versions->length = versions_len;
1183 
1184 	rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining);
1185 	if (rc < 0) {
1186 		return rc;
1187 	}
1188 
1189 	data->ptr = cursor;
1190 	data->length = remaining;
1191 
1192 	return 0;
1193 }
1194 
1195 LIBPLDM_ABI_TESTING
1196 int decode_downstream_device_parameter_table_entry_versions(
1197 	const struct variable_field *versions,
1198 	struct pldm_downstream_device_parameter_entry *entry, char *active,
1199 	char *pending)
1200 {
1201 	struct pldm_msgbuf _buf;
1202 	struct pldm_msgbuf *buf = &_buf;
1203 	int rc;
1204 
1205 	if (versions == NULL || versions->ptr == NULL || !versions->length ||
1206 	    entry == NULL || active == NULL || pending == NULL) {
1207 		return -EINVAL;
1208 	}
1209 
1210 	/* This API should be called after decode_downstream_device_parameter_table_entry
1211 	 * has successfully decoded the entry, assume the entry data is valid here.
1212 	 */
1213 	const size_t versions_len = entry->active_comp_ver_str_len +
1214 				    entry->pending_comp_ver_str_len;
1215 	rc = pldm_msgbuf_init_errno(buf, versions_len, versions->ptr,
1216 				    versions->length);
1217 	if (rc < 0) {
1218 		return rc;
1219 	}
1220 
1221 	pldm_msgbuf_extract_array(buf, active, entry->active_comp_ver_str_len);
1222 	active[entry->active_comp_ver_str_len] = '\0';
1223 	pldm_msgbuf_extract_array(buf, pending,
1224 				  entry->pending_comp_ver_str_len);
1225 	pending[entry->pending_comp_ver_str_len] = '\0';
1226 
1227 	entry->active_comp_ver_str = active;
1228 	entry->pending_comp_ver_str = pending;
1229 
1230 	return pldm_msgbuf_destroy_consumed(buf);
1231 }
1232 
1233 LIBPLDM_ABI_STABLE
1234 int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
1235 			      uint16_t num_of_comp,
1236 			      uint8_t max_outstanding_transfer_req,
1237 			      uint16_t pkg_data_len,
1238 			      uint8_t comp_image_set_ver_str_type,
1239 			      uint8_t comp_image_set_ver_str_len,
1240 			      const struct variable_field *comp_img_set_ver_str,
1241 			      struct pldm_msg *msg, size_t payload_length)
1242 {
1243 	if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
1244 	    msg == NULL) {
1245 		return PLDM_ERROR_INVALID_DATA;
1246 	}
1247 
1248 	if (payload_length != sizeof(struct pldm_request_update_req) +
1249 				      comp_img_set_ver_str->length) {
1250 		return PLDM_ERROR_INVALID_LENGTH;
1251 	}
1252 
1253 	if ((comp_image_set_ver_str_len == 0) ||
1254 	    (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
1255 		return PLDM_ERROR_INVALID_DATA;
1256 	}
1257 
1258 	if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
1259 	    (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
1260 		return PLDM_ERROR_INVALID_DATA;
1261 	}
1262 
1263 	if (!is_string_type_valid(comp_image_set_ver_str_type)) {
1264 		return PLDM_ERROR_INVALID_DATA;
1265 	}
1266 
1267 	struct pldm_header_info header = { 0 };
1268 	header.instance = instance_id;
1269 	header.msg_type = PLDM_REQUEST;
1270 	header.pldm_type = PLDM_FWUP;
1271 	header.command = PLDM_REQUEST_UPDATE;
1272 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1273 	if (rc) {
1274 		return rc;
1275 	}
1276 
1277 	struct pldm_request_update_req *request =
1278 		(struct pldm_request_update_req *)msg->payload;
1279 
1280 	request->max_transfer_size = htole32(max_transfer_size);
1281 	request->num_of_comp = htole16(num_of_comp);
1282 	request->max_outstanding_transfer_req = max_outstanding_transfer_req;
1283 	request->pkg_data_len = htole16(pkg_data_len);
1284 	request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
1285 	request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
1286 
1287 	memcpy(msg->payload + sizeof(struct pldm_request_update_req),
1288 	       comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
1289 
1290 	return PLDM_SUCCESS;
1291 }
1292 
1293 LIBPLDM_ABI_STABLE
1294 int decode_request_update_resp(const struct pldm_msg *msg,
1295 			       size_t payload_length, uint8_t *completion_code,
1296 			       uint16_t *fd_meta_data_len,
1297 			       uint8_t *fd_will_send_pkg_data)
1298 {
1299 	if (msg == NULL || completion_code == NULL ||
1300 	    fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
1301 	    !payload_length) {
1302 		return PLDM_ERROR_INVALID_DATA;
1303 	}
1304 
1305 	*completion_code = msg->payload[0];
1306 	if (*completion_code != PLDM_SUCCESS) {
1307 		return PLDM_SUCCESS;
1308 	}
1309 
1310 	if (payload_length != sizeof(struct pldm_request_update_resp)) {
1311 		return PLDM_ERROR_INVALID_LENGTH;
1312 	}
1313 
1314 	struct pldm_request_update_resp *response =
1315 		(struct pldm_request_update_resp *)msg->payload;
1316 
1317 	*fd_meta_data_len = le16toh(response->fd_meta_data_len);
1318 	*fd_will_send_pkg_data = response->fd_will_send_pkg_data;
1319 
1320 	return PLDM_SUCCESS;
1321 }
1322 
1323 LIBPLDM_ABI_STABLE
1324 int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
1325 				    uint16_t comp_classification,
1326 				    uint16_t comp_identifier,
1327 				    uint8_t comp_classification_index,
1328 				    uint32_t comp_comparison_stamp,
1329 				    uint8_t comp_ver_str_type,
1330 				    uint8_t comp_ver_str_len,
1331 				    const struct variable_field *comp_ver_str,
1332 				    struct pldm_msg *msg, size_t payload_length)
1333 {
1334 	if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1335 		return PLDM_ERROR_INVALID_DATA;
1336 	}
1337 
1338 	if (payload_length != sizeof(struct pldm_pass_component_table_req) +
1339 				      comp_ver_str->length) {
1340 		return PLDM_ERROR_INVALID_LENGTH;
1341 	}
1342 
1343 	if ((comp_ver_str_len == 0) ||
1344 	    (comp_ver_str_len != comp_ver_str->length)) {
1345 		return PLDM_ERROR_INVALID_DATA;
1346 	}
1347 
1348 	if (!is_transfer_flag_valid(transfer_flag)) {
1349 		return PLDM_INVALID_TRANSFER_OPERATION_FLAG;
1350 	}
1351 
1352 	if (!is_string_type_valid(comp_ver_str_type)) {
1353 		return PLDM_ERROR_INVALID_DATA;
1354 	}
1355 
1356 	struct pldm_header_info header = { 0 };
1357 	header.instance = instance_id;
1358 	header.msg_type = PLDM_REQUEST;
1359 	header.pldm_type = PLDM_FWUP;
1360 	header.command = PLDM_PASS_COMPONENT_TABLE;
1361 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1362 	if (rc) {
1363 		return rc;
1364 	}
1365 
1366 	struct pldm_pass_component_table_req *request =
1367 		(struct pldm_pass_component_table_req *)msg->payload;
1368 
1369 	request->transfer_flag = transfer_flag;
1370 	request->comp_classification = htole16(comp_classification);
1371 	request->comp_identifier = htole16(comp_identifier);
1372 	request->comp_classification_index = comp_classification_index;
1373 	request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1374 	request->comp_ver_str_type = comp_ver_str_type;
1375 	request->comp_ver_str_len = comp_ver_str_len;
1376 
1377 	memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
1378 	       comp_ver_str->ptr, comp_ver_str->length);
1379 
1380 	return PLDM_SUCCESS;
1381 }
1382 
1383 LIBPLDM_ABI_STABLE
1384 int decode_pass_component_table_resp(const struct pldm_msg *msg,
1385 				     const size_t payload_length,
1386 				     uint8_t *completion_code,
1387 				     uint8_t *comp_resp,
1388 				     uint8_t *comp_resp_code)
1389 {
1390 	if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
1391 	    comp_resp_code == NULL || !payload_length) {
1392 		return PLDM_ERROR_INVALID_DATA;
1393 	}
1394 
1395 	*completion_code = msg->payload[0];
1396 	if (*completion_code != PLDM_SUCCESS) {
1397 		return PLDM_SUCCESS;
1398 	}
1399 
1400 	if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
1401 		return PLDM_ERROR_INVALID_LENGTH;
1402 	}
1403 
1404 	struct pldm_pass_component_table_resp *response =
1405 		(struct pldm_pass_component_table_resp *)msg->payload;
1406 
1407 	if (!is_comp_resp_valid(response->comp_resp)) {
1408 		return PLDM_ERROR_INVALID_DATA;
1409 	}
1410 
1411 	if (!is_comp_resp_code_valid(response->comp_resp_code)) {
1412 		return PLDM_ERROR_INVALID_DATA;
1413 	}
1414 
1415 	*comp_resp = response->comp_resp;
1416 	*comp_resp_code = response->comp_resp_code;
1417 
1418 	return PLDM_SUCCESS;
1419 }
1420 
1421 LIBPLDM_ABI_STABLE
1422 int encode_update_component_req(
1423 	uint8_t instance_id, uint16_t comp_classification,
1424 	uint16_t comp_identifier, uint8_t comp_classification_index,
1425 	uint32_t comp_comparison_stamp, uint32_t comp_image_size,
1426 	bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
1427 	uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
1428 	struct pldm_msg *msg, size_t payload_length)
1429 {
1430 	if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
1431 		return PLDM_ERROR_INVALID_DATA;
1432 	}
1433 
1434 	if (payload_length !=
1435 	    sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
1436 		return PLDM_ERROR_INVALID_LENGTH;
1437 	}
1438 
1439 	if (!comp_image_size) {
1440 		return PLDM_ERROR_INVALID_DATA;
1441 	}
1442 
1443 	if ((comp_ver_str_len == 0) ||
1444 	    (comp_ver_str_len != comp_ver_str->length)) {
1445 		return PLDM_ERROR_INVALID_DATA;
1446 	}
1447 
1448 	if (!is_string_type_valid(comp_ver_str_type)) {
1449 		return PLDM_ERROR_INVALID_DATA;
1450 	}
1451 
1452 	struct pldm_header_info header = { 0 };
1453 	header.instance = instance_id;
1454 	header.msg_type = PLDM_REQUEST;
1455 	header.pldm_type = PLDM_FWUP;
1456 	header.command = PLDM_UPDATE_COMPONENT;
1457 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1458 	if (rc) {
1459 		return rc;
1460 	}
1461 
1462 	struct pldm_update_component_req *request =
1463 		(struct pldm_update_component_req *)msg->payload;
1464 
1465 	request->comp_classification = htole16(comp_classification);
1466 	request->comp_identifier = htole16(comp_identifier);
1467 	request->comp_classification_index = comp_classification_index;
1468 	request->comp_comparison_stamp = htole32(comp_comparison_stamp);
1469 	request->comp_image_size = htole32(comp_image_size);
1470 	request->update_option_flags.value = htole32(update_option_flags.value);
1471 	request->comp_ver_str_type = comp_ver_str_type;
1472 	request->comp_ver_str_len = comp_ver_str_len;
1473 
1474 	memcpy(msg->payload + sizeof(struct pldm_update_component_req),
1475 	       comp_ver_str->ptr, comp_ver_str->length);
1476 
1477 	return PLDM_SUCCESS;
1478 }
1479 
1480 LIBPLDM_ABI_STABLE
1481 int decode_update_component_resp(const struct pldm_msg *msg,
1482 				 size_t payload_length,
1483 				 uint8_t *completion_code,
1484 				 uint8_t *comp_compatibility_resp,
1485 				 uint8_t *comp_compatibility_resp_code,
1486 				 bitfield32_t *update_option_flags_enabled,
1487 				 uint16_t *time_before_req_fw_data)
1488 {
1489 	if (msg == NULL || completion_code == NULL ||
1490 	    comp_compatibility_resp == NULL ||
1491 	    comp_compatibility_resp_code == NULL ||
1492 	    update_option_flags_enabled == NULL ||
1493 	    time_before_req_fw_data == NULL || !payload_length) {
1494 		return PLDM_ERROR_INVALID_DATA;
1495 	}
1496 
1497 	*completion_code = msg->payload[0];
1498 	if (*completion_code != PLDM_SUCCESS) {
1499 		return PLDM_SUCCESS;
1500 	}
1501 
1502 	if (payload_length != sizeof(struct pldm_update_component_resp)) {
1503 		return PLDM_ERROR_INVALID_LENGTH;
1504 	}
1505 
1506 	struct pldm_update_component_resp *response =
1507 		(struct pldm_update_component_resp *)msg->payload;
1508 
1509 	if (!is_comp_compatibility_resp_valid(
1510 		    response->comp_compatibility_resp)) {
1511 		return PLDM_ERROR_INVALID_DATA;
1512 	}
1513 
1514 	if (!is_comp_compatibility_resp_code_valid(
1515 		    response->comp_compatibility_resp_code)) {
1516 		return PLDM_ERROR_INVALID_DATA;
1517 	}
1518 
1519 	*comp_compatibility_resp = response->comp_compatibility_resp;
1520 	*comp_compatibility_resp_code = response->comp_compatibility_resp_code;
1521 	update_option_flags_enabled->value =
1522 		le32toh(response->update_option_flags_enabled.value);
1523 	*time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
1524 
1525 	return PLDM_SUCCESS;
1526 }
1527 
1528 LIBPLDM_ABI_STABLE
1529 int decode_request_firmware_data_req(const struct pldm_msg *msg,
1530 				     size_t payload_length, uint32_t *offset,
1531 				     uint32_t *length)
1532 {
1533 	if (msg == NULL || offset == NULL || length == NULL) {
1534 		return PLDM_ERROR_INVALID_DATA;
1535 	}
1536 	if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
1537 		return PLDM_ERROR_INVALID_LENGTH;
1538 	}
1539 	struct pldm_request_firmware_data_req *request =
1540 		(struct pldm_request_firmware_data_req *)msg->payload;
1541 	*offset = le32toh(request->offset);
1542 	*length = le32toh(request->length);
1543 
1544 	if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
1545 		return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
1546 	}
1547 
1548 	return PLDM_SUCCESS;
1549 }
1550 
1551 LIBPLDM_ABI_STABLE
1552 int encode_request_firmware_data_resp(uint8_t instance_id,
1553 				      uint8_t completion_code,
1554 				      struct pldm_msg *msg,
1555 				      size_t payload_length)
1556 {
1557 	if (msg == NULL || !payload_length) {
1558 		return PLDM_ERROR_INVALID_DATA;
1559 	}
1560 
1561 	struct pldm_header_info header = { 0 };
1562 	header.instance = instance_id;
1563 	header.msg_type = PLDM_RESPONSE;
1564 	header.pldm_type = PLDM_FWUP;
1565 	header.command = PLDM_REQUEST_FIRMWARE_DATA;
1566 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1567 	if (rc) {
1568 		return rc;
1569 	}
1570 
1571 	msg->payload[0] = completion_code;
1572 
1573 	return PLDM_SUCCESS;
1574 }
1575 
1576 LIBPLDM_ABI_STABLE
1577 int decode_transfer_complete_req(const struct pldm_msg *msg,
1578 				 size_t payload_length,
1579 				 uint8_t *transfer_result)
1580 {
1581 	if (msg == NULL || transfer_result == NULL) {
1582 		return PLDM_ERROR_INVALID_DATA;
1583 	}
1584 
1585 	if (payload_length != sizeof(*transfer_result)) {
1586 		return PLDM_ERROR_INVALID_LENGTH;
1587 	}
1588 
1589 	*transfer_result = msg->payload[0];
1590 	return PLDM_SUCCESS;
1591 }
1592 
1593 LIBPLDM_ABI_STABLE
1594 int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
1595 				  struct pldm_msg *msg, size_t payload_length)
1596 {
1597 	if (msg == NULL) {
1598 		return PLDM_ERROR_INVALID_DATA;
1599 	}
1600 
1601 	if (payload_length != sizeof(completion_code)) {
1602 		return PLDM_ERROR_INVALID_LENGTH;
1603 	}
1604 
1605 	struct pldm_header_info header = { 0 };
1606 	header.instance = instance_id;
1607 	header.msg_type = PLDM_RESPONSE;
1608 	header.pldm_type = PLDM_FWUP;
1609 	header.command = PLDM_TRANSFER_COMPLETE;
1610 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1611 	if (rc) {
1612 		return rc;
1613 	}
1614 
1615 	msg->payload[0] = completion_code;
1616 
1617 	return PLDM_SUCCESS;
1618 }
1619 
1620 LIBPLDM_ABI_STABLE
1621 int decode_verify_complete_req(const struct pldm_msg *msg,
1622 			       size_t payload_length, uint8_t *verify_result)
1623 {
1624 	if (msg == NULL || verify_result == NULL) {
1625 		return PLDM_ERROR_INVALID_DATA;
1626 	}
1627 
1628 	if (payload_length != sizeof(*verify_result)) {
1629 		return PLDM_ERROR_INVALID_LENGTH;
1630 	}
1631 
1632 	*verify_result = msg->payload[0];
1633 	return PLDM_SUCCESS;
1634 }
1635 
1636 LIBPLDM_ABI_STABLE
1637 int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
1638 				struct pldm_msg *msg, size_t payload_length)
1639 {
1640 	if (msg == NULL) {
1641 		return PLDM_ERROR_INVALID_DATA;
1642 	}
1643 
1644 	if (payload_length != sizeof(completion_code)) {
1645 		return PLDM_ERROR_INVALID_LENGTH;
1646 	}
1647 
1648 	struct pldm_header_info header = { 0 };
1649 	header.instance = instance_id;
1650 	header.msg_type = PLDM_RESPONSE;
1651 	header.pldm_type = PLDM_FWUP;
1652 	header.command = PLDM_VERIFY_COMPLETE;
1653 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1654 	if (rc) {
1655 		return rc;
1656 	}
1657 
1658 	msg->payload[0] = completion_code;
1659 
1660 	return PLDM_SUCCESS;
1661 }
1662 
1663 LIBPLDM_ABI_STABLE
1664 int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
1665 			      uint8_t *apply_result,
1666 			      bitfield16_t *comp_activation_methods_modification)
1667 {
1668 	if (msg == NULL || apply_result == NULL ||
1669 	    comp_activation_methods_modification == NULL) {
1670 		return PLDM_ERROR_INVALID_DATA;
1671 	}
1672 
1673 	if (payload_length != sizeof(struct pldm_apply_complete_req)) {
1674 		return PLDM_ERROR_INVALID_LENGTH;
1675 	}
1676 
1677 	struct pldm_apply_complete_req *request =
1678 		(struct pldm_apply_complete_req *)msg->payload;
1679 
1680 	*apply_result = request->apply_result;
1681 	comp_activation_methods_modification->value =
1682 		le16toh(request->comp_activation_methods_modification.value);
1683 
1684 	if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
1685 	    comp_activation_methods_modification->value) {
1686 		return PLDM_ERROR_INVALID_DATA;
1687 	}
1688 
1689 	return PLDM_SUCCESS;
1690 }
1691 
1692 LIBPLDM_ABI_STABLE
1693 int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
1694 			       struct pldm_msg *msg, size_t payload_length)
1695 {
1696 	if (msg == NULL) {
1697 		return PLDM_ERROR_INVALID_DATA;
1698 	}
1699 
1700 	if (payload_length != sizeof(completion_code)) {
1701 		return PLDM_ERROR_INVALID_LENGTH;
1702 	}
1703 
1704 	struct pldm_header_info header = { 0 };
1705 	header.instance = instance_id;
1706 	header.msg_type = PLDM_RESPONSE;
1707 	header.pldm_type = PLDM_FWUP;
1708 	header.command = PLDM_APPLY_COMPLETE;
1709 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1710 	if (rc) {
1711 		return rc;
1712 	}
1713 
1714 	msg->payload[0] = completion_code;
1715 
1716 	return PLDM_SUCCESS;
1717 }
1718 
1719 LIBPLDM_ABI_STABLE
1720 int encode_activate_firmware_req(uint8_t instance_id,
1721 				 bool8_t self_contained_activation_req,
1722 				 struct pldm_msg *msg, size_t payload_length)
1723 {
1724 	if (msg == NULL) {
1725 		return PLDM_ERROR_INVALID_DATA;
1726 	}
1727 
1728 	if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
1729 		return PLDM_ERROR_INVALID_LENGTH;
1730 	}
1731 
1732 	if (!is_self_contained_activation_req_valid(
1733 		    self_contained_activation_req)) {
1734 		return PLDM_ERROR_INVALID_DATA;
1735 	}
1736 
1737 	struct pldm_header_info header = { 0 };
1738 	header.instance = instance_id;
1739 	header.msg_type = PLDM_REQUEST;
1740 	header.pldm_type = PLDM_FWUP;
1741 	header.command = PLDM_ACTIVATE_FIRMWARE;
1742 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1743 	if (rc) {
1744 		return rc;
1745 	}
1746 
1747 	struct pldm_activate_firmware_req *request =
1748 		(struct pldm_activate_firmware_req *)msg->payload;
1749 
1750 	request->self_contained_activation_req = self_contained_activation_req;
1751 
1752 	return PLDM_SUCCESS;
1753 }
1754 
1755 LIBPLDM_ABI_STABLE
1756 int decode_activate_firmware_resp(const struct pldm_msg *msg,
1757 				  size_t payload_length,
1758 				  uint8_t *completion_code,
1759 				  uint16_t *estimated_time_activation)
1760 {
1761 	if (msg == NULL || completion_code == NULL ||
1762 	    estimated_time_activation == NULL || !payload_length) {
1763 		return PLDM_ERROR_INVALID_DATA;
1764 	}
1765 
1766 	*completion_code = msg->payload[0];
1767 	if (*completion_code != PLDM_SUCCESS) {
1768 		return PLDM_SUCCESS;
1769 	}
1770 
1771 	if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
1772 		return PLDM_ERROR_INVALID_LENGTH;
1773 	}
1774 
1775 	struct pldm_activate_firmware_resp *response =
1776 		(struct pldm_activate_firmware_resp *)msg->payload;
1777 
1778 	*estimated_time_activation =
1779 		le16toh(response->estimated_time_activation);
1780 
1781 	return PLDM_SUCCESS;
1782 }
1783 
1784 LIBPLDM_ABI_STABLE
1785 int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
1786 			  size_t payload_length)
1787 {
1788 	if (msg == NULL) {
1789 		return PLDM_ERROR_INVALID_DATA;
1790 	}
1791 
1792 	if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
1793 		return PLDM_ERROR_INVALID_LENGTH;
1794 	}
1795 
1796 	struct pldm_header_info header = { 0 };
1797 	header.instance = instance_id;
1798 	header.msg_type = PLDM_REQUEST;
1799 	header.pldm_type = PLDM_FWUP;
1800 	header.command = PLDM_GET_STATUS;
1801 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1802 	if (rc) {
1803 		return rc;
1804 	}
1805 
1806 	return PLDM_SUCCESS;
1807 }
1808 
1809 LIBPLDM_ABI_STABLE
1810 int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
1811 			   uint8_t *completion_code, uint8_t *current_state,
1812 			   uint8_t *previous_state, uint8_t *aux_state,
1813 			   uint8_t *aux_state_status, uint8_t *progress_percent,
1814 			   uint8_t *reason_code,
1815 			   bitfield32_t *update_option_flags_enabled)
1816 {
1817 	if (msg == NULL || completion_code == NULL || current_state == NULL ||
1818 	    previous_state == NULL || aux_state == NULL ||
1819 	    aux_state_status == NULL || progress_percent == NULL ||
1820 	    reason_code == NULL || update_option_flags_enabled == NULL ||
1821 	    !payload_length) {
1822 		return PLDM_ERROR_INVALID_DATA;
1823 	}
1824 
1825 	*completion_code = msg->payload[0];
1826 	if (*completion_code != PLDM_SUCCESS) {
1827 		return PLDM_SUCCESS;
1828 	}
1829 
1830 	if (payload_length != sizeof(struct pldm_get_status_resp)) {
1831 		return PLDM_ERROR_INVALID_LENGTH;
1832 	}
1833 	struct pldm_get_status_resp *response =
1834 		(struct pldm_get_status_resp *)msg->payload;
1835 
1836 	if (!is_state_valid(response->current_state)) {
1837 		return PLDM_ERROR_INVALID_DATA;
1838 	}
1839 	if (!is_state_valid(response->previous_state)) {
1840 		return PLDM_ERROR_INVALID_DATA;
1841 	}
1842 	if (!is_aux_state_valid(response->aux_state)) {
1843 		return PLDM_ERROR_INVALID_DATA;
1844 	}
1845 	if (!is_aux_state_status_valid(response->aux_state_status)) {
1846 		return PLDM_ERROR_INVALID_DATA;
1847 	}
1848 	if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
1849 		return PLDM_ERROR_INVALID_DATA;
1850 	}
1851 	if (!is_reason_code_valid(response->reason_code)) {
1852 		return PLDM_ERROR_INVALID_DATA;
1853 	}
1854 
1855 	if ((response->current_state == PLDM_FD_STATE_IDLE) ||
1856 	    (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
1857 	    (response->current_state == PLDM_FD_STATE_READY_XFER)) {
1858 		if (response->aux_state !=
1859 		    PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
1860 			return PLDM_ERROR_INVALID_DATA;
1861 		}
1862 	}
1863 
1864 	*current_state = response->current_state;
1865 	*previous_state = response->previous_state;
1866 	*aux_state = response->aux_state;
1867 	*aux_state_status = response->aux_state_status;
1868 	*progress_percent = response->progress_percent;
1869 	*reason_code = response->reason_code;
1870 	update_option_flags_enabled->value =
1871 		le32toh(response->update_option_flags_enabled.value);
1872 
1873 	return PLDM_SUCCESS;
1874 }
1875 
1876 LIBPLDM_ABI_STABLE
1877 int encode_cancel_update_component_req(uint8_t instance_id,
1878 				       struct pldm_msg *msg,
1879 				       size_t payload_length)
1880 {
1881 	if (msg == NULL) {
1882 		return PLDM_ERROR_INVALID_DATA;
1883 	}
1884 
1885 	if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
1886 		return PLDM_ERROR_INVALID_LENGTH;
1887 	}
1888 
1889 	struct pldm_header_info header = { 0 };
1890 	header.instance = instance_id;
1891 	header.msg_type = PLDM_REQUEST;
1892 	header.pldm_type = PLDM_FWUP;
1893 	header.command = PLDM_CANCEL_UPDATE_COMPONENT;
1894 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1895 	if (rc) {
1896 		return rc;
1897 	}
1898 
1899 	return PLDM_SUCCESS;
1900 }
1901 
1902 LIBPLDM_ABI_STABLE
1903 int decode_cancel_update_component_resp(const struct pldm_msg *msg,
1904 					size_t payload_length,
1905 					uint8_t *completion_code)
1906 {
1907 	if (msg == NULL || completion_code == NULL) {
1908 		return PLDM_ERROR_INVALID_DATA;
1909 	}
1910 
1911 	if (payload_length != sizeof(*completion_code)) {
1912 		return PLDM_ERROR_INVALID_LENGTH;
1913 	}
1914 
1915 	*completion_code = msg->payload[0];
1916 	return PLDM_SUCCESS;
1917 }
1918 
1919 LIBPLDM_ABI_STABLE
1920 int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
1921 			     size_t payload_length)
1922 {
1923 	if (msg == NULL) {
1924 		return PLDM_ERROR_INVALID_DATA;
1925 	}
1926 
1927 	if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
1928 		return PLDM_ERROR_INVALID_LENGTH;
1929 	}
1930 
1931 	struct pldm_header_info header = { 0 };
1932 	header.instance = instance_id;
1933 	header.msg_type = PLDM_REQUEST;
1934 	header.pldm_type = PLDM_FWUP;
1935 	header.command = PLDM_CANCEL_UPDATE;
1936 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
1937 	if (rc) {
1938 		return rc;
1939 	}
1940 
1941 	return PLDM_SUCCESS;
1942 }
1943 
1944 LIBPLDM_ABI_STABLE
1945 int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
1946 			      uint8_t *completion_code,
1947 			      bool8_t *non_functioning_component_indication,
1948 			      bitfield64_t *non_functioning_component_bitmap)
1949 {
1950 	if (msg == NULL || completion_code == NULL ||
1951 	    non_functioning_component_indication == NULL ||
1952 	    non_functioning_component_bitmap == NULL || !payload_length) {
1953 		return PLDM_ERROR_INVALID_DATA;
1954 	}
1955 
1956 	*completion_code = msg->payload[0];
1957 	if (*completion_code != PLDM_SUCCESS) {
1958 		return PLDM_SUCCESS;
1959 	}
1960 
1961 	if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
1962 		return PLDM_ERROR_INVALID_LENGTH;
1963 	}
1964 	struct pldm_cancel_update_resp *response =
1965 		(struct pldm_cancel_update_resp *)msg->payload;
1966 
1967 	if (!is_non_functioning_component_indication_valid(
1968 		    response->non_functioning_component_indication)) {
1969 		return PLDM_ERROR_INVALID_DATA;
1970 	}
1971 
1972 	*non_functioning_component_indication =
1973 		response->non_functioning_component_indication;
1974 
1975 	if (*non_functioning_component_indication) {
1976 		non_functioning_component_bitmap->value =
1977 			le64toh(response->non_functioning_component_bitmap);
1978 	}
1979 
1980 	return PLDM_SUCCESS;
1981 }
1982