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