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