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