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