xref: /openbmc/libpldm/src/dsp/firmware_update.c (revision 7a8d932bc3cd30a0869b2e5cfd38c1b87019cffb)
1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 #include "api.h"
3 #include "array.h"
4 #include "utils.h"
5 #include "compiler.h"
6 #include "dsp/base.h"
7 #include "msgbuf.h"
8 #include <libpldm/base.h>
9 #include <libpldm/compiler.h>
10 #include <libpldm/firmware_update.h>
11 #include <libpldm/utils.h>
12 
13 #include <endian.h>
14 #include <stdbool.h>
15 #include <string.h>
16 
17 static_assert(PLDM_FIRMWARE_MAX_STRING <= UINT8_MAX, "too large");
18 
19 /** @brief Check whether string type value is valid
20  *
21  *  @return true if string type value is valid, false if not
22  */
is_string_type_valid(uint8_t string_type)23 static bool is_string_type_valid(uint8_t string_type)
24 {
25 	switch (string_type) {
26 	case PLDM_STR_TYPE_UNKNOWN:
27 		return false;
28 	case PLDM_STR_TYPE_ASCII:
29 	case PLDM_STR_TYPE_UTF_8:
30 	case PLDM_STR_TYPE_UTF_16:
31 	case PLDM_STR_TYPE_UTF_16LE:
32 	case PLDM_STR_TYPE_UTF_16BE:
33 		return true;
34 	default:
35 		return false;
36 	}
37 }
38 
39 /** @brief Return the length of the descriptor type described in firmware update
40  *         specification
41  *
42  *  @return length of the descriptor type if descriptor type is valid else
43  *          return 0
44  */
get_descriptor_type_length(uint16_t descriptor_type)45 static uint16_t get_descriptor_type_length(uint16_t descriptor_type)
46 {
47 	switch (descriptor_type) {
48 	case PLDM_FWUP_PCI_VENDOR_ID:
49 		return PLDM_FWUP_PCI_VENDOR_ID_LENGTH;
50 	case PLDM_FWUP_IANA_ENTERPRISE_ID:
51 		return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH;
52 	case PLDM_FWUP_UUID:
53 		return PLDM_FWUP_UUID_LENGTH;
54 	case PLDM_FWUP_PNP_VENDOR_ID:
55 		return PLDM_FWUP_PNP_VENDOR_ID_LENGTH;
56 	case PLDM_FWUP_ACPI_VENDOR_ID:
57 		return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH;
58 	case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID:
59 		return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH;
60 	case PLDM_FWUP_SCSI_VENDOR_ID:
61 		return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH;
62 	case PLDM_FWUP_PCI_DEVICE_ID:
63 		return PLDM_FWUP_PCI_DEVICE_ID_LENGTH;
64 	case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID:
65 		return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH;
66 	case PLDM_FWUP_PCI_SUBSYSTEM_ID:
67 		return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH;
68 	case PLDM_FWUP_PCI_REVISION_ID:
69 		return PLDM_FWUP_PCI_REVISION_ID_LENGTH;
70 	case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER:
71 		return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH;
72 	case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER:
73 		return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH;
74 	case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING:
75 		return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH;
76 	case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING:
77 		return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH;
78 	case PLDM_FWUP_SCSI_PRODUCT_ID:
79 		return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH;
80 	case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE:
81 		return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH;
82 	default:
83 		return 0;
84 	}
85 }
86 
is_downstream_device_update_support_valid(uint8_t resp)87 static bool is_downstream_device_update_support_valid(uint8_t resp)
88 {
89 	switch (resp) {
90 	case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED:
91 	case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED:
92 		return true;
93 	default:
94 		return false;
95 	}
96 }
97 
98 static bool
is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag)99 is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag)
100 {
101 	switch (transfer_op_flag) {
102 	case PLDM_GET_NEXTPART:
103 	case PLDM_GET_FIRSTPART:
104 		return true;
105 	default:
106 		return false;
107 	}
108 }
109 
110 /** @brief Check whether ComponentResponse is valid
111  *
112  *  @return true if ComponentResponse is valid, false if not
113  */
is_comp_resp_valid(uint8_t comp_resp)114 static bool is_comp_resp_valid(uint8_t comp_resp)
115 {
116 	switch (comp_resp) {
117 	case PLDM_CR_COMP_CAN_BE_UPDATED:
118 	case PLDM_CR_COMP_MAY_BE_UPDATEABLE:
119 		return true;
120 
121 	default:
122 		return false;
123 	}
124 }
125 
126 /** @brief Check whether ComponentResponseCode is valid
127  *
128  *  @return true if ComponentResponseCode is valid, false if not
129  */
is_comp_resp_code_valid(uint8_t comp_resp_code)130 static bool is_comp_resp_code_valid(uint8_t comp_resp_code)
131 {
132 	switch (comp_resp_code) {
133 	case PLDM_CRC_COMP_CAN_BE_UPDATED:
134 	case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL:
135 	case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER:
136 	case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP:
137 	case PLDM_CRC_COMP_CONFLICT:
138 	case PLDM_CRC_COMP_PREREQUISITES_NOT_MET:
139 	case PLDM_CRC_COMP_NOT_SUPPORTED:
140 	case PLDM_CRC_COMP_SECURITY_RESTRICTIONS:
141 	case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
142 	case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY:
143 	case PLDM_CRC_COMP_VER_STR_IDENTICAL:
144 	case PLDM_CRC_COMP_VER_STR_LOWER:
145 		return true;
146 
147 	default:
148 		if (comp_resp_code >=
149 			    PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
150 		    comp_resp_code <=
151 			    PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
152 			return true;
153 		}
154 		return false;
155 	}
156 }
157 
158 /** @brief Check whether ComponentCompatibilityResponse is valid
159  *
160  *  @return true if ComponentCompatibilityResponse is valid, false if not
161  */
is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)162 static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp)
163 {
164 	switch (comp_compatibility_resp) {
165 	case PLDM_CCR_COMP_CAN_BE_UPDATED:
166 	case PLDM_CCR_COMP_CANNOT_BE_UPDATED:
167 		return true;
168 
169 	default:
170 		return false;
171 	}
172 }
173 
174 /** @brief Check whether ComponentCompatibilityResponse Code is valid
175  *
176  *  @return true if ComponentCompatibilityResponse Code is valid, false if not
177  */
178 static bool
is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)179 is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code)
180 {
181 	switch (comp_compatibility_resp_code) {
182 	case PLDM_CCRC_NO_RESPONSE_CODE:
183 	case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL:
184 	case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER:
185 	case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP:
186 	case PLDM_CCRC_COMP_CONFLICT:
187 	case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET:
188 	case PLDM_CCRC_COMP_NOT_SUPPORTED:
189 	case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS:
190 	case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET:
191 	case PLDM_CCRC_COMP_INFO_NO_MATCH:
192 	case PLDM_CCRC_COMP_VER_STR_IDENTICAL:
193 	case PLDM_CCRC_COMP_VER_STR_LOWER:
194 		return true;
195 
196 	default:
197 		if (comp_compatibility_resp_code >=
198 			    PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN &&
199 		    comp_compatibility_resp_code <=
200 			    PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) {
201 			return true;
202 		}
203 		return false;
204 	}
205 }
206 
207 /** @brief Check whether SelfContainedActivationRequest is valid
208  *
209  *  @return true if SelfContainedActivationRequest is valid, false if not
210  */
211 static bool
is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)212 is_self_contained_activation_req_valid(bool8_t self_contained_activation_req)
213 {
214 	switch (self_contained_activation_req) {
215 	case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS:
216 	case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS:
217 		return true;
218 
219 	default:
220 		return false;
221 	}
222 }
223 
224 /** @brief Check if current or previous status in GetStatus command response is
225  *         valid
226  *
227  *	@param[in] state - current or previous different state machine state of
228  *                     the FD
229  *	@return true if state is valid, false if not
230  */
is_state_valid(uint8_t state)231 static bool is_state_valid(uint8_t state)
232 {
233 	switch (state) {
234 	case PLDM_FD_STATE_IDLE:
235 	case PLDM_FD_STATE_LEARN_COMPONENTS:
236 	case PLDM_FD_STATE_READY_XFER:
237 	case PLDM_FD_STATE_DOWNLOAD:
238 	case PLDM_FD_STATE_VERIFY:
239 	case PLDM_FD_STATE_APPLY:
240 	case PLDM_FD_STATE_ACTIVATE:
241 		return true;
242 
243 	default:
244 		return false;
245 	}
246 }
247 
248 /** @brief Check if aux state in GetStatus command response is valid
249  *
250  *  @param[in] aux_state - provides additional information to the UA to describe
251  *                         the current operation state of the FD/FDP
252  *
253  *	@return true if aux state is valid, false if not
254  */
is_aux_state_valid(uint8_t aux_state)255 static bool is_aux_state_valid(uint8_t aux_state)
256 {
257 	switch (aux_state) {
258 	case PLDM_FD_OPERATION_IN_PROGRESS:
259 	case PLDM_FD_OPERATION_SUCCESSFUL:
260 	case PLDM_FD_OPERATION_FAILED:
261 	case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER:
262 		return true;
263 
264 	default:
265 		return false;
266 	}
267 }
268 
269 /** @brief Check if aux state status in GetStatus command response is valid
270  *
271  *	@param[in] aux_state_status - aux state status
272  *
273  *	@return true if aux state status is valid, false if not
274  */
is_aux_state_status_valid(uint8_t aux_state_status)275 static bool is_aux_state_status_valid(uint8_t aux_state_status)
276 {
277 	if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS ||
278 	    aux_state_status == PLDM_FD_TIMEOUT ||
279 	    aux_state_status == PLDM_FD_GENERIC_ERROR ||
280 	    (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
281 	     aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) {
282 		return true;
283 	}
284 
285 	return false;
286 }
287 
288 /** @brief Check if reason code in GetStatus command response is valid
289  *
290  *	@param[in] reason_code - provides the reason for why the current state
291  *                           entered the IDLE state
292  *
293  *	@return true if reason code is valid, false if not
294  */
is_reason_code_valid(uint8_t reason_code)295 static bool is_reason_code_valid(uint8_t reason_code)
296 {
297 	switch (reason_code) {
298 	case PLDM_FD_INITIALIZATION:
299 	case PLDM_FD_ACTIVATE_FW:
300 	case PLDM_FD_CANCEL_UPDATE:
301 	case PLDM_FD_TIMEOUT_LEARN_COMPONENT:
302 	case PLDM_FD_TIMEOUT_READY_XFER:
303 	case PLDM_FD_TIMEOUT_DOWNLOAD:
304 	case PLDM_FD_TIMEOUT_VERIFY:
305 	case PLDM_FD_TIMEOUT_APPLY:
306 		return true;
307 
308 	default:
309 		if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) {
310 			return true;
311 		}
312 		return false;
313 	}
314 }
315 
316 /** @brief Check if non functioning component indication in CancelUpdate
317  *         response is valid
318  *
319  *  @return true if non functioning component indication is valid, false if not
320  */
is_non_functioning_component_indication_valid(bool8_t non_functioning_component_indication)321 static bool is_non_functioning_component_indication_valid(
322 	bool8_t non_functioning_component_indication)
323 {
324 	switch (non_functioning_component_indication) {
325 	case PLDM_FWUP_COMPONENTS_FUNCTIONING:
326 	case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING:
327 		return true;
328 
329 	default:
330 		return false;
331 	}
332 }
333 
334 #define PLDM_FWUP_PACKAGE_HEADER_FIXED_SIZE 36
335 LIBPLDM_CC_NONNULL
336 static int
decode_pldm_package_header_info_errno(const void * data,size_t length,const struct pldm_package_format_pin * pin,pldm_package_header_information_pad * hdr,struct pldm_package * pkg)337 decode_pldm_package_header_info_errno(const void *data, size_t length,
338 				      const struct pldm_package_format_pin *pin,
339 				      pldm_package_header_information_pad *hdr,
340 				      struct pldm_package *pkg)
341 {
342 	static const struct pldm_package_header_format_revision_info {
343 		pldm_uuid identifier;
344 		size_t magic;
345 	} revision_info[1 + PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H] = {
346 		[0] = {
347 			.identifier = {0},
348 			.magic = 0,
349 		},
350 		[PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H] = {
351 			.identifier = PLDM_PACKAGE_HEADER_IDENTIFIER_V1_0,
352 			.magic =
353 				LIBPLDM_SIZEAT(struct pldm_package, iter) +
354 				LIBPLDM_SIZEAT(struct pldm__package_header_information, package_version_string) +
355 				LIBPLDM_SIZEAT(struct pldm_package_firmware_device_id_record, firmware_device_package_data) +
356 				LIBPLDM_SIZEAT(struct pldm_descriptor, descriptor_data) +
357 				LIBPLDM_SIZEAT(struct pldm_package_component_image_information, component_version_string)
358 		},
359 		[PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR02H] = {
360 			.identifier = PLDM_PACKAGE_HEADER_IDENTIFIER_V1_1,
361 			.magic =
362 				LIBPLDM_SIZEAT(struct pldm_package, iter) +
363 				LIBPLDM_SIZEAT(struct pldm__package_header_information, package_version_string) +
364 				LIBPLDM_SIZEAT(struct pldm_package_firmware_device_id_record, firmware_device_package_data) +
365 				LIBPLDM_SIZEAT(struct pldm_descriptor, descriptor_data) +
366 				LIBPLDM_SIZEAT(struct pldm_package_downstream_device_id_record, package_data) +
367 				LIBPLDM_SIZEAT(struct pldm_package_component_image_information, component_version_string)
368 		},
369 		[PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR03H] = {
370 			.identifier = PLDM_PACKAGE_HEADER_IDENTIFIER_V1_2,
371 			.magic =
372 				LIBPLDM_SIZEAT(struct pldm_package, iter) +
373 				LIBPLDM_SIZEAT(struct pldm__package_header_information, package_version_string) +
374 				LIBPLDM_SIZEAT(struct pldm_package_firmware_device_id_record, firmware_device_package_data) +
375 				LIBPLDM_SIZEAT(struct pldm_descriptor, descriptor_data) +
376 				LIBPLDM_SIZEAT(struct pldm_package_downstream_device_id_record, package_data) +
377 				LIBPLDM_SIZEAT(struct pldm_package_component_image_information, component_opaque_data)
378 		},
379 		[PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H] = {
380 			.identifier = PLDM_PACKAGE_HEADER_IDENTIFIER_V1_3,
381 			.magic =
382 				LIBPLDM_SIZEAT(struct pldm_package, iter) +
383 				LIBPLDM_SIZEAT(struct pldm__package_header_information, package_version_string) +
384 				LIBPLDM_SIZEAT(struct pldm_package_firmware_device_id_record, reference_manifest_data) +
385 				LIBPLDM_SIZEAT(struct pldm_descriptor, descriptor_data) +
386 				LIBPLDM_SIZEAT(struct pldm_package_downstream_device_id_record, reference_manifest_data) +
387 				LIBPLDM_SIZEAT(struct pldm_package_component_image_information, component_opaque_data)
388 		},
389 	};
390 
391 	const struct pldm_package_header_format_revision_info *info;
392 	uint32_t package_payload_checksum = 0;
393 	uint32_t package_header_checksum = 0;
394 	size_t package_header_variable_size;
395 	size_t package_header_payload_size;
396 	const void *package_payload_offset;
397 	size_t package_header_areas_size;
398 	uint16_t package_header_size;
399 	size_t package_payload_size;
400 	PLDM_MSGBUF_RO_DEFINE_P(buf);
401 	int checksums = 1;
402 	int rc;
403 
404 	if (pkg->state != PLDM_PACKAGE_PARSE_INIT) {
405 		return -EINVAL;
406 	}
407 
408 	if (pin->meta.version > 0u) {
409 		return -ENOTSUP;
410 	}
411 
412 	if (pin->format.revision == 0u) {
413 		return -EINVAL;
414 	}
415 
416 	if (pin->format.revision > PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H) {
417 		return -ENOTSUP;
418 	}
419 	static_assert(ARRAY_SIZE(revision_info) ==
420 			      1 + PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H,
421 		      "Mismatched array bounds test");
422 
423 	info = &revision_info[(size_t)pin->format.revision];
424 	if (memcmp(&pin->format.identifier, info->identifier,
425 		   sizeof(info->identifier)) != 0) {
426 		return -ENOTSUP;
427 	}
428 
429 	if (pin->meta.magic != info->magic) {
430 		return -EINVAL;
431 	}
432 
433 	rc = pldm_msgbuf_init_errno(buf, PLDM_FWUP_PACKAGE_HEADER_FIXED_SIZE,
434 				    data, length);
435 	if (rc) {
436 		return rc;
437 	}
438 
439 	rc = pldm_msgbuf_extract_array(buf,
440 				       sizeof(hdr->package_header_identifier),
441 				       hdr->package_header_identifier,
442 				       sizeof(hdr->package_header_identifier));
443 	if (rc) {
444 		return pldm_msgbuf_discard(buf, rc);
445 	}
446 
447 	if (memcmp(revision_info[PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H]
448 			   .identifier,
449 		   hdr->package_header_identifier,
450 		   sizeof(hdr->package_header_identifier)) != 0 &&
451 	    memcmp(revision_info[PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR02H]
452 			   .identifier,
453 		   hdr->package_header_identifier,
454 		   sizeof(hdr->package_header_identifier)) != 0 &&
455 	    memcmp(revision_info[PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR03H]
456 			   .identifier,
457 		   hdr->package_header_identifier,
458 		   sizeof(hdr->package_header_identifier)) != 0 &&
459 	    memcmp(revision_info[PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H]
460 			   .identifier,
461 		   hdr->package_header_identifier,
462 		   sizeof(hdr->package_header_identifier)) != 0) {
463 		return pldm_msgbuf_discard(buf, -ENOTSUP);
464 	}
465 
466 	rc = pldm_msgbuf_extract(buf, hdr->package_header_format_revision);
467 	if (rc) {
468 		return pldm_msgbuf_discard(buf, rc);
469 	}
470 	if (hdr->package_header_format_revision > pin->format.revision) {
471 		return pldm_msgbuf_discard(buf, -ENOTSUP);
472 	}
473 
474 	if (hdr->package_header_format_revision >=
475 	    PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H) {
476 		checksums = 2;
477 	}
478 
479 	rc = pldm_msgbuf_extract(buf, package_header_size);
480 	if (rc) {
481 		return pldm_msgbuf_discard(buf, rc);
482 	}
483 
484 	rc = pldm_msgbuf_extract_array(buf,
485 				       sizeof(hdr->package_release_date_time),
486 				       hdr->package_release_date_time,
487 				       sizeof(hdr->package_release_date_time));
488 	if (rc) {
489 		return pldm_msgbuf_discard(buf, rc);
490 	}
491 
492 	rc = pldm_msgbuf_extract(buf, hdr->component_bitmap_bit_length);
493 	if (rc) {
494 		return pldm_msgbuf_discard(buf, rc);
495 	}
496 	if (hdr->component_bitmap_bit_length & 7) {
497 		return pldm_msgbuf_discard(buf, -EPROTO);
498 	}
499 
500 	rc = pldm_msgbuf_extract(buf, hdr->package_version_string_type);
501 	if (rc) {
502 		return pldm_msgbuf_discard(buf, rc);
503 	}
504 	if (!is_string_type_valid(hdr->package_version_string_type)) {
505 		return pldm_msgbuf_discard(buf, -EPROTO);
506 	}
507 
508 	rc = pldm_msgbuf_extract_uint8_to_size(
509 		buf, hdr->package_version_string.length);
510 	if (rc) {
511 		return pldm_msgbuf_discard(buf, rc);
512 	}
513 
514 	pldm_msgbuf_span_required(
515 		buf, hdr->package_version_string.length,
516 		(const void **)&hdr->package_version_string.ptr);
517 
518 	if (package_header_size < (PLDM_FWUP_PACKAGE_HEADER_FIXED_SIZE + 3 +
519 				   checksums * sizeof(uint32_t))) {
520 		return pldm_msgbuf_discard(buf, -EOVERFLOW);
521 	}
522 	package_header_payload_size =
523 		package_header_size - (checksums * sizeof(uint32_t));
524 	package_header_variable_size = package_header_payload_size -
525 				       PLDM_FWUP_PACKAGE_HEADER_FIXED_SIZE;
526 
527 	if (package_header_variable_size < hdr->package_version_string.length) {
528 		return pldm_msgbuf_discard(buf, -EOVERFLOW);
529 	}
530 
531 	package_header_areas_size = package_header_variable_size -
532 				    hdr->package_version_string.length;
533 	rc = pldm_msgbuf_span_required(buf, package_header_areas_size,
534 				       (const void **)&pkg->areas.ptr);
535 	if (rc) {
536 		return pldm_msgbuf_discard(buf, rc);
537 	}
538 	pkg->areas.length = package_header_areas_size;
539 
540 	pldm_msgbuf_extract(buf, package_header_checksum);
541 
542 	if (hdr->package_header_format_revision >=
543 	    PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H) {
544 		pldm_msgbuf_extract(buf, package_payload_checksum);
545 		rc = pldm_msgbuf_span_remaining(buf, &package_payload_offset,
546 						&package_payload_size);
547 		if (rc) {
548 			return pldm_msgbuf_discard(buf, rc);
549 		}
550 	} else {
551 		package_payload_offset = NULL;
552 		package_payload_size = 0;
553 	}
554 
555 	rc = pldm_msgbuf_complete(buf);
556 	if (rc) {
557 		return rc;
558 	}
559 
560 	rc = pldm_edac_crc32_validate(package_header_checksum, data,
561 				      package_header_payload_size);
562 	if (rc) {
563 #if 0
564 		printf("header checksum failure, expected: %#08" PRIx32 ", found: %#08" PRIx32 "\n", package_header_checksum, pldm_edac_crc32(data, package_header_payload_size));
565 #endif
566 		return rc;
567 	}
568 
569 	if (hdr->package_header_format_revision >=
570 	    PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H) {
571 		rc = pldm_edac_crc32_validate(package_payload_checksum,
572 					      package_payload_offset,
573 					      package_payload_size);
574 		if (rc) {
575 #if 0
576 			printf("payload checksum failure, expected: %#08" PRIx32 ", found: %#08" PRIx32 "\n", package_payload_checksum, pldm_edac_crc32(package_payload_offset, package_payload_size));
577 #endif
578 			return rc;
579 		}
580 	}
581 
582 	/* We stash these to resolve component images later */
583 	pkg->pin = pin;
584 	pkg->hdr = hdr;
585 	pkg->state = PLDM_PACKAGE_PARSE_HEADER;
586 	pkg->flags = 0;
587 	pkg->package.ptr = data;
588 	pkg->package.length = length;
589 
590 	return 0;
591 }
592 
593 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)594 int decode_pldm_package_header_info(
595 	const uint8_t *data, size_t length,
596 	struct pldm_package_header_information *package_header_info,
597 	struct variable_field *package_version_str)
598 {
599 	DEFINE_PLDM_PACKAGE_FORMAT_PIN_FR01H(pin);
600 	pldm_package_header_information_pad hdr;
601 	struct pldm_package pkg = { 0 };
602 	int rc;
603 
604 	if (!data || !package_header_info || !package_version_str) {
605 		return PLDM_ERROR_INVALID_DATA;
606 	}
607 
608 	rc = decode_pldm_package_header_info_errno(data, length, &pin, &hdr,
609 						   &pkg);
610 	if (rc < 0) {
611 		return pldm_xlate_errno(rc);
612 	}
613 
614 	static_assert(sizeof(package_header_info->uuid) ==
615 			      sizeof(hdr.package_header_identifier),
616 		      "UUID field size");
617 	memcpy(package_header_info->uuid, hdr.package_header_identifier,
618 	       sizeof(hdr.package_header_identifier));
619 	package_header_info->package_header_format_version =
620 		hdr.package_header_format_revision;
621 	memcpy(&package_header_info->package_header_size, data + 17,
622 	       sizeof(package_header_info->package_header_size));
623 	LE16TOH(package_header_info->package_header_size);
624 	static_assert(sizeof(package_header_info->package_release_date_time) ==
625 			      sizeof(hdr.package_release_date_time),
626 		      "TIMESTAMP104 field size");
627 	memcpy(package_header_info->package_release_date_time,
628 	       hdr.package_release_date_time,
629 	       sizeof(hdr.package_release_date_time));
630 	package_header_info->component_bitmap_bit_length =
631 		hdr.component_bitmap_bit_length;
632 	package_header_info->package_version_string_type =
633 		hdr.package_version_string_type;
634 	package_header_info->package_version_string_length =
635 		hdr.package_version_string.length;
636 	*package_version_str = hdr.package_version_string;
637 
638 	return PLDM_SUCCESS;
639 }
640 
641 /* Currently only used for decode_firmware_device_id_record_errno() */
pldm_msgbuf_init_dynamic_uint16(struct pldm_msgbuf_ro * buf,size_t req,void * data,size_t len,void ** tail_data,size_t * tail_len)642 static int pldm_msgbuf_init_dynamic_uint16(struct pldm_msgbuf_ro *buf,
643 					   size_t req, void *data, size_t len,
644 					   void **tail_data, size_t *tail_len)
645 {
646 	const void *dyn_start;
647 	size_t dyn_length;
648 	int rc;
649 
650 	rc = pldm_msgbuf_init_errno(buf, req, data, len);
651 	if (rc) {
652 		return rc;
653 	}
654 	/*
655 	 * Extract the record length from the first field, then reinitialise the msgbuf
656 	 * after determining that it's safe to do so
657 	 */
658 
659 	rc = pldm_msgbuf_extract_uint16_to_size(buf, dyn_length);
660 	if (rc) {
661 		return pldm_msgbuf_discard(buf, rc);
662 	}
663 
664 	rc = pldm_msgbuf_complete(buf);
665 	if (rc) {
666 		return rc;
667 	}
668 
669 	rc = pldm_msgbuf_init_errno(buf, req, data, len);
670 	if (rc) {
671 		return rc;
672 	}
673 
674 	/* Ensure there's no arithmetic funkiness and the span is within buffer bounds */
675 	rc = pldm_msgbuf_span_required(buf, dyn_length, &dyn_start);
676 	if (rc) {
677 		return pldm_msgbuf_discard(buf, rc);
678 	}
679 
680 	rc = pldm_msgbuf_span_remaining(buf, (const void **)tail_data,
681 					tail_len);
682 	if (rc) {
683 		return pldm_msgbuf_discard(buf, rc);
684 	}
685 
686 	rc = pldm_msgbuf_complete(buf);
687 	if (rc) {
688 		return rc;
689 	}
690 
691 	return pldm_msgbuf_init_errno(buf, req, dyn_start, dyn_length);
692 }
693 
694 #define PLDM_FWUP_FIRMWARE_DEVICE_ID_RECORD_MIN_SIZE 11
decode_pldm_package_firmware_device_id_record_errno(const pldm_package_header_information_pad * hdr,struct variable_field * field,struct pldm_package_firmware_device_id_record * rec)695 static int decode_pldm_package_firmware_device_id_record_errno(
696 	const pldm_package_header_information_pad *hdr,
697 	struct variable_field *field,
698 	struct pldm_package_firmware_device_id_record *rec)
699 {
700 	size_t firmware_device_package_data_offset;
701 	PLDM_MSGBUF_RO_DEFINE_P(buf);
702 	uint16_t record_len = 0;
703 	int rc;
704 
705 	if (!hdr || !field || !rec || !field->ptr) {
706 		return -EINVAL;
707 	}
708 
709 	rc = pldm_msgbuf_init_dynamic_uint16(
710 		buf, PLDM_FWUP_FIRMWARE_DEVICE_ID_RECORD_MIN_SIZE,
711 		(void *)field->ptr, field->length, (void **)&field->ptr,
712 		&field->length);
713 	if (rc) {
714 		return rc;
715 	}
716 
717 	pldm_msgbuf_extract(buf, record_len);
718 	pldm_msgbuf_extract(buf, rec->descriptor_count);
719 	pldm_msgbuf_extract(buf, rec->device_update_option_flags.value);
720 
721 	rc = pldm_msgbuf_extract(buf,
722 				 rec->component_image_set_version_string_type);
723 	if (rc) {
724 		return pldm_msgbuf_discard(buf, rc);
725 	}
726 	if (!is_string_type_valid(
727 		    rec->component_image_set_version_string_type)) {
728 		return pldm_msgbuf_discard(buf, -EPROTO);
729 	}
730 
731 	rc = pldm_msgbuf_extract_uint8_to_size(
732 		buf, rec->component_image_set_version_string.length);
733 	if (rc) {
734 		return pldm_msgbuf_discard(buf, rc);
735 	}
736 
737 	if (rec->component_image_set_version_string.length == 0) {
738 		return pldm_msgbuf_discard(buf, -EPROTO);
739 	}
740 
741 	rc = pldm_msgbuf_extract_uint16_to_size(
742 		buf, rec->firmware_device_package_data.length);
743 	if (rc) {
744 		return pldm_msgbuf_discard(buf, rc);
745 	}
746 
747 	if (hdr->package_header_format_revision >=
748 	    PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H) {
749 		rc = pldm_msgbuf_extract_uint32_to_size(
750 			buf, rec->reference_manifest_data.length);
751 		if (rc) {
752 			return pldm_msgbuf_discard(buf, rc);
753 		}
754 	} else {
755 		rec->reference_manifest_data.length = 0;
756 	}
757 
758 	assert((hdr->component_bitmap_bit_length & 7) == 0);
759 	rc = pldm_msgbuf_span_required(
760 		buf, hdr->component_bitmap_bit_length / 8,
761 		(const void **)&rec->applicable_components.bitmap.ptr);
762 	if (rc) {
763 		return pldm_msgbuf_discard(buf, rc);
764 	}
765 	rec->applicable_components.bitmap.length =
766 		hdr->component_bitmap_bit_length / 8;
767 
768 	pldm_msgbuf_span_required(
769 		buf, rec->component_image_set_version_string.length,
770 		(const void **)&rec->component_image_set_version_string.ptr);
771 
772 	/* The total length reserved for `package_data` and `reference_manifest_data` */
773 	firmware_device_package_data_offset =
774 		rec->firmware_device_package_data.length +
775 		rec->reference_manifest_data.length;
776 
777 	pldm_msgbuf_span_until(buf, firmware_device_package_data_offset,
778 			       (const void **)&rec->record_descriptors.ptr,
779 			       &rec->record_descriptors.length);
780 
781 	pldm_msgbuf_span_required(
782 		buf, rec->firmware_device_package_data.length,
783 		(const void **)&rec->firmware_device_package_data.ptr);
784 	if (!rec->firmware_device_package_data.length) {
785 		rec->firmware_device_package_data.ptr = NULL;
786 	}
787 
788 	if (hdr->package_header_format_revision >=
789 	    PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H) {
790 		pldm_msgbuf_span_required(
791 			buf, rec->reference_manifest_data.length,
792 			(const void **)&rec->reference_manifest_data.ptr);
793 
794 	} else {
795 		assert(rec->reference_manifest_data.length == 0);
796 		rec->reference_manifest_data.ptr = NULL;
797 	}
798 
799 	return pldm_msgbuf_complete_consumed(buf);
800 }
801 
802 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)803 int decode_firmware_device_id_record(
804 	const uint8_t *data, size_t length,
805 	uint16_t component_bitmap_bit_length,
806 	struct pldm_firmware_device_id_record *fw_device_id_record,
807 	struct variable_field *applicable_components,
808 	struct variable_field *comp_image_set_version_str,
809 	struct variable_field *record_descriptors,
810 	struct variable_field *fw_device_pkg_data)
811 {
812 	struct pldm_package_firmware_device_id_record rec;
813 	pldm_package_header_information_pad hdr;
814 	int rc;
815 
816 	if (!data || !fw_device_id_record || !applicable_components ||
817 	    !comp_image_set_version_str || !record_descriptors ||
818 	    !fw_device_pkg_data) {
819 		return PLDM_ERROR_INVALID_DATA;
820 	}
821 
822 	hdr.package_header_format_revision =
823 		PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H;
824 	hdr.component_bitmap_bit_length = component_bitmap_bit_length;
825 
826 	rc = decode_pldm_package_firmware_device_id_record_errno(
827 		&hdr, &(struct variable_field){ data, length }, &rec);
828 	if (rc < 0) {
829 		return pldm_xlate_errno(rc);
830 	}
831 
832 	memcpy(&fw_device_id_record->record_length, data,
833 	       sizeof(fw_device_id_record->record_length));
834 	LE16TOH(fw_device_id_record->record_length);
835 	fw_device_id_record->descriptor_count = rec.descriptor_count;
836 	fw_device_id_record->device_update_option_flags =
837 		rec.device_update_option_flags;
838 	fw_device_id_record->comp_image_set_version_string_type =
839 		rec.component_image_set_version_string_type;
840 	fw_device_id_record->comp_image_set_version_string_length =
841 		rec.component_image_set_version_string.length;
842 	fw_device_id_record->fw_device_pkg_data_length =
843 		rec.firmware_device_package_data.length;
844 	*applicable_components = rec.applicable_components.bitmap;
845 	*comp_image_set_version_str = rec.component_image_set_version_string;
846 	*record_descriptors = rec.record_descriptors;
847 	*fw_device_pkg_data = rec.firmware_device_package_data;
848 
849 	return PLDM_SUCCESS;
850 }
851 
852 LIBPLDM_ABI_STABLE
decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter * iter,struct pldm_descriptor * desc)853 int decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter *iter,
854 				     struct pldm_descriptor *desc)
855 {
856 	PLDM_MSGBUF_RO_DEFINE_P(buf);
857 	int rc;
858 
859 	if (!iter || !iter->field || !desc) {
860 		return -EINVAL;
861 	}
862 
863 	rc = pldm_msgbuf_init_errno(buf, PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN,
864 				    iter->field->ptr, iter->field->length);
865 	if (rc) {
866 		return rc;
867 	}
868 
869 	pldm_msgbuf_extract(buf, desc->descriptor_type);
870 	rc = pldm_msgbuf_extract(buf, desc->descriptor_length);
871 	if (rc) {
872 		return pldm_msgbuf_discard(buf, rc);
873 	}
874 
875 	desc->descriptor_data = NULL;
876 	pldm_msgbuf_span_required(buf, desc->descriptor_length,
877 				  (const void **)&desc->descriptor_data);
878 	iter->field->ptr = NULL;
879 	pldm_msgbuf_span_remaining(buf, (const void **)&iter->field->ptr,
880 				   &iter->field->length);
881 
882 	return pldm_msgbuf_complete(buf);
883 }
884 
decode_descriptor_type_length_value_errno(const void * data,size_t length,uint16_t * descriptor_type,struct variable_field * descriptor_data)885 static int decode_descriptor_type_length_value_errno(
886 	const void *data, size_t length, uint16_t *descriptor_type,
887 	struct variable_field *descriptor_data)
888 {
889 	uint16_t descriptor_length = 0;
890 
891 	if (data == NULL || descriptor_type == NULL ||
892 	    descriptor_data == NULL) {
893 		return -EINVAL;
894 	}
895 
896 	if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
897 		return -EOVERFLOW;
898 	}
899 
900 	struct pldm_descriptor_tlv *entry =
901 		(struct pldm_descriptor_tlv *)(data);
902 
903 	*descriptor_type = le16toh(entry->descriptor_type);
904 	descriptor_length = le16toh(entry->descriptor_length);
905 	if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) {
906 		if (descriptor_length !=
907 		    get_descriptor_type_length(*descriptor_type)) {
908 			return -EBADMSG;
909 		}
910 	}
911 
912 	if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) +
913 		      descriptor_length)) {
914 		return -EOVERFLOW;
915 	}
916 
917 	descriptor_data->ptr = entry->descriptor_data;
918 	descriptor_data->length = descriptor_length;
919 
920 	return 0;
921 }
922 
923 LIBPLDM_ABI_STABLE
decode_descriptor_type_length_value(const uint8_t * data,size_t length,uint16_t * descriptor_type,struct variable_field * descriptor_data)924 int decode_descriptor_type_length_value(const uint8_t *data, size_t length,
925 					uint16_t *descriptor_type,
926 					struct variable_field *descriptor_data)
927 {
928 	int rc;
929 
930 	rc = decode_descriptor_type_length_value_errno(
931 		data, length, descriptor_type, descriptor_data);
932 	if (rc < 0) {
933 		return pldm_xlate_errno(rc);
934 	}
935 
936 	return PLDM_SUCCESS;
937 }
938 
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)939 static int decode_vendor_defined_descriptor_value_errno(
940 	const void *data, size_t length, uint8_t *descriptor_title_str_type,
941 	struct variable_field *descriptor_title_str,
942 	struct variable_field *descriptor_data)
943 {
944 	if (data == NULL || descriptor_title_str_type == NULL ||
945 	    descriptor_title_str == NULL || descriptor_data == NULL) {
946 		return -EINVAL;
947 	}
948 
949 	if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) {
950 		return -EOVERFLOW;
951 	}
952 
953 	struct pldm_vendor_defined_descriptor_title_data *entry =
954 		(struct pldm_vendor_defined_descriptor_title_data *)(data);
955 	if (!is_string_type_valid(
956 		    entry->vendor_defined_descriptor_title_str_type) ||
957 	    (entry->vendor_defined_descriptor_title_str_len == 0)) {
958 		return -EBADMSG;
959 	}
960 
961 	// Assuming at least 1 byte of VendorDefinedDescriptorData
962 	if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) +
963 		      entry->vendor_defined_descriptor_title_str_len)) {
964 		return -EOVERFLOW;
965 	}
966 
967 	*descriptor_title_str_type =
968 		entry->vendor_defined_descriptor_title_str_type;
969 	descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str;
970 	descriptor_title_str->length =
971 		entry->vendor_defined_descriptor_title_str_len;
972 
973 	descriptor_data->ptr =
974 		descriptor_title_str->ptr + descriptor_title_str->length;
975 	descriptor_data->length =
976 		length -
977 		sizeof(entry->vendor_defined_descriptor_title_str_type) -
978 		sizeof(entry->vendor_defined_descriptor_title_str_len) -
979 		descriptor_title_str->length;
980 
981 	return 0;
982 }
983 
984 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)985 int decode_vendor_defined_descriptor_value(
986 	const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type,
987 	struct variable_field *descriptor_title_str,
988 	struct variable_field *descriptor_data)
989 {
990 	int rc;
991 
992 	rc = decode_vendor_defined_descriptor_value_errno(
993 		data, length, descriptor_title_str_type, descriptor_title_str,
994 		descriptor_data);
995 	if (rc < 0) {
996 		return pldm_xlate_errno(rc);
997 	}
998 
999 	return PLDM_SUCCESS;
1000 }
1001 
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)1002 static int decode_pldm_comp_image_info_errno(
1003 	const void *data, size_t length,
1004 	struct pldm_component_image_information *pldm_comp_image_info,
1005 	struct variable_field *comp_version_str)
1006 {
1007 	if (data == NULL || pldm_comp_image_info == NULL ||
1008 	    comp_version_str == NULL) {
1009 		return -EINVAL;
1010 	}
1011 
1012 	if (length < sizeof(struct pldm_component_image_information)) {
1013 		return -EOVERFLOW;
1014 	}
1015 
1016 	struct pldm_component_image_information *data_header =
1017 		(struct pldm_component_image_information *)(data);
1018 
1019 	if (!is_string_type_valid(data_header->comp_version_string_type) ||
1020 	    (data_header->comp_version_string_length == 0)) {
1021 		return -EBADMSG;
1022 	}
1023 
1024 	if (length < sizeof(struct pldm_component_image_information) +
1025 			     data_header->comp_version_string_length) {
1026 		return -EOVERFLOW;
1027 	}
1028 
1029 	pldm_comp_image_info->comp_classification =
1030 		le16toh(data_header->comp_classification);
1031 	pldm_comp_image_info->comp_identifier =
1032 		le16toh(data_header->comp_identifier);
1033 	pldm_comp_image_info->comp_comparison_stamp =
1034 		le32toh(data_header->comp_comparison_stamp);
1035 	pldm_comp_image_info->comp_options.value =
1036 		le16toh(data_header->comp_options.value);
1037 	pldm_comp_image_info->requested_comp_activation_method.value =
1038 		le16toh(data_header->requested_comp_activation_method.value);
1039 	pldm_comp_image_info->comp_location_offset =
1040 		le32toh(data_header->comp_location_offset);
1041 	pldm_comp_image_info->comp_size = le32toh(data_header->comp_size);
1042 	pldm_comp_image_info->comp_version_string_type =
1043 		data_header->comp_version_string_type;
1044 	pldm_comp_image_info->comp_version_string_length =
1045 		data_header->comp_version_string_length;
1046 
1047 	if ((pldm_comp_image_info->comp_options.bits.bit1 == false &&
1048 	     pldm_comp_image_info->comp_comparison_stamp !=
1049 		     PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) {
1050 		return -EBADMSG;
1051 	}
1052 
1053 	if (pldm_comp_image_info->comp_location_offset == 0 ||
1054 	    pldm_comp_image_info->comp_size == 0) {
1055 		return -EBADMSG;
1056 	}
1057 
1058 	comp_version_str->ptr = (const uint8_t *)data +
1059 				sizeof(struct pldm_component_image_information);
1060 	comp_version_str->length =
1061 		pldm_comp_image_info->comp_version_string_length;
1062 
1063 	return 0;
1064 }
1065 
1066 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)1067 int decode_pldm_comp_image_info(
1068 	const uint8_t *data, size_t length,
1069 	struct pldm_component_image_information *pldm_comp_image_info,
1070 	struct variable_field *comp_version_str)
1071 {
1072 	int rc;
1073 
1074 	rc = decode_pldm_comp_image_info_errno(
1075 		data, length, pldm_comp_image_info, comp_version_str);
1076 	if (rc < 0) {
1077 		return pldm_xlate_errno(rc);
1078 	}
1079 
1080 	return PLDM_SUCCESS;
1081 }
1082 
1083 LIBPLDM_ABI_STABLE
encode_query_device_identifiers_req(uint8_t instance_id,size_t payload_length,struct pldm_msg * msg)1084 int encode_query_device_identifiers_req(uint8_t instance_id,
1085 					size_t payload_length,
1086 					struct pldm_msg *msg)
1087 {
1088 	if (msg == NULL) {
1089 		return PLDM_ERROR_INVALID_DATA;
1090 	}
1091 
1092 	if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) {
1093 		return PLDM_ERROR_INVALID_LENGTH;
1094 	}
1095 
1096 	return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
1097 				       PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
1098 }
1099 
1100 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)1101 int decode_query_device_identifiers_resp(const struct pldm_msg *msg,
1102 					 size_t payload_length,
1103 					 uint8_t *completion_code,
1104 					 uint32_t *device_identifiers_len,
1105 					 uint8_t *descriptor_count,
1106 					 uint8_t **descriptor_data)
1107 {
1108 	if (msg == NULL || completion_code == NULL ||
1109 	    device_identifiers_len == NULL || descriptor_count == NULL ||
1110 	    descriptor_data == NULL) {
1111 		return PLDM_ERROR_INVALID_DATA;
1112 	}
1113 
1114 	*completion_code = msg->payload[0];
1115 	if (PLDM_SUCCESS != *completion_code) {
1116 		return PLDM_SUCCESS;
1117 	}
1118 
1119 	if (payload_length <
1120 	    sizeof(struct pldm_query_device_identifiers_resp)) {
1121 		return PLDM_ERROR_INVALID_LENGTH;
1122 	}
1123 
1124 	struct pldm_query_device_identifiers_resp *response =
1125 		(struct pldm_query_device_identifiers_resp *)msg->payload;
1126 	*device_identifiers_len = le32toh(response->device_identifiers_len);
1127 
1128 	if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) {
1129 		return PLDM_ERROR_INVALID_LENGTH;
1130 	}
1131 
1132 	if (payload_length !=
1133 	    sizeof(struct pldm_query_device_identifiers_resp) +
1134 		    *device_identifiers_len) {
1135 		return PLDM_ERROR_INVALID_LENGTH;
1136 	}
1137 	*descriptor_count = response->descriptor_count;
1138 
1139 	if (*descriptor_count == 0) {
1140 		return PLDM_ERROR_INVALID_DATA;
1141 	}
1142 	*descriptor_data =
1143 		(uint8_t *)(msg->payload +
1144 			    sizeof(struct pldm_query_device_identifiers_resp));
1145 	return PLDM_SUCCESS;
1146 }
1147 
1148 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)1149 int encode_query_device_identifiers_resp(
1150 	uint8_t instance_id, uint8_t descriptor_count,
1151 	const struct pldm_descriptor *descriptors, struct pldm_msg *msg,
1152 	size_t *payload_length)
1153 {
1154 	PLDM_MSGBUF_RW_DEFINE_P(buf);
1155 	int rc;
1156 
1157 	if (descriptors == NULL || msg == NULL || payload_length == NULL) {
1158 		return -EINVAL;
1159 	}
1160 
1161 	if (descriptor_count < 1) {
1162 		return -EINVAL;
1163 	}
1164 
1165 	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
1166 				     PLDM_QUERY_DEVICE_IDENTIFIERS, msg);
1167 	if (rc) {
1168 		return -EINVAL;
1169 	}
1170 
1171 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1172 	if (rc) {
1173 		return rc;
1174 	}
1175 
1176 	/* Determine total length */
1177 	uint32_t device_identifiers_len = 0;
1178 	for (uint8_t i = 0; i < descriptor_count; i++) {
1179 		const struct pldm_descriptor *d = &descriptors[i];
1180 		device_identifiers_len +=
1181 			2 * sizeof(uint16_t) + d->descriptor_length;
1182 	}
1183 
1184 	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
1185 	pldm_msgbuf_insert(buf, device_identifiers_len);
1186 	pldm_msgbuf_insert(buf, descriptor_count);
1187 
1188 	for (uint8_t i = 0; i < descriptor_count; i++) {
1189 		const struct pldm_descriptor *d = &descriptors[i];
1190 		pldm_msgbuf_insert(buf, d->descriptor_type);
1191 		pldm_msgbuf_insert(buf, d->descriptor_length);
1192 		if (d->descriptor_data == NULL) {
1193 			return pldm_msgbuf_discard(buf, -EINVAL);
1194 		}
1195 		rc = pldm_msgbuf_insert_array(
1196 			buf, d->descriptor_length,
1197 			(const uint8_t *)d->descriptor_data,
1198 			d->descriptor_length);
1199 		if (rc) {
1200 			return pldm_msgbuf_discard(buf, rc);
1201 		}
1202 	}
1203 
1204 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1205 }
1206 
1207 LIBPLDM_ABI_STABLE
encode_get_firmware_parameters_req(uint8_t instance_id,size_t payload_length,struct pldm_msg * msg)1208 int encode_get_firmware_parameters_req(uint8_t instance_id,
1209 				       size_t payload_length,
1210 				       struct pldm_msg *msg)
1211 {
1212 	if (msg == NULL) {
1213 		return PLDM_ERROR_INVALID_DATA;
1214 	}
1215 
1216 	if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) {
1217 		return PLDM_ERROR_INVALID_LENGTH;
1218 	}
1219 
1220 	return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
1221 				       PLDM_GET_FIRMWARE_PARAMETERS, msg);
1222 }
1223 
1224 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)1225 int decode_get_firmware_parameters_resp(
1226 	const struct pldm_msg *msg, size_t payload_length,
1227 	struct pldm_get_firmware_parameters_resp *resp_data,
1228 	struct variable_field *active_comp_image_set_ver_str,
1229 	struct variable_field *pending_comp_image_set_ver_str,
1230 	struct variable_field *comp_parameter_table)
1231 {
1232 	if (msg == NULL || resp_data == NULL ||
1233 	    active_comp_image_set_ver_str == NULL ||
1234 	    pending_comp_image_set_ver_str == NULL ||
1235 	    comp_parameter_table == NULL || !payload_length) {
1236 		return PLDM_ERROR_INVALID_DATA;
1237 	}
1238 
1239 	resp_data->completion_code = msg->payload[0];
1240 	if (PLDM_SUCCESS != resp_data->completion_code) {
1241 		return PLDM_SUCCESS;
1242 	}
1243 
1244 	if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) {
1245 		return PLDM_ERROR_INVALID_LENGTH;
1246 	}
1247 
1248 	struct pldm_get_firmware_parameters_resp *response =
1249 		(struct pldm_get_firmware_parameters_resp *)msg->payload;
1250 
1251 	if (!is_string_type_valid(
1252 		    response->active_comp_image_set_ver_str_type) ||
1253 	    (response->active_comp_image_set_ver_str_len == 0)) {
1254 		return PLDM_ERROR_INVALID_DATA;
1255 	}
1256 
1257 	if (response->pending_comp_image_set_ver_str_len == 0) {
1258 		if (response->pending_comp_image_set_ver_str_type !=
1259 		    PLDM_STR_TYPE_UNKNOWN) {
1260 			return PLDM_ERROR_INVALID_DATA;
1261 		}
1262 	} else {
1263 		if (!is_string_type_valid(
1264 			    response->pending_comp_image_set_ver_str_type)) {
1265 			return PLDM_ERROR_INVALID_DATA;
1266 		}
1267 	}
1268 
1269 	size_t partial_response_length =
1270 		sizeof(struct pldm_get_firmware_parameters_resp) +
1271 		response->active_comp_image_set_ver_str_len +
1272 		response->pending_comp_image_set_ver_str_len;
1273 
1274 	if (payload_length < partial_response_length) {
1275 		return PLDM_ERROR_INVALID_LENGTH;
1276 	}
1277 
1278 	resp_data->capabilities_during_update.value =
1279 		le32toh(response->capabilities_during_update.value);
1280 	resp_data->comp_count = le16toh(response->comp_count);
1281 	resp_data->active_comp_image_set_ver_str_type =
1282 		response->active_comp_image_set_ver_str_type;
1283 	resp_data->active_comp_image_set_ver_str_len =
1284 		response->active_comp_image_set_ver_str_len;
1285 	resp_data->pending_comp_image_set_ver_str_type =
1286 		response->pending_comp_image_set_ver_str_type;
1287 	resp_data->pending_comp_image_set_ver_str_len =
1288 		response->pending_comp_image_set_ver_str_len;
1289 
1290 	active_comp_image_set_ver_str->ptr =
1291 		msg->payload + sizeof(struct pldm_get_firmware_parameters_resp);
1292 	active_comp_image_set_ver_str->length =
1293 		resp_data->active_comp_image_set_ver_str_len;
1294 
1295 	if (resp_data->pending_comp_image_set_ver_str_len != 0) {
1296 		pending_comp_image_set_ver_str->ptr =
1297 			msg->payload +
1298 			sizeof(struct pldm_get_firmware_parameters_resp) +
1299 			resp_data->active_comp_image_set_ver_str_len;
1300 		pending_comp_image_set_ver_str->length =
1301 			resp_data->pending_comp_image_set_ver_str_len;
1302 	} else {
1303 		pending_comp_image_set_ver_str->ptr = NULL;
1304 		pending_comp_image_set_ver_str->length = 0;
1305 	}
1306 
1307 	if (payload_length > partial_response_length && resp_data->comp_count) {
1308 		comp_parameter_table->ptr =
1309 			msg->payload +
1310 			sizeof(struct pldm_get_firmware_parameters_resp) +
1311 			resp_data->active_comp_image_set_ver_str_len +
1312 			resp_data->pending_comp_image_set_ver_str_len;
1313 		comp_parameter_table->length =
1314 			payload_length - partial_response_length;
1315 	} else {
1316 		comp_parameter_table->ptr = NULL;
1317 		comp_parameter_table->length = 0;
1318 	}
1319 
1320 	return PLDM_SUCCESS;
1321 }
1322 
1323 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)1324 int encode_get_firmware_parameters_resp(
1325 	uint8_t instance_id,
1326 	const struct pldm_get_firmware_parameters_resp_full *resp_data,
1327 	struct pldm_msg *msg, size_t *payload_length)
1328 {
1329 	PLDM_MSGBUF_RW_DEFINE_P(buf);
1330 	int rc;
1331 
1332 	if (resp_data == NULL || msg == NULL || payload_length == NULL) {
1333 		return -EINVAL;
1334 	}
1335 
1336 	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
1337 				     PLDM_GET_FIRMWARE_PARAMETERS, msg);
1338 	if (rc) {
1339 		return -EINVAL;
1340 	}
1341 
1342 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
1343 	if (rc) {
1344 		return rc;
1345 	}
1346 
1347 	pldm_msgbuf_insert(buf, resp_data->completion_code);
1348 	pldm_msgbuf_insert(buf, resp_data->capabilities_during_update.value);
1349 	pldm_msgbuf_insert(buf, resp_data->comp_count);
1350 	pldm_msgbuf_insert(buf,
1351 			   resp_data->active_comp_image_set_ver_str.str_type);
1352 	pldm_msgbuf_insert(buf,
1353 			   resp_data->active_comp_image_set_ver_str.str_len);
1354 	pldm_msgbuf_insert(buf,
1355 			   resp_data->pending_comp_image_set_ver_str.str_type);
1356 	pldm_msgbuf_insert(buf,
1357 			   resp_data->pending_comp_image_set_ver_str.str_len);
1358 	/* String data appended */
1359 	rc = pldm_msgbuf_insert_array(
1360 		buf, resp_data->active_comp_image_set_ver_str.str_len,
1361 		resp_data->active_comp_image_set_ver_str.str_data,
1362 		resp_data->active_comp_image_set_ver_str.str_len);
1363 	if (rc) {
1364 		return pldm_msgbuf_discard(buf, rc);
1365 	}
1366 	rc = pldm_msgbuf_insert_array(
1367 		buf, resp_data->pending_comp_image_set_ver_str.str_len,
1368 		resp_data->pending_comp_image_set_ver_str.str_data,
1369 		resp_data->pending_comp_image_set_ver_str.str_len);
1370 	if (rc) {
1371 		return pldm_msgbuf_discard(buf, rc);
1372 	}
1373 
1374 	/* Further calls to encode_get_firmware_parameters_resp_comp_entry
1375 	 * will populate the remainder */
1376 
1377 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1378 }
1379 
1380 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)1381 int encode_get_firmware_parameters_resp_comp_entry(
1382 	const struct pldm_component_parameter_entry_full *comp,
1383 	uint8_t *payload, size_t *payload_length)
1384 {
1385 	PLDM_MSGBUF_RW_DEFINE_P(buf);
1386 	int rc;
1387 
1388 	if (comp == NULL || payload == NULL || payload_length == NULL) {
1389 		return -EINVAL;
1390 	}
1391 
1392 	rc = pldm_msgbuf_init_errno(buf, 0, payload, *payload_length);
1393 	if (rc) {
1394 		return rc;
1395 	}
1396 
1397 	pldm_msgbuf_insert(buf, comp->comp_classification);
1398 	pldm_msgbuf_insert(buf, comp->comp_identifier);
1399 	pldm_msgbuf_insert(buf, comp->comp_classification_index);
1400 
1401 	pldm_msgbuf_insert(buf, comp->active_ver.comparison_stamp);
1402 	pldm_msgbuf_insert(buf, (uint8_t)comp->active_ver.str.str_type);
1403 	pldm_msgbuf_insert(buf, comp->active_ver.str.str_len);
1404 	rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1405 				      comp->active_ver.date,
1406 				      PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
1407 	if (rc) {
1408 		return pldm_msgbuf_discard(buf, rc);
1409 	}
1410 
1411 	pldm_msgbuf_insert(buf, comp->pending_ver.comparison_stamp);
1412 	pldm_msgbuf_insert(buf, (uint8_t)comp->pending_ver.str.str_type);
1413 	pldm_msgbuf_insert(buf, comp->pending_ver.str.str_len);
1414 	rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1415 				      comp->pending_ver.date,
1416 				      PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN);
1417 	if (rc) {
1418 		return pldm_msgbuf_discard(buf, rc);
1419 	}
1420 
1421 	pldm_msgbuf_insert(buf, comp->comp_activation_methods.value);
1422 	pldm_msgbuf_insert(buf, comp->capabilities_during_update.value);
1423 
1424 	rc = pldm_msgbuf_insert_array(buf, comp->active_ver.str.str_len,
1425 				      comp->active_ver.str.str_data,
1426 				      comp->active_ver.str.str_len);
1427 	if (rc) {
1428 		return pldm_msgbuf_discard(buf, rc);
1429 	}
1430 	rc = pldm_msgbuf_insert_array(buf, comp->pending_ver.str.str_len,
1431 				      comp->pending_ver.str.str_data,
1432 				      comp->pending_ver.str.str_len);
1433 	if (rc) {
1434 		return pldm_msgbuf_discard(buf, rc);
1435 	}
1436 
1437 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1438 }
1439 
1440 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)1441 int decode_get_firmware_parameters_resp_comp_entry(
1442 	const uint8_t *data, size_t length,
1443 	struct pldm_component_parameter_entry *component_data,
1444 	struct variable_field *active_comp_ver_str,
1445 	struct variable_field *pending_comp_ver_str)
1446 {
1447 	if (data == NULL || component_data == NULL ||
1448 	    active_comp_ver_str == NULL || pending_comp_ver_str == NULL) {
1449 		return PLDM_ERROR_INVALID_DATA;
1450 	}
1451 
1452 	if (length < sizeof(struct pldm_component_parameter_entry)) {
1453 		return PLDM_ERROR_INVALID_LENGTH;
1454 	}
1455 
1456 	struct pldm_component_parameter_entry *entry =
1457 		(struct pldm_component_parameter_entry *)(data);
1458 
1459 	size_t entry_length = sizeof(struct pldm_component_parameter_entry) +
1460 			      entry->active_comp_ver_str_len +
1461 			      entry->pending_comp_ver_str_len;
1462 
1463 	if (length < entry_length) {
1464 		return PLDM_ERROR_INVALID_LENGTH;
1465 	}
1466 
1467 	component_data->comp_classification =
1468 		le16toh(entry->comp_classification);
1469 	component_data->comp_identifier = le16toh(entry->comp_identifier);
1470 	component_data->comp_classification_index =
1471 		entry->comp_classification_index;
1472 	component_data->active_comp_comparison_stamp =
1473 		le32toh(entry->active_comp_comparison_stamp);
1474 	component_data->active_comp_ver_str_type =
1475 		entry->active_comp_ver_str_type;
1476 	component_data->active_comp_ver_str_len =
1477 		entry->active_comp_ver_str_len;
1478 	memcpy(component_data->active_comp_release_date,
1479 	       entry->active_comp_release_date,
1480 	       sizeof(entry->active_comp_release_date));
1481 	component_data->pending_comp_comparison_stamp =
1482 		le32toh(entry->pending_comp_comparison_stamp);
1483 	component_data->pending_comp_ver_str_type =
1484 		entry->pending_comp_ver_str_type;
1485 	component_data->pending_comp_ver_str_len =
1486 		entry->pending_comp_ver_str_len;
1487 	memcpy(component_data->pending_comp_release_date,
1488 	       entry->pending_comp_release_date,
1489 	       sizeof(entry->pending_comp_release_date));
1490 	component_data->comp_activation_methods.value =
1491 		le16toh(entry->comp_activation_methods.value);
1492 	component_data->capabilities_during_update.value =
1493 		le32toh(entry->capabilities_during_update.value);
1494 
1495 	if (entry->active_comp_ver_str_len != 0) {
1496 		active_comp_ver_str->ptr =
1497 			data + sizeof(struct pldm_component_parameter_entry);
1498 		active_comp_ver_str->length = entry->active_comp_ver_str_len;
1499 	} else {
1500 		active_comp_ver_str->ptr = NULL;
1501 		active_comp_ver_str->length = 0;
1502 	}
1503 
1504 	if (entry->pending_comp_ver_str_len != 0) {
1505 		pending_comp_ver_str->ptr =
1506 			data + sizeof(struct pldm_component_parameter_entry) +
1507 			entry->active_comp_ver_str_len;
1508 		pending_comp_ver_str->length = entry->pending_comp_ver_str_len;
1509 	} else {
1510 		pending_comp_ver_str->ptr = NULL;
1511 		pending_comp_ver_str->length = 0;
1512 	}
1513 	return PLDM_SUCCESS;
1514 }
1515 
1516 LIBPLDM_ABI_STABLE
encode_query_downstream_devices_req(uint8_t instance_id,struct pldm_msg * msg)1517 int encode_query_downstream_devices_req(uint8_t instance_id,
1518 					struct pldm_msg *msg)
1519 {
1520 	if (msg == NULL) {
1521 		return -EINVAL;
1522 	}
1523 
1524 	return encode_pldm_header_only_errno(PLDM_REQUEST, instance_id,
1525 					     PLDM_FWUP,
1526 					     PLDM_QUERY_DOWNSTREAM_DEVICES,
1527 					     msg);
1528 }
1529 
1530 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)1531 int decode_query_downstream_devices_resp(
1532 	const struct pldm_msg *msg, size_t payload_length,
1533 	struct pldm_query_downstream_devices_resp *resp_data)
1534 {
1535 	PLDM_MSGBUF_RO_DEFINE_P(buf);
1536 	int rc;
1537 
1538 	if (msg == NULL || resp_data == NULL || !payload_length) {
1539 		return -EINVAL;
1540 	}
1541 
1542 	rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1543 				    msg->payload, payload_length);
1544 	if (rc) {
1545 		return rc;
1546 	}
1547 
1548 	rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1549 	if (rc) {
1550 		return pldm_msgbuf_discard(buf, rc);
1551 	}
1552 	if (PLDM_SUCCESS != resp_data->completion_code) {
1553 		// Return the CC directly without decoding the rest of the payload
1554 		return pldm_msgbuf_complete(buf);
1555 	}
1556 
1557 	if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) {
1558 		return pldm_msgbuf_discard(buf, -EBADMSG);
1559 	}
1560 
1561 	rc = pldm_msgbuf_extract(buf,
1562 				 resp_data->downstream_device_update_supported);
1563 	if (rc) {
1564 		return pldm_msgbuf_discard(buf, rc);
1565 	}
1566 
1567 	if (!is_downstream_device_update_support_valid(
1568 		    resp_data->downstream_device_update_supported)) {
1569 		return pldm_msgbuf_discard(buf, -EINVAL);
1570 	}
1571 
1572 	pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
1573 	pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices);
1574 	pldm_msgbuf_extract(buf, resp_data->capabilities.value);
1575 
1576 	return pldm_msgbuf_complete_consumed(buf);
1577 }
1578 
1579 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)1580 int encode_query_downstream_identifiers_req(
1581 	uint8_t instance_id,
1582 	const struct pldm_query_downstream_identifiers_req *params_req,
1583 	struct pldm_msg *msg, size_t payload_length)
1584 {
1585 	PLDM_MSGBUF_RW_DEFINE_P(buf);
1586 	int rc;
1587 
1588 	if (!msg || !params_req) {
1589 		return -EINVAL;
1590 	}
1591 
1592 	if (!is_transfer_operation_flag_valid(
1593 		    (enum transfer_op_flag)
1594 			    params_req->transfer_operation_flag)) {
1595 		return -EINVAL;
1596 	}
1597 
1598 	struct pldm_header_info header = { 0 };
1599 	header.instance = instance_id;
1600 	header.msg_type = PLDM_REQUEST;
1601 	header.pldm_type = PLDM_FWUP;
1602 	header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS;
1603 	rc = pack_pldm_header_errno(&header, &(msg->hdr));
1604 	if (rc) {
1605 		return rc;
1606 	}
1607 
1608 	rc = pldm_msgbuf_init_errno(buf,
1609 				    PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES,
1610 				    msg->payload, payload_length);
1611 	if (rc) {
1612 		return rc;
1613 	}
1614 
1615 	pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
1616 	// Data correctness has been verified, cast it to 1-byte data directly.
1617 	pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
1618 
1619 	return pldm_msgbuf_complete(buf);
1620 }
1621 
1622 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)1623 int decode_query_downstream_identifiers_resp(
1624 	const struct pldm_msg *msg, size_t payload_length,
1625 	struct pldm_query_downstream_identifiers_resp *resp_data,
1626 	struct pldm_downstream_device_iter *iter)
1627 {
1628 	PLDM_MSGBUF_RO_DEFINE_P(buf);
1629 	const void *remaining = NULL;
1630 	int rc = 0;
1631 
1632 	if (msg == NULL || resp_data == NULL || iter == NULL ||
1633 	    !payload_length) {
1634 		return -EINVAL;
1635 	}
1636 
1637 	rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1638 				    msg->payload, payload_length);
1639 	if (rc) {
1640 		return rc;
1641 	}
1642 
1643 	rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1644 	if (rc) {
1645 		return pldm_msgbuf_discard(buf, rc);
1646 	}
1647 	if (PLDM_SUCCESS != resp_data->completion_code) {
1648 		return pldm_msgbuf_complete(buf);
1649 	}
1650 
1651 	if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) {
1652 		return pldm_msgbuf_discard(buf, -EBADMSG);
1653 	}
1654 
1655 	pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1656 	pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1657 
1658 	rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length);
1659 	if (rc) {
1660 		return pldm_msgbuf_discard(buf, rc);
1661 	}
1662 
1663 	pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices);
1664 	pldm_msgbuf_span_required(buf, resp_data->downstream_devices_length,
1665 				  &remaining);
1666 
1667 	rc = pldm_msgbuf_complete(buf);
1668 	if (rc) {
1669 		return rc;
1670 	}
1671 
1672 	iter->field.ptr = remaining;
1673 	iter->field.length = resp_data->downstream_devices_length;
1674 	iter->devs = resp_data->number_of_downstream_devices;
1675 
1676 	return 0;
1677 }
1678 
1679 LIBPLDM_ABI_STABLE
decode_pldm_downstream_device_from_iter(struct pldm_downstream_device_iter * iter,struct pldm_downstream_device * dev)1680 int decode_pldm_downstream_device_from_iter(
1681 	struct pldm_downstream_device_iter *iter,
1682 	struct pldm_downstream_device *dev)
1683 {
1684 	PLDM_MSGBUF_RO_DEFINE_P(buf);
1685 	int rc;
1686 
1687 	if (!iter || !iter->field.ptr || !dev) {
1688 		return -EINVAL;
1689 	}
1690 
1691 	rc = pldm_msgbuf_init_errno(buf, 3, iter->field.ptr,
1692 				    iter->field.length);
1693 	if (rc) {
1694 		return rc;
1695 	}
1696 
1697 	pldm_msgbuf_extract(buf, dev->downstream_device_index);
1698 	pldm_msgbuf_extract(buf, dev->downstream_descriptor_count);
1699 	pldm_msgbuf_span_remaining(buf, (const void **)&iter->field.ptr,
1700 				   &iter->field.length);
1701 
1702 	return pldm_msgbuf_complete(buf);
1703 }
1704 
1705 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)1706 int encode_get_downstream_firmware_parameters_req(
1707 	uint8_t instance_id,
1708 	const struct pldm_get_downstream_firmware_parameters_req *params_req,
1709 	struct pldm_msg *msg, size_t payload_length)
1710 {
1711 	PLDM_MSGBUF_RW_DEFINE_P(buf);
1712 	int rc;
1713 
1714 	if (!msg || !params_req) {
1715 		return -EINVAL;
1716 	}
1717 
1718 	if (!is_transfer_operation_flag_valid(
1719 		    (enum transfer_op_flag)
1720 			    params_req->transfer_operation_flag)) {
1721 		return -EBADMSG;
1722 	}
1723 
1724 	struct pldm_header_info header = { 0 };
1725 	header.instance = instance_id;
1726 	header.msg_type = PLDM_REQUEST;
1727 	header.pldm_type = PLDM_FWUP;
1728 	header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS;
1729 	rc = pack_pldm_header_errno(&header, &msg->hdr);
1730 	if (rc < 0) {
1731 		return rc;
1732 	}
1733 
1734 	rc = pldm_msgbuf_init_errno(
1735 		buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES,
1736 		msg->payload, payload_length);
1737 	if (rc < 0) {
1738 		return rc;
1739 	}
1740 
1741 	pldm_msgbuf_insert(buf, params_req->data_transfer_handle);
1742 	// Data correctness has been verified, cast it to 1-byte data directly.
1743 	pldm_msgbuf_insert(buf, params_req->transfer_operation_flag);
1744 
1745 	return pldm_msgbuf_complete(buf);
1746 }
1747 
1748 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)1749 int decode_get_downstream_firmware_parameters_resp(
1750 	const struct pldm_msg *msg, size_t payload_length,
1751 	struct pldm_get_downstream_firmware_parameters_resp *resp_data,
1752 	struct pldm_downstream_device_parameters_iter *iter)
1753 {
1754 	PLDM_MSGBUF_RO_DEFINE_P(buf);
1755 	const void *remaining = NULL;
1756 	size_t length;
1757 	int rc;
1758 
1759 	if (msg == NULL || resp_data == NULL || iter == NULL) {
1760 		return -EINVAL;
1761 	}
1762 
1763 	rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN,
1764 				    msg->payload, payload_length);
1765 	if (rc < 0) {
1766 		return rc;
1767 	}
1768 
1769 	rc = pldm_msgbuf_extract(buf, resp_data->completion_code);
1770 	if (rc < 0) {
1771 		return pldm_msgbuf_discard(buf, rc);
1772 	}
1773 	if (PLDM_SUCCESS != resp_data->completion_code) {
1774 		return pldm_msgbuf_complete(buf);
1775 	}
1776 
1777 	if (payload_length <
1778 	    PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN) {
1779 		return pldm_msgbuf_discard(buf, -EBADMSG);
1780 	}
1781 
1782 	pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle);
1783 	pldm_msgbuf_extract(buf, resp_data->transfer_flag);
1784 	pldm_msgbuf_extract(buf,
1785 			    resp_data->fdp_capabilities_during_update.value);
1786 	pldm_msgbuf_extract(buf, resp_data->downstream_device_count);
1787 
1788 	rc = pldm_msgbuf_span_remaining(buf, &remaining, &length);
1789 	if (rc) {
1790 		return pldm_msgbuf_discard(buf, rc);
1791 	}
1792 
1793 	rc = pldm_msgbuf_complete(buf);
1794 	if (rc) {
1795 		return rc;
1796 	}
1797 
1798 	iter->field.ptr = remaining;
1799 	iter->field.length = length;
1800 	iter->entries = resp_data->downstream_device_count;
1801 
1802 	return 0;
1803 }
1804 
1805 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)1806 int decode_pldm_downstream_device_parameters_entry_from_iter(
1807 	struct pldm_downstream_device_parameters_iter *iter,
1808 	struct pldm_downstream_device_parameters_entry *entry)
1809 {
1810 	PLDM_MSGBUF_RO_DEFINE_P(buf);
1811 	const void *comp_ver_str;
1812 	const void *cursor;
1813 	size_t remaining;
1814 	int rc;
1815 
1816 	if (iter == NULL || iter->field.ptr == NULL || entry == NULL) {
1817 		return -EINVAL;
1818 	}
1819 
1820 	rc = pldm_msgbuf_init_errno(
1821 		buf, PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN,
1822 		iter->field.ptr, iter->field.length);
1823 	if (rc < 0) {
1824 		return rc;
1825 	}
1826 
1827 	pldm_msgbuf_extract(buf, entry->downstream_device_index);
1828 	pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp);
1829 	pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type);
1830 	rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len);
1831 	if (rc < 0) {
1832 		return pldm_msgbuf_discard(buf, rc);
1833 	}
1834 	rc = pldm_msgbuf_extract_array(buf,
1835 				       PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1836 				       entry->active_comp_release_date,
1837 				       sizeof(entry->active_comp_release_date));
1838 	if (rc < 0) {
1839 		return pldm_msgbuf_discard(buf, rc);
1840 	}
1841 
1842 	// Fill the last byte with NULL character
1843 	entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1844 		'\0';
1845 
1846 	pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp);
1847 	pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type);
1848 	rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len);
1849 	if (rc < 0) {
1850 		return pldm_msgbuf_discard(buf, rc);
1851 	}
1852 
1853 	rc = pldm_msgbuf_extract_array(
1854 		buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN,
1855 		entry->pending_comp_release_date,
1856 		sizeof(entry->pending_comp_release_date));
1857 	if (rc < 0) {
1858 		return pldm_msgbuf_discard(buf, rc);
1859 	}
1860 
1861 	// Fill the last byte with NULL character
1862 	entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] =
1863 		'\0';
1864 
1865 	pldm_msgbuf_extract(buf, entry->comp_activation_methods.value);
1866 	pldm_msgbuf_extract(buf, entry->capabilities_during_update.value);
1867 
1868 	rc = pldm_msgbuf_span_required(buf, entry->active_comp_ver_str_len,
1869 				       &comp_ver_str);
1870 	if (rc < 0) {
1871 		return pldm_msgbuf_discard(buf, rc);
1872 	}
1873 	entry->active_comp_ver_str = comp_ver_str;
1874 
1875 	rc = pldm_msgbuf_span_required(buf, entry->pending_comp_ver_str_len,
1876 				       &comp_ver_str);
1877 	if (rc < 0) {
1878 		return pldm_msgbuf_discard(buf, rc);
1879 	}
1880 	entry->pending_comp_ver_str = comp_ver_str;
1881 
1882 	rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining);
1883 	if (rc < 0) {
1884 		return pldm_msgbuf_discard(buf, rc);
1885 	}
1886 
1887 	iter->field.ptr = cursor;
1888 	iter->field.length = remaining;
1889 
1890 	return pldm_msgbuf_complete(buf);
1891 }
1892 
1893 LIBPLDM_ABI_TESTING
encode_request_downstream_device_update_req(uint8_t instance_id,const struct pldm_request_downstream_device_update_req * req_data,struct pldm_msg * msg,size_t * payload_length)1894 int encode_request_downstream_device_update_req(
1895 	uint8_t instance_id,
1896 	const struct pldm_request_downstream_device_update_req *req_data,
1897 	struct pldm_msg *msg, size_t *payload_length)
1898 {
1899 	PLDM_MSGBUF_RW_DEFINE_P(buf);
1900 	int rc;
1901 
1902 	if (!req_data || !msg || !payload_length ||
1903 	    req_data->maximum_downstream_device_transfer_size <
1904 		    PLDM_FWUP_BASELINE_TRANSFER_SIZE ||
1905 	    req_data->maximum_outstanding_transfer_requests <
1906 		    PLDM_FWUP_MIN_OUTSTANDING_REQ) {
1907 		return -EINVAL;
1908 	}
1909 
1910 	rc = encode_pldm_header_only_errno(
1911 		PLDM_REQUEST, instance_id, PLDM_FWUP,
1912 		PLDM_REQUEST_DOWNSTREAM_DEVICE_UPDATE, msg);
1913 	if (rc) {
1914 		return rc;
1915 	}
1916 
1917 	rc = pldm_msgbuf_init_errno(buf,
1918 				    PLDM_DOWNSTREAM_DEVICE_UPDATE_REQUEST_BYTES,
1919 				    msg->payload, *payload_length);
1920 	if (rc) {
1921 		return rc;
1922 	}
1923 
1924 	pldm_msgbuf_insert(buf,
1925 			   req_data->maximum_downstream_device_transfer_size);
1926 	pldm_msgbuf_insert(buf,
1927 			   req_data->maximum_outstanding_transfer_requests);
1928 	pldm_msgbuf_insert(buf,
1929 			   req_data->downstream_device_package_data_length);
1930 
1931 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1932 }
1933 
1934 LIBPLDM_ABI_TESTING
decode_request_downstream_device_update_req(const struct pldm_msg * msg,size_t payload_length,struct pldm_request_downstream_device_update_req * req)1935 int decode_request_downstream_device_update_req(
1936 	const struct pldm_msg *msg, size_t payload_length,
1937 	struct pldm_request_downstream_device_update_req *req)
1938 {
1939 	int rc;
1940 	PLDM_MSGBUF_RO_DEFINE_P(buf);
1941 
1942 	if (!msg || !req) {
1943 		return -EINVAL;
1944 	}
1945 
1946 	rc = pldm_msgbuf_init_errno(buf,
1947 				    PLDM_DOWNSTREAM_DEVICE_UPDATE_REQUEST_BYTES,
1948 				    msg->payload, payload_length);
1949 	if (rc) {
1950 		return rc;
1951 	}
1952 
1953 	pldm_msgbuf_extract(buf, req->maximum_downstream_device_transfer_size);
1954 	pldm_msgbuf_extract(buf, req->maximum_outstanding_transfer_requests);
1955 	pldm_msgbuf_extract(buf, req->downstream_device_package_data_length);
1956 
1957 	return pldm_msgbuf_complete_consumed(buf);
1958 }
1959 
1960 LIBPLDM_ABI_TESTING
encode_request_downstream_device_update_resp(uint8_t instance_id,const struct pldm_request_downstream_device_update_resp * resp_data,struct pldm_msg * msg,size_t * payload_length)1961 int encode_request_downstream_device_update_resp(
1962 	uint8_t instance_id,
1963 	const struct pldm_request_downstream_device_update_resp *resp_data,
1964 	struct pldm_msg *msg, size_t *payload_length)
1965 {
1966 	PLDM_MSGBUF_RW_DEFINE_P(buf);
1967 	int rc;
1968 
1969 	if (!resp_data || !msg || !payload_length) {
1970 		return -EINVAL;
1971 	}
1972 
1973 	rc = encode_pldm_header_only_errno(
1974 		PLDM_RESPONSE, instance_id, PLDM_FWUP,
1975 		PLDM_REQUEST_DOWNSTREAM_DEVICE_UPDATE, msg);
1976 	if (rc) {
1977 		return rc;
1978 	}
1979 
1980 	rc = pldm_msgbuf_init_errno(
1981 		buf, PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES, msg->payload,
1982 		*payload_length);
1983 	if (rc) {
1984 		return rc;
1985 	}
1986 
1987 	pldm_msgbuf_insert(buf, resp_data->completion_code);
1988 	pldm_msgbuf_insert(buf, resp_data->downstream_device_meta_data_length);
1989 	pldm_msgbuf_insert(
1990 		buf, resp_data->downstream_device_will_send_get_package_data);
1991 	pldm_msgbuf_insert(buf,
1992 			   resp_data->get_package_data_maximum_transfer_size);
1993 
1994 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
1995 }
1996 
1997 LIBPLDM_ABI_TESTING
decode_request_downstream_device_update_resp(const struct pldm_msg * msg,size_t payload_length,struct pldm_request_downstream_device_update_resp * resp_data)1998 int decode_request_downstream_device_update_resp(
1999 	const struct pldm_msg *msg, size_t payload_length,
2000 	struct pldm_request_downstream_device_update_resp *resp_data)
2001 {
2002 	PLDM_MSGBUF_RO_DEFINE_P(buf);
2003 	int rc;
2004 
2005 	if (!msg || !resp_data) {
2006 		return -EINVAL;
2007 	}
2008 
2009 	rc = pldm_msg_has_error(msg,
2010 				PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES);
2011 	if (rc) {
2012 		resp_data->completion_code = rc;
2013 		return 0;
2014 	}
2015 
2016 	rc = pldm_msgbuf_init_errno(
2017 		buf, PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES, msg->payload,
2018 		payload_length);
2019 	if (rc) {
2020 		return rc;
2021 	}
2022 
2023 	pldm_msgbuf_extract(buf, resp_data->completion_code);
2024 	pldm_msgbuf_extract(buf, resp_data->downstream_device_meta_data_length);
2025 	pldm_msgbuf_extract(
2026 		buf, resp_data->downstream_device_will_send_get_package_data);
2027 	pldm_msgbuf_extract(buf,
2028 			    resp_data->get_package_data_maximum_transfer_size);
2029 
2030 	return pldm_msgbuf_complete_consumed(buf);
2031 }
2032 
2033 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)2034 int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size,
2035 			      uint16_t num_of_comp,
2036 			      uint8_t max_outstanding_transfer_req,
2037 			      uint16_t pkg_data_len,
2038 			      uint8_t comp_image_set_ver_str_type,
2039 			      uint8_t comp_image_set_ver_str_len,
2040 			      const struct variable_field *comp_img_set_ver_str,
2041 			      struct pldm_msg *msg, size_t payload_length)
2042 {
2043 	if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL ||
2044 	    msg == NULL) {
2045 		return PLDM_ERROR_INVALID_DATA;
2046 	}
2047 
2048 	if (payload_length != sizeof(struct pldm_request_update_req) +
2049 				      comp_img_set_ver_str->length) {
2050 		return PLDM_ERROR_INVALID_LENGTH;
2051 	}
2052 
2053 	if ((comp_image_set_ver_str_len == 0) ||
2054 	    (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) {
2055 		return PLDM_ERROR_INVALID_DATA;
2056 	}
2057 
2058 	if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) ||
2059 	    (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) {
2060 		return PLDM_ERROR_INVALID_DATA;
2061 	}
2062 
2063 	if (!is_string_type_valid(comp_image_set_ver_str_type)) {
2064 		return PLDM_ERROR_INVALID_DATA;
2065 	}
2066 
2067 	struct pldm_header_info header = { 0 };
2068 	header.instance = instance_id;
2069 	header.msg_type = PLDM_REQUEST;
2070 	header.pldm_type = PLDM_FWUP;
2071 	header.command = PLDM_REQUEST_UPDATE;
2072 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2073 	if (rc) {
2074 		return rc;
2075 	}
2076 
2077 	struct pldm_request_update_req *request =
2078 		(struct pldm_request_update_req *)msg->payload;
2079 
2080 	request->max_transfer_size = htole32(max_transfer_size);
2081 	request->num_of_comp = htole16(num_of_comp);
2082 	request->max_outstanding_transfer_req = max_outstanding_transfer_req;
2083 	request->pkg_data_len = htole16(pkg_data_len);
2084 	request->comp_image_set_ver_str_type = comp_image_set_ver_str_type;
2085 	request->comp_image_set_ver_str_len = comp_image_set_ver_str_len;
2086 
2087 	memcpy(msg->payload + sizeof(struct pldm_request_update_req),
2088 	       comp_img_set_ver_str->ptr, comp_img_set_ver_str->length);
2089 
2090 	return PLDM_SUCCESS;
2091 }
2092 
2093 LIBPLDM_ABI_TESTING
decode_request_update_req(const struct pldm_msg * msg,size_t payload_length,struct pldm_request_update_req_full * req)2094 int decode_request_update_req(const struct pldm_msg *msg, size_t payload_length,
2095 			      struct pldm_request_update_req_full *req)
2096 {
2097 	int rc;
2098 	uint8_t t;
2099 	PLDM_MSGBUF_RO_DEFINE_P(buf);
2100 
2101 	if (msg == NULL || req == NULL) {
2102 		return -EINVAL;
2103 	}
2104 
2105 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
2106 	if (rc) {
2107 		return rc;
2108 	}
2109 
2110 	pldm_msgbuf_extract(buf, req->max_transfer_size);
2111 	pldm_msgbuf_extract(buf, req->num_of_comp);
2112 	pldm_msgbuf_extract(buf, req->max_outstanding_transfer_req);
2113 	pldm_msgbuf_extract(buf, req->pkg_data_len);
2114 	rc = pldm_msgbuf_extract(buf, t);
2115 	if (rc) {
2116 		return pldm_msgbuf_discard(buf, rc);
2117 	}
2118 	if (t > PLDM_STR_TYPE_UTF_16BE) {
2119 		return pldm_msgbuf_discard(buf, -EBADMSG);
2120 	}
2121 	req->image_set_ver.str_type = (enum pldm_firmware_update_string_type)t;
2122 	pldm_msgbuf_extract(buf, req->image_set_ver.str_len);
2123 	if (rc) {
2124 		return pldm_msgbuf_discard(buf, rc);
2125 	}
2126 
2127 	rc = pldm_msgbuf_extract_array(buf, req->image_set_ver.str_len,
2128 				       req->image_set_ver.str_data,
2129 				       PLDM_FIRMWARE_MAX_STRING);
2130 	if (rc) {
2131 		return pldm_msgbuf_discard(buf, rc);
2132 	}
2133 
2134 	return pldm_msgbuf_complete_consumed(buf);
2135 }
2136 
2137 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)2138 int decode_request_update_resp(const struct pldm_msg *msg,
2139 			       size_t payload_length, uint8_t *completion_code,
2140 			       uint16_t *fd_meta_data_len,
2141 			       uint8_t *fd_will_send_pkg_data)
2142 {
2143 	if (msg == NULL || completion_code == NULL ||
2144 	    fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL ||
2145 	    !payload_length) {
2146 		return PLDM_ERROR_INVALID_DATA;
2147 	}
2148 
2149 	*completion_code = msg->payload[0];
2150 	if (*completion_code != PLDM_SUCCESS) {
2151 		return PLDM_SUCCESS;
2152 	}
2153 
2154 	if (payload_length != sizeof(struct pldm_request_update_resp)) {
2155 		return PLDM_ERROR_INVALID_LENGTH;
2156 	}
2157 
2158 	struct pldm_request_update_resp *response =
2159 		(struct pldm_request_update_resp *)msg->payload;
2160 
2161 	*fd_meta_data_len = le16toh(response->fd_meta_data_len);
2162 	*fd_will_send_pkg_data = response->fd_will_send_pkg_data;
2163 
2164 	return PLDM_SUCCESS;
2165 }
2166 
2167 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)2168 int encode_request_update_resp(uint8_t instance_id,
2169 			       const struct pldm_request_update_resp *resp_data,
2170 			       struct pldm_msg *msg, size_t *payload_length)
2171 {
2172 	PLDM_MSGBUF_RW_DEFINE_P(buf);
2173 	int rc;
2174 
2175 	if (msg == NULL || payload_length == NULL) {
2176 		return -EINVAL;
2177 	}
2178 
2179 	struct pldm_header_info header = {
2180 		.instance = instance_id,
2181 		.msg_type = PLDM_RESPONSE,
2182 		.pldm_type = PLDM_FWUP,
2183 		.command = PLDM_REQUEST_UPDATE,
2184 	};
2185 	rc = pack_pldm_header(&header, &(msg->hdr));
2186 	if (rc) {
2187 		return -EINVAL;
2188 	}
2189 
2190 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2191 	if (rc) {
2192 		return rc;
2193 	}
2194 
2195 	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2196 	pldm_msgbuf_insert(buf, resp_data->fd_meta_data_len);
2197 	pldm_msgbuf_insert(buf, resp_data->fd_will_send_pkg_data);
2198 
2199 	/* TODO: DSP0267 1.3.0 adds GetPackageDataMaximumTransferSize */
2200 
2201 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2202 }
2203 
2204 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)2205 int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag,
2206 				    uint16_t comp_classification,
2207 				    uint16_t comp_identifier,
2208 				    uint8_t comp_classification_index,
2209 				    uint32_t comp_comparison_stamp,
2210 				    uint8_t comp_ver_str_type,
2211 				    uint8_t comp_ver_str_len,
2212 				    const struct variable_field *comp_ver_str,
2213 				    struct pldm_msg *msg, size_t payload_length)
2214 {
2215 	if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
2216 		return PLDM_ERROR_INVALID_DATA;
2217 	}
2218 
2219 	if (payload_length != sizeof(struct pldm_pass_component_table_req) +
2220 				      comp_ver_str->length) {
2221 		return PLDM_ERROR_INVALID_LENGTH;
2222 	}
2223 
2224 	if ((comp_ver_str_len == 0) ||
2225 	    (comp_ver_str_len != comp_ver_str->length)) {
2226 		return PLDM_ERROR_INVALID_DATA;
2227 	}
2228 
2229 	if (!is_transfer_flag_valid(transfer_flag)) {
2230 		return PLDM_FWUP_INVALID_TRANSFER_OPERATION_FLAG;
2231 	}
2232 
2233 	if (!is_string_type_valid(comp_ver_str_type)) {
2234 		return PLDM_ERROR_INVALID_DATA;
2235 	}
2236 
2237 	struct pldm_header_info header = { 0 };
2238 	header.instance = instance_id;
2239 	header.msg_type = PLDM_REQUEST;
2240 	header.pldm_type = PLDM_FWUP;
2241 	header.command = PLDM_PASS_COMPONENT_TABLE;
2242 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2243 	if (rc) {
2244 		return rc;
2245 	}
2246 
2247 	struct pldm_pass_component_table_req *request =
2248 		(struct pldm_pass_component_table_req *)msg->payload;
2249 
2250 	request->transfer_flag = transfer_flag;
2251 	request->comp_classification = htole16(comp_classification);
2252 	request->comp_identifier = htole16(comp_identifier);
2253 	request->comp_classification_index = comp_classification_index;
2254 	request->comp_comparison_stamp = htole32(comp_comparison_stamp);
2255 	request->comp_ver_str_type = comp_ver_str_type;
2256 	request->comp_ver_str_len = comp_ver_str_len;
2257 
2258 	memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req),
2259 	       comp_ver_str->ptr, comp_ver_str->length);
2260 
2261 	return PLDM_SUCCESS;
2262 }
2263 
2264 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)2265 int decode_pass_component_table_req(
2266 	const struct pldm_msg *msg, size_t payload_length,
2267 	struct pldm_pass_component_table_req_full *pcomp)
2268 {
2269 	int rc;
2270 	uint8_t t;
2271 	PLDM_MSGBUF_RO_DEFINE_P(buf);
2272 
2273 	if (msg == NULL || pcomp == NULL) {
2274 		return -EINVAL;
2275 	}
2276 
2277 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
2278 	if (rc) {
2279 		return rc;
2280 	}
2281 
2282 	pldm_msgbuf_extract(buf, pcomp->transfer_flag);
2283 	pldm_msgbuf_extract(buf, pcomp->comp_classification);
2284 	pldm_msgbuf_extract(buf, pcomp->comp_identifier);
2285 	pldm_msgbuf_extract(buf, pcomp->comp_classification_index);
2286 	pldm_msgbuf_extract(buf, pcomp->comp_comparison_stamp);
2287 	rc = pldm_msgbuf_extract(buf, t);
2288 	if (rc) {
2289 		return pldm_msgbuf_discard(buf, rc);
2290 	}
2291 	if (t > PLDM_STR_TYPE_UTF_16BE) {
2292 		return pldm_msgbuf_discard(buf, -EBADMSG);
2293 	}
2294 	pcomp->version.str_type = (enum pldm_firmware_update_string_type)t;
2295 	rc = pldm_msgbuf_extract(buf, pcomp->version.str_len);
2296 	if (rc) {
2297 		return pldm_msgbuf_discard(buf, rc);
2298 	}
2299 	rc = pldm_msgbuf_extract_array(buf, pcomp->version.str_len,
2300 				       pcomp->version.str_data,
2301 				       PLDM_FIRMWARE_MAX_STRING);
2302 	if (rc) {
2303 		return pldm_msgbuf_discard(buf, rc);
2304 	}
2305 
2306 	return pldm_msgbuf_complete_consumed(buf);
2307 }
2308 
2309 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)2310 int decode_pass_component_table_resp(const struct pldm_msg *msg,
2311 				     const size_t payload_length,
2312 				     uint8_t *completion_code,
2313 				     uint8_t *comp_resp,
2314 				     uint8_t *comp_resp_code)
2315 {
2316 	if (msg == NULL || completion_code == NULL || comp_resp == NULL ||
2317 	    comp_resp_code == NULL || !payload_length) {
2318 		return PLDM_ERROR_INVALID_DATA;
2319 	}
2320 
2321 	*completion_code = msg->payload[0];
2322 	if (*completion_code != PLDM_SUCCESS) {
2323 		return PLDM_SUCCESS;
2324 	}
2325 
2326 	if (payload_length != sizeof(struct pldm_pass_component_table_resp)) {
2327 		return PLDM_ERROR_INVALID_LENGTH;
2328 	}
2329 
2330 	struct pldm_pass_component_table_resp *response =
2331 		(struct pldm_pass_component_table_resp *)msg->payload;
2332 
2333 	if (!is_comp_resp_valid(response->comp_resp)) {
2334 		return PLDM_ERROR_INVALID_DATA;
2335 	}
2336 
2337 	if (!is_comp_resp_code_valid(response->comp_resp_code)) {
2338 		return PLDM_ERROR_INVALID_DATA;
2339 	}
2340 
2341 	*comp_resp = response->comp_resp;
2342 	*comp_resp_code = response->comp_resp_code;
2343 
2344 	return PLDM_SUCCESS;
2345 }
2346 
2347 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)2348 int encode_pass_component_table_resp(
2349 	uint8_t instance_id,
2350 	const struct pldm_pass_component_table_resp *resp_data,
2351 	struct pldm_msg *msg, size_t *payload_length)
2352 {
2353 	PLDM_MSGBUF_RW_DEFINE_P(buf);
2354 	int rc;
2355 
2356 	if (msg == NULL || payload_length == NULL) {
2357 		return -EINVAL;
2358 	}
2359 
2360 	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2361 				     PLDM_PASS_COMPONENT_TABLE, msg);
2362 	if (rc) {
2363 		return -EINVAL;
2364 	}
2365 
2366 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2367 	if (rc) {
2368 		return rc;
2369 	}
2370 
2371 	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2372 	pldm_msgbuf_insert(buf, resp_data->comp_resp);
2373 	pldm_msgbuf_insert(buf, resp_data->comp_resp_code);
2374 
2375 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2376 }
2377 
2378 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)2379 int encode_update_component_req(
2380 	uint8_t instance_id, uint16_t comp_classification,
2381 	uint16_t comp_identifier, uint8_t comp_classification_index,
2382 	uint32_t comp_comparison_stamp, uint32_t comp_image_size,
2383 	bitfield32_t update_option_flags, uint8_t comp_ver_str_type,
2384 	uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str,
2385 	struct pldm_msg *msg, size_t payload_length)
2386 {
2387 	if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) {
2388 		return PLDM_ERROR_INVALID_DATA;
2389 	}
2390 
2391 	if (payload_length !=
2392 	    sizeof(struct pldm_update_component_req) + comp_ver_str->length) {
2393 		return PLDM_ERROR_INVALID_LENGTH;
2394 	}
2395 
2396 	if (!comp_image_size) {
2397 		return PLDM_ERROR_INVALID_DATA;
2398 	}
2399 
2400 	if ((comp_ver_str_len == 0) ||
2401 	    (comp_ver_str_len != comp_ver_str->length)) {
2402 		return PLDM_ERROR_INVALID_DATA;
2403 	}
2404 
2405 	if (!is_string_type_valid(comp_ver_str_type)) {
2406 		return PLDM_ERROR_INVALID_DATA;
2407 	}
2408 
2409 	struct pldm_header_info header = { 0 };
2410 	header.instance = instance_id;
2411 	header.msg_type = PLDM_REQUEST;
2412 	header.pldm_type = PLDM_FWUP;
2413 	header.command = PLDM_UPDATE_COMPONENT;
2414 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2415 	if (rc) {
2416 		return rc;
2417 	}
2418 
2419 	struct pldm_update_component_req *request =
2420 		(struct pldm_update_component_req *)msg->payload;
2421 
2422 	request->comp_classification = htole16(comp_classification);
2423 	request->comp_identifier = htole16(comp_identifier);
2424 	request->comp_classification_index = comp_classification_index;
2425 	request->comp_comparison_stamp = htole32(comp_comparison_stamp);
2426 	request->comp_image_size = htole32(comp_image_size);
2427 	request->update_option_flags.value = htole32(update_option_flags.value);
2428 	request->comp_ver_str_type = comp_ver_str_type;
2429 	request->comp_ver_str_len = comp_ver_str_len;
2430 
2431 	memcpy(msg->payload + sizeof(struct pldm_update_component_req),
2432 	       comp_ver_str->ptr, comp_ver_str->length);
2433 
2434 	return PLDM_SUCCESS;
2435 }
2436 
2437 LIBPLDM_ABI_TESTING
decode_update_component_req(const struct pldm_msg * msg,size_t payload_length,struct pldm_update_component_req_full * up)2438 int decode_update_component_req(const struct pldm_msg *msg,
2439 				size_t payload_length,
2440 				struct pldm_update_component_req_full *up)
2441 {
2442 	int rc;
2443 	uint8_t t;
2444 	PLDM_MSGBUF_RO_DEFINE_P(buf);
2445 
2446 	if (msg == NULL || up == NULL) {
2447 		return -EINVAL;
2448 	}
2449 
2450 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
2451 	if (rc) {
2452 		return rc;
2453 	}
2454 
2455 	pldm_msgbuf_extract(buf, up->comp_classification);
2456 	pldm_msgbuf_extract(buf, up->comp_identifier);
2457 	pldm_msgbuf_extract(buf, up->comp_classification_index);
2458 	pldm_msgbuf_extract(buf, up->comp_comparison_stamp);
2459 	pldm_msgbuf_extract(buf, up->comp_image_size);
2460 	pldm_msgbuf_extract(buf, up->update_option_flags.value);
2461 	rc = pldm_msgbuf_extract(buf, t);
2462 	if (rc) {
2463 		return pldm_msgbuf_discard(buf, rc);
2464 	}
2465 	if (t > PLDM_STR_TYPE_UTF_16BE) {
2466 		return pldm_msgbuf_discard(buf, -EBADMSG);
2467 	}
2468 	up->version.str_type = (enum pldm_firmware_update_string_type)t;
2469 	rc = pldm_msgbuf_extract(buf, up->version.str_len);
2470 	if (rc) {
2471 		return pldm_msgbuf_discard(buf, rc);
2472 	}
2473 	rc = pldm_msgbuf_extract_array(buf, up->version.str_len,
2474 				       up->version.str_data,
2475 				       PLDM_FIRMWARE_MAX_STRING);
2476 	if (rc) {
2477 		return pldm_msgbuf_discard(buf, rc);
2478 	}
2479 
2480 	return pldm_msgbuf_complete_consumed(buf);
2481 }
2482 
2483 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)2484 int decode_update_component_resp(const struct pldm_msg *msg,
2485 				 size_t payload_length,
2486 				 uint8_t *completion_code,
2487 				 uint8_t *comp_compatibility_resp,
2488 				 uint8_t *comp_compatibility_resp_code,
2489 				 bitfield32_t *update_option_flags_enabled,
2490 				 uint16_t *time_before_req_fw_data)
2491 {
2492 	if (msg == NULL || completion_code == NULL ||
2493 	    comp_compatibility_resp == NULL ||
2494 	    comp_compatibility_resp_code == NULL ||
2495 	    update_option_flags_enabled == NULL ||
2496 	    time_before_req_fw_data == NULL || !payload_length) {
2497 		return PLDM_ERROR_INVALID_DATA;
2498 	}
2499 
2500 	*completion_code = msg->payload[0];
2501 	if (*completion_code != PLDM_SUCCESS) {
2502 		return PLDM_SUCCESS;
2503 	}
2504 
2505 	if (payload_length != sizeof(struct pldm_update_component_resp)) {
2506 		return PLDM_ERROR_INVALID_LENGTH;
2507 	}
2508 
2509 	struct pldm_update_component_resp *response =
2510 		(struct pldm_update_component_resp *)msg->payload;
2511 
2512 	if (!is_comp_compatibility_resp_valid(
2513 		    response->comp_compatibility_resp)) {
2514 		return PLDM_ERROR_INVALID_DATA;
2515 	}
2516 
2517 	if (!is_comp_compatibility_resp_code_valid(
2518 		    response->comp_compatibility_resp_code)) {
2519 		return PLDM_ERROR_INVALID_DATA;
2520 	}
2521 
2522 	*comp_compatibility_resp = response->comp_compatibility_resp;
2523 	*comp_compatibility_resp_code = response->comp_compatibility_resp_code;
2524 	update_option_flags_enabled->value =
2525 		le32toh(response->update_option_flags_enabled.value);
2526 	*time_before_req_fw_data = le16toh(response->time_before_req_fw_data);
2527 
2528 	return PLDM_SUCCESS;
2529 }
2530 
2531 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)2532 int encode_update_component_resp(
2533 	uint8_t instance_id, const struct pldm_update_component_resp *resp_data,
2534 	struct pldm_msg *msg, size_t *payload_length)
2535 {
2536 	PLDM_MSGBUF_RW_DEFINE_P(buf);
2537 	int rc;
2538 
2539 	if (msg == NULL || payload_length == NULL) {
2540 		return -EINVAL;
2541 	}
2542 
2543 	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2544 				     PLDM_UPDATE_COMPONENT, msg);
2545 	if (rc) {
2546 		return -EINVAL;
2547 	}
2548 
2549 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2550 	if (rc) {
2551 		return rc;
2552 	}
2553 
2554 	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2555 	pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp);
2556 	pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp_code);
2557 	pldm_msgbuf_insert(buf, resp_data->update_option_flags_enabled.value);
2558 	pldm_msgbuf_insert(buf, resp_data->time_before_req_fw_data);
2559 
2560 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2561 }
2562 
2563 LIBPLDM_ABI_STABLE
decode_request_firmware_data_req(const struct pldm_msg * msg,size_t payload_length,uint32_t * offset,uint32_t * length)2564 int decode_request_firmware_data_req(const struct pldm_msg *msg,
2565 				     size_t payload_length, uint32_t *offset,
2566 				     uint32_t *length)
2567 {
2568 	if (msg == NULL || offset == NULL || length == NULL) {
2569 		return PLDM_ERROR_INVALID_DATA;
2570 	}
2571 	if (payload_length != sizeof(struct pldm_request_firmware_data_req)) {
2572 		return PLDM_ERROR_INVALID_LENGTH;
2573 	}
2574 	struct pldm_request_firmware_data_req *request =
2575 		(struct pldm_request_firmware_data_req *)msg->payload;
2576 	*offset = le32toh(request->offset);
2577 	*length = le32toh(request->length);
2578 
2579 	if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) {
2580 		return PLDM_FWUP_INVALID_TRANSFER_LENGTH;
2581 	}
2582 
2583 	return PLDM_SUCCESS;
2584 }
2585 
2586 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)2587 int encode_request_firmware_data_req(
2588 	uint8_t instance_id,
2589 	const struct pldm_request_firmware_data_req *req_params,
2590 	struct pldm_msg *msg, size_t *payload_length)
2591 {
2592 	PLDM_MSGBUF_RW_DEFINE_P(buf);
2593 	int rc;
2594 
2595 	if (msg == NULL || payload_length == NULL) {
2596 		return -EINVAL;
2597 	}
2598 
2599 	rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2600 				     PLDM_REQUEST_FIRMWARE_DATA, msg);
2601 	if (rc) {
2602 		return -EINVAL;
2603 	}
2604 
2605 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2606 	if (rc) {
2607 		return rc;
2608 	}
2609 
2610 	pldm_msgbuf_insert(buf, req_params->offset);
2611 	pldm_msgbuf_insert(buf, req_params->length);
2612 
2613 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2614 }
2615 
2616 LIBPLDM_ABI_STABLE
encode_request_firmware_data_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2617 int encode_request_firmware_data_resp(uint8_t instance_id,
2618 				      uint8_t completion_code,
2619 				      struct pldm_msg *msg,
2620 				      size_t payload_length)
2621 {
2622 	if (msg == NULL || !payload_length) {
2623 		return PLDM_ERROR_INVALID_DATA;
2624 	}
2625 
2626 	struct pldm_header_info header = { 0 };
2627 	header.instance = instance_id;
2628 	header.msg_type = PLDM_RESPONSE;
2629 	header.pldm_type = PLDM_FWUP;
2630 	header.command = PLDM_REQUEST_FIRMWARE_DATA;
2631 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2632 	if (rc) {
2633 		return rc;
2634 	}
2635 
2636 	msg->payload[0] = completion_code;
2637 
2638 	return PLDM_SUCCESS;
2639 }
2640 
2641 LIBPLDM_ABI_STABLE
decode_transfer_complete_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * transfer_result)2642 int decode_transfer_complete_req(const struct pldm_msg *msg,
2643 				 size_t payload_length,
2644 				 uint8_t *transfer_result)
2645 {
2646 	if (msg == NULL || transfer_result == NULL) {
2647 		return PLDM_ERROR_INVALID_DATA;
2648 	}
2649 
2650 	if (payload_length != sizeof(*transfer_result)) {
2651 		return PLDM_ERROR_INVALID_LENGTH;
2652 	}
2653 
2654 	*transfer_result = msg->payload[0];
2655 	return PLDM_SUCCESS;
2656 }
2657 
2658 LIBPLDM_ABI_TESTING
encode_transfer_complete_req(uint8_t instance_id,uint8_t transfer_result,struct pldm_msg * msg,size_t * payload_length)2659 int encode_transfer_complete_req(uint8_t instance_id, uint8_t transfer_result,
2660 				 struct pldm_msg *msg, size_t *payload_length)
2661 {
2662 	PLDM_MSGBUF_RW_DEFINE_P(buf);
2663 	int rc;
2664 
2665 	if (msg == NULL || payload_length == NULL) {
2666 		return -EINVAL;
2667 	}
2668 
2669 	rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2670 				     PLDM_TRANSFER_COMPLETE, msg);
2671 	if (rc) {
2672 		return -EINVAL;
2673 	}
2674 
2675 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2676 	if (rc) {
2677 		return rc;
2678 	}
2679 
2680 	pldm_msgbuf_insert(buf, transfer_result);
2681 
2682 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2683 }
2684 
2685 LIBPLDM_ABI_STABLE
encode_transfer_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2686 int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code,
2687 				  struct pldm_msg *msg, size_t payload_length)
2688 {
2689 	if (msg == NULL) {
2690 		return PLDM_ERROR_INVALID_DATA;
2691 	}
2692 
2693 	if (payload_length != sizeof(completion_code)) {
2694 		return PLDM_ERROR_INVALID_LENGTH;
2695 	}
2696 
2697 	struct pldm_header_info header = { 0 };
2698 	header.instance = instance_id;
2699 	header.msg_type = PLDM_RESPONSE;
2700 	header.pldm_type = PLDM_FWUP;
2701 	header.command = PLDM_TRANSFER_COMPLETE;
2702 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2703 	if (rc) {
2704 		return rc;
2705 	}
2706 
2707 	msg->payload[0] = completion_code;
2708 
2709 	return PLDM_SUCCESS;
2710 }
2711 
2712 LIBPLDM_ABI_STABLE
decode_verify_complete_req(const struct pldm_msg * msg,size_t payload_length,uint8_t * verify_result)2713 int decode_verify_complete_req(const struct pldm_msg *msg,
2714 			       size_t payload_length, uint8_t *verify_result)
2715 {
2716 	if (msg == NULL || verify_result == NULL) {
2717 		return PLDM_ERROR_INVALID_DATA;
2718 	}
2719 
2720 	if (payload_length != sizeof(*verify_result)) {
2721 		return PLDM_ERROR_INVALID_LENGTH;
2722 	}
2723 
2724 	*verify_result = msg->payload[0];
2725 	return PLDM_SUCCESS;
2726 }
2727 
2728 LIBPLDM_ABI_TESTING
encode_verify_complete_req(uint8_t instance_id,uint8_t verify_result,struct pldm_msg * msg,size_t * payload_length)2729 int encode_verify_complete_req(uint8_t instance_id, uint8_t verify_result,
2730 			       struct pldm_msg *msg, size_t *payload_length)
2731 {
2732 	PLDM_MSGBUF_RW_DEFINE_P(buf);
2733 	int rc;
2734 
2735 	if (msg == NULL || payload_length == NULL) {
2736 		return -EINVAL;
2737 	}
2738 
2739 	rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2740 				     PLDM_VERIFY_COMPLETE, msg);
2741 	if (rc) {
2742 		return EINVAL;
2743 	}
2744 
2745 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2746 	if (rc) {
2747 		return rc;
2748 	}
2749 
2750 	pldm_msgbuf_insert(buf, verify_result);
2751 
2752 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2753 }
2754 
2755 LIBPLDM_ABI_STABLE
encode_verify_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2756 int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code,
2757 				struct pldm_msg *msg, size_t payload_length)
2758 {
2759 	if (msg == NULL) {
2760 		return PLDM_ERROR_INVALID_DATA;
2761 	}
2762 
2763 	if (payload_length != sizeof(completion_code)) {
2764 		return PLDM_ERROR_INVALID_LENGTH;
2765 	}
2766 
2767 	struct pldm_header_info header = { 0 };
2768 	header.instance = instance_id;
2769 	header.msg_type = PLDM_RESPONSE;
2770 	header.pldm_type = PLDM_FWUP;
2771 	header.command = PLDM_VERIFY_COMPLETE;
2772 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2773 	if (rc) {
2774 		return rc;
2775 	}
2776 
2777 	msg->payload[0] = completion_code;
2778 
2779 	return PLDM_SUCCESS;
2780 }
2781 
2782 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)2783 int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length,
2784 			      uint8_t *apply_result,
2785 			      bitfield16_t *comp_activation_methods_modification)
2786 {
2787 	if (msg == NULL || apply_result == NULL ||
2788 	    comp_activation_methods_modification == NULL) {
2789 		return PLDM_ERROR_INVALID_DATA;
2790 	}
2791 
2792 	if (payload_length != sizeof(struct pldm_apply_complete_req)) {
2793 		return PLDM_ERROR_INVALID_LENGTH;
2794 	}
2795 
2796 	struct pldm_apply_complete_req *request =
2797 		(struct pldm_apply_complete_req *)msg->payload;
2798 
2799 	*apply_result = request->apply_result;
2800 	comp_activation_methods_modification->value =
2801 		le16toh(request->comp_activation_methods_modification.value);
2802 
2803 	if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) &&
2804 	    comp_activation_methods_modification->value) {
2805 		return PLDM_ERROR_INVALID_DATA;
2806 	}
2807 
2808 	return PLDM_SUCCESS;
2809 }
2810 
2811 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)2812 int encode_apply_complete_req(uint8_t instance_id,
2813 			      const struct pldm_apply_complete_req *req_data,
2814 			      struct pldm_msg *msg, size_t *payload_length)
2815 {
2816 	PLDM_MSGBUF_RW_DEFINE_P(buf);
2817 	int rc;
2818 
2819 	if (msg == NULL || payload_length == NULL) {
2820 		return -EINVAL;
2821 	}
2822 
2823 	rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP,
2824 				     PLDM_APPLY_COMPLETE, msg);
2825 	if (rc) {
2826 		return -EINVAL;
2827 	}
2828 
2829 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2830 	if (rc) {
2831 		return rc;
2832 	}
2833 
2834 	pldm_msgbuf_insert(buf, req_data->apply_result);
2835 	pldm_msgbuf_insert(
2836 		buf, req_data->comp_activation_methods_modification.value);
2837 
2838 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2839 }
2840 
2841 LIBPLDM_ABI_STABLE
encode_apply_complete_resp(uint8_t instance_id,uint8_t completion_code,struct pldm_msg * msg,size_t payload_length)2842 int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code,
2843 			       struct pldm_msg *msg, size_t payload_length)
2844 {
2845 	if (msg == NULL) {
2846 		return PLDM_ERROR_INVALID_DATA;
2847 	}
2848 
2849 	if (payload_length != sizeof(completion_code)) {
2850 		return PLDM_ERROR_INVALID_LENGTH;
2851 	}
2852 
2853 	struct pldm_header_info header = { 0 };
2854 	header.instance = instance_id;
2855 	header.msg_type = PLDM_RESPONSE;
2856 	header.pldm_type = PLDM_FWUP;
2857 	header.command = PLDM_APPLY_COMPLETE;
2858 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2859 	if (rc) {
2860 		return rc;
2861 	}
2862 
2863 	msg->payload[0] = completion_code;
2864 
2865 	return PLDM_SUCCESS;
2866 }
2867 
2868 LIBPLDM_ABI_TESTING
decode_activate_firmware_req(const struct pldm_msg * msg,size_t payload_length,bool * self_contained)2869 int decode_activate_firmware_req(const struct pldm_msg *msg,
2870 				 size_t payload_length, bool *self_contained)
2871 {
2872 	uint8_t self_contained_u8 = 0;
2873 	PLDM_MSGBUF_RO_DEFINE_P(buf);
2874 	int rc;
2875 
2876 	if (msg == NULL || self_contained == NULL) {
2877 		return -EINVAL;
2878 	}
2879 
2880 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length);
2881 	if (rc) {
2882 		return 0;
2883 	}
2884 
2885 	pldm_msgbuf_extract(buf, self_contained_u8);
2886 
2887 	rc = pldm_msgbuf_complete_consumed(buf);
2888 	if (rc) {
2889 		return rc;
2890 	}
2891 
2892 	*self_contained = (bool)self_contained_u8;
2893 	return 0;
2894 }
2895 
2896 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)2897 int encode_activate_firmware_req(uint8_t instance_id,
2898 				 bool8_t self_contained_activation_req,
2899 				 struct pldm_msg *msg, size_t payload_length)
2900 {
2901 	if (msg == NULL) {
2902 		return PLDM_ERROR_INVALID_DATA;
2903 	}
2904 
2905 	if (payload_length != sizeof(struct pldm_activate_firmware_req)) {
2906 		return PLDM_ERROR_INVALID_LENGTH;
2907 	}
2908 
2909 	if (!is_self_contained_activation_req_valid(
2910 		    self_contained_activation_req)) {
2911 		return PLDM_ERROR_INVALID_DATA;
2912 	}
2913 
2914 	struct pldm_header_info header = { 0 };
2915 	header.instance = instance_id;
2916 	header.msg_type = PLDM_REQUEST;
2917 	header.pldm_type = PLDM_FWUP;
2918 	header.command = PLDM_ACTIVATE_FIRMWARE;
2919 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
2920 	if (rc) {
2921 		return rc;
2922 	}
2923 
2924 	struct pldm_activate_firmware_req *request =
2925 		(struct pldm_activate_firmware_req *)msg->payload;
2926 
2927 	request->self_contained_activation_req = self_contained_activation_req;
2928 
2929 	return PLDM_SUCCESS;
2930 }
2931 
2932 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)2933 int decode_activate_firmware_resp(const struct pldm_msg *msg,
2934 				  size_t payload_length,
2935 				  uint8_t *completion_code,
2936 				  uint16_t *estimated_time_activation)
2937 {
2938 	if (msg == NULL || completion_code == NULL ||
2939 	    estimated_time_activation == NULL || !payload_length) {
2940 		return PLDM_ERROR_INVALID_DATA;
2941 	}
2942 
2943 	*completion_code = msg->payload[0];
2944 	if (*completion_code != PLDM_SUCCESS) {
2945 		return PLDM_SUCCESS;
2946 	}
2947 
2948 	if (payload_length != sizeof(struct pldm_activate_firmware_resp)) {
2949 		return PLDM_ERROR_INVALID_LENGTH;
2950 	}
2951 
2952 	struct pldm_activate_firmware_resp *response =
2953 		(struct pldm_activate_firmware_resp *)msg->payload;
2954 
2955 	*estimated_time_activation =
2956 		le16toh(response->estimated_time_activation);
2957 
2958 	return PLDM_SUCCESS;
2959 }
2960 
2961 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)2962 int encode_activate_firmware_resp(
2963 	uint8_t instance_id,
2964 	const struct pldm_activate_firmware_resp *resp_data,
2965 	struct pldm_msg *msg, size_t *payload_length)
2966 {
2967 	PLDM_MSGBUF_RW_DEFINE_P(buf);
2968 	int rc;
2969 
2970 	if (msg == NULL || payload_length == NULL) {
2971 		return -EINVAL;
2972 	}
2973 
2974 	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
2975 				     PLDM_ACTIVATE_FIRMWARE, msg);
2976 	if (rc) {
2977 		return -EINVAL;
2978 	}
2979 
2980 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
2981 	if (rc) {
2982 		return rc;
2983 	}
2984 
2985 	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
2986 	pldm_msgbuf_insert(buf, resp_data->estimated_time_activation);
2987 
2988 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
2989 }
2990 
2991 LIBPLDM_ABI_STABLE
encode_get_status_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)2992 int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg,
2993 			  size_t payload_length)
2994 {
2995 	if (msg == NULL) {
2996 		return PLDM_ERROR_INVALID_DATA;
2997 	}
2998 
2999 	if (payload_length != PLDM_GET_STATUS_REQ_BYTES) {
3000 		return PLDM_ERROR_INVALID_LENGTH;
3001 	}
3002 
3003 	struct pldm_header_info header = { 0 };
3004 	header.instance = instance_id;
3005 	header.msg_type = PLDM_REQUEST;
3006 	header.pldm_type = PLDM_FWUP;
3007 	header.command = PLDM_GET_STATUS;
3008 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
3009 	if (rc) {
3010 		return rc;
3011 	}
3012 
3013 	return PLDM_SUCCESS;
3014 }
3015 
3016 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)3017 int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length,
3018 			   uint8_t *completion_code, uint8_t *current_state,
3019 			   uint8_t *previous_state, uint8_t *aux_state,
3020 			   uint8_t *aux_state_status, uint8_t *progress_percent,
3021 			   uint8_t *reason_code,
3022 			   bitfield32_t *update_option_flags_enabled)
3023 {
3024 	if (msg == NULL || completion_code == NULL || current_state == NULL ||
3025 	    previous_state == NULL || aux_state == NULL ||
3026 	    aux_state_status == NULL || progress_percent == NULL ||
3027 	    reason_code == NULL || update_option_flags_enabled == NULL ||
3028 	    !payload_length) {
3029 		return PLDM_ERROR_INVALID_DATA;
3030 	}
3031 
3032 	*completion_code = msg->payload[0];
3033 	if (*completion_code != PLDM_SUCCESS) {
3034 		return PLDM_SUCCESS;
3035 	}
3036 
3037 	if (payload_length != sizeof(struct pldm_get_status_resp)) {
3038 		return PLDM_ERROR_INVALID_LENGTH;
3039 	}
3040 	struct pldm_get_status_resp *response =
3041 		(struct pldm_get_status_resp *)msg->payload;
3042 
3043 	if (!is_state_valid(response->current_state)) {
3044 		return PLDM_ERROR_INVALID_DATA;
3045 	}
3046 	if (!is_state_valid(response->previous_state)) {
3047 		return PLDM_ERROR_INVALID_DATA;
3048 	}
3049 	if (!is_aux_state_valid(response->aux_state)) {
3050 		return PLDM_ERROR_INVALID_DATA;
3051 	}
3052 	if (!is_aux_state_status_valid(response->aux_state_status)) {
3053 		return PLDM_ERROR_INVALID_DATA;
3054 	}
3055 	if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) {
3056 		return PLDM_ERROR_INVALID_DATA;
3057 	}
3058 	if (!is_reason_code_valid(response->reason_code)) {
3059 		return PLDM_ERROR_INVALID_DATA;
3060 	}
3061 
3062 	if ((response->current_state == PLDM_FD_STATE_IDLE) ||
3063 	    (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) ||
3064 	    (response->current_state == PLDM_FD_STATE_READY_XFER)) {
3065 		if (response->aux_state !=
3066 		    PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) {
3067 			return PLDM_ERROR_INVALID_DATA;
3068 		}
3069 	}
3070 
3071 	*current_state = response->current_state;
3072 	*previous_state = response->previous_state;
3073 	*aux_state = response->aux_state;
3074 	*aux_state_status = response->aux_state_status;
3075 	*progress_percent = response->progress_percent;
3076 	*reason_code = response->reason_code;
3077 	update_option_flags_enabled->value =
3078 		le32toh(response->update_option_flags_enabled.value);
3079 
3080 	return PLDM_SUCCESS;
3081 }
3082 
3083 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)3084 int encode_get_status_resp(uint8_t instance_id,
3085 			   const struct pldm_get_status_resp *status,
3086 			   struct pldm_msg *msg, size_t *payload_length)
3087 {
3088 	PLDM_MSGBUF_RW_DEFINE_P(buf);
3089 	int rc;
3090 
3091 	if (status == NULL || msg == NULL || payload_length == NULL) {
3092 		return -EINVAL;
3093 	}
3094 
3095 	if (status->completion_code != PLDM_SUCCESS) {
3096 		return -EINVAL;
3097 	}
3098 
3099 	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
3100 				     PLDM_GET_STATUS, msg);
3101 	if (rc) {
3102 		return -EINVAL;
3103 	}
3104 
3105 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
3106 	if (rc) {
3107 		return rc;
3108 	}
3109 
3110 	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
3111 	pldm_msgbuf_insert(buf, status->current_state);
3112 	pldm_msgbuf_insert(buf, status->previous_state);
3113 	pldm_msgbuf_insert(buf, status->aux_state);
3114 	pldm_msgbuf_insert(buf, status->aux_state_status);
3115 	pldm_msgbuf_insert(buf, status->progress_percent);
3116 	pldm_msgbuf_insert(buf, status->reason_code);
3117 	pldm_msgbuf_insert(buf, status->update_option_flags_enabled.value);
3118 
3119 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
3120 }
3121 
3122 LIBPLDM_ABI_STABLE
encode_cancel_update_component_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)3123 int encode_cancel_update_component_req(uint8_t instance_id,
3124 				       struct pldm_msg *msg,
3125 				       size_t payload_length)
3126 {
3127 	if (msg == NULL) {
3128 		return PLDM_ERROR_INVALID_DATA;
3129 	}
3130 
3131 	if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) {
3132 		return PLDM_ERROR_INVALID_LENGTH;
3133 	}
3134 
3135 	struct pldm_header_info header = { 0 };
3136 	header.instance = instance_id;
3137 	header.msg_type = PLDM_REQUEST;
3138 	header.pldm_type = PLDM_FWUP;
3139 	header.command = PLDM_CANCEL_UPDATE_COMPONENT;
3140 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
3141 	if (rc) {
3142 		return rc;
3143 	}
3144 
3145 	return PLDM_SUCCESS;
3146 }
3147 
3148 LIBPLDM_ABI_STABLE
decode_cancel_update_component_resp(const struct pldm_msg * msg,size_t payload_length,uint8_t * completion_code)3149 int decode_cancel_update_component_resp(const struct pldm_msg *msg,
3150 					size_t payload_length,
3151 					uint8_t *completion_code)
3152 {
3153 	if (msg == NULL || completion_code == NULL) {
3154 		return PLDM_ERROR_INVALID_DATA;
3155 	}
3156 
3157 	if (payload_length != sizeof(*completion_code)) {
3158 		return PLDM_ERROR_INVALID_LENGTH;
3159 	}
3160 
3161 	*completion_code = msg->payload[0];
3162 	return PLDM_SUCCESS;
3163 }
3164 
3165 LIBPLDM_ABI_STABLE
encode_cancel_update_req(uint8_t instance_id,struct pldm_msg * msg,size_t payload_length)3166 int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg,
3167 			     size_t payload_length)
3168 {
3169 	if (msg == NULL) {
3170 		return PLDM_ERROR_INVALID_DATA;
3171 	}
3172 
3173 	if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) {
3174 		return PLDM_ERROR_INVALID_LENGTH;
3175 	}
3176 
3177 	struct pldm_header_info header = { 0 };
3178 	header.instance = instance_id;
3179 	header.msg_type = PLDM_REQUEST;
3180 	header.pldm_type = PLDM_FWUP;
3181 	header.command = PLDM_CANCEL_UPDATE;
3182 	uint8_t rc = pack_pldm_header(&header, &(msg->hdr));
3183 	if (rc) {
3184 		return rc;
3185 	}
3186 
3187 	return PLDM_SUCCESS;
3188 }
3189 
3190 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)3191 int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length,
3192 			      uint8_t *completion_code,
3193 			      bool8_t *non_functioning_component_indication,
3194 			      bitfield64_t *non_functioning_component_bitmap)
3195 {
3196 	if (msg == NULL || completion_code == NULL ||
3197 	    non_functioning_component_indication == NULL ||
3198 	    non_functioning_component_bitmap == NULL || !payload_length) {
3199 		return PLDM_ERROR_INVALID_DATA;
3200 	}
3201 
3202 	*completion_code = msg->payload[0];
3203 	if (*completion_code != PLDM_SUCCESS) {
3204 		return PLDM_SUCCESS;
3205 	}
3206 
3207 	if (payload_length != sizeof(struct pldm_cancel_update_resp)) {
3208 		return PLDM_ERROR_INVALID_LENGTH;
3209 	}
3210 	struct pldm_cancel_update_resp *response =
3211 		(struct pldm_cancel_update_resp *)msg->payload;
3212 
3213 	if (!is_non_functioning_component_indication_valid(
3214 		    response->non_functioning_component_indication)) {
3215 		return PLDM_ERROR_INVALID_DATA;
3216 	}
3217 
3218 	*non_functioning_component_indication =
3219 		response->non_functioning_component_indication;
3220 
3221 	if (*non_functioning_component_indication) {
3222 		non_functioning_component_bitmap->value =
3223 			le64toh(response->non_functioning_component_bitmap);
3224 	}
3225 
3226 	return PLDM_SUCCESS;
3227 }
3228 
3229 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)3230 int encode_cancel_update_resp(uint8_t instance_id,
3231 			      const struct pldm_cancel_update_resp *resp_data,
3232 			      struct pldm_msg *msg, size_t *payload_length)
3233 {
3234 	PLDM_MSGBUF_RW_DEFINE_P(buf);
3235 	int rc;
3236 
3237 	if (msg == NULL || payload_length == NULL) {
3238 		return -EINVAL;
3239 	}
3240 
3241 	rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP,
3242 				     PLDM_CANCEL_UPDATE, msg);
3243 	if (rc) {
3244 		return -EINVAL;
3245 	}
3246 
3247 	rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length);
3248 	if (rc) {
3249 		return rc;
3250 	}
3251 
3252 	pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS);
3253 	pldm_msgbuf_insert(buf,
3254 			   resp_data->non_functioning_component_indication);
3255 	pldm_msgbuf_insert(buf, resp_data->non_functioning_component_bitmap);
3256 
3257 	return pldm_msgbuf_complete_used(buf, *payload_length, payload_length);
3258 }
3259 
3260 LIBPLDM_ABI_STABLE
decode_pldm_firmware_update_package(const void * data,size_t length,const struct pldm_package_format_pin * pin,pldm_package_header_information_pad * hdr,struct pldm_package * pkg,uint32_t flags)3261 int decode_pldm_firmware_update_package(
3262 	const void *data, size_t length,
3263 	const struct pldm_package_format_pin *pin,
3264 	pldm_package_header_information_pad *hdr, struct pldm_package *pkg,
3265 	uint32_t flags)
3266 {
3267 	if (!data || !pin || !hdr || !pkg) {
3268 		return -EINVAL;
3269 	}
3270 
3271 	if (flags) {
3272 		return -EINVAL;
3273 	}
3274 
3275 	return decode_pldm_package_header_info_errno(data, length, pin, hdr,
3276 						     pkg);
3277 }
3278 
3279 LIBPLDM_ABI_STABLE
pldm_package_firmware_device_id_record_iter_init(struct pldm_package * pkg)3280 int pldm_package_firmware_device_id_record_iter_init(struct pldm_package *pkg)
3281 {
3282 	struct pldm_package_iter *iter;
3283 	PLDM_MSGBUF_RO_DEFINE_P(buf);
3284 	int rc;
3285 
3286 	if (!pkg || !pkg->pin || !pkg->hdr) {
3287 		return -EINVAL;
3288 	}
3289 
3290 	assert(pkg->pin->format.revision >=
3291 	       PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H);
3292 	assert(pkg->pin->format.revision <=
3293 	       PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H);
3294 	assert(pkg->hdr->package_header_format_revision >=
3295 	       PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H);
3296 	assert(pkg->hdr->package_header_format_revision <=
3297 	       pkg->pin->format.revision);
3298 
3299 	if (pkg->state != PLDM_PACKAGE_PARSE_HEADER) {
3300 		return -EPROTO;
3301 	}
3302 
3303 	if (!pkg->areas.ptr) {
3304 		return -EINVAL;
3305 	}
3306 
3307 	pkg->state = PLDM_PACKAGE_PARSE_FIRMWARE_DEVICES;
3308 
3309 	iter = &pkg->iter;
3310 	iter->field = pkg->areas;
3311 
3312 	/* Extract the fd record id count */
3313 	rc = pldm_msgbuf_init_errno(buf, 1, iter->field.ptr,
3314 				    iter->field.length);
3315 	if (rc) {
3316 		return rc;
3317 	}
3318 
3319 	pldm_msgbuf_extract_uint8_to_size(buf, iter->entries);
3320 	pldm_msgbuf_span_remaining(buf, (const void **)&iter->field.ptr,
3321 				   &iter->field.length);
3322 
3323 	return pldm_msgbuf_complete(buf);
3324 }
3325 
3326 LIBPLDM_ABI_STABLE
decode_pldm_package_firmware_device_id_record_from_iter(struct pldm_package * pkg LIBPLDM_CC_UNUSED,struct pldm_package_firmware_device_id_record * rec)3327 int decode_pldm_package_firmware_device_id_record_from_iter(
3328 	struct pldm_package *pkg LIBPLDM_CC_UNUSED,
3329 	struct pldm_package_firmware_device_id_record *rec)
3330 {
3331 	if (!pkg) {
3332 		return -EINVAL;
3333 	}
3334 
3335 	if (pkg->state != PLDM_PACKAGE_PARSE_FIRMWARE_DEVICES) {
3336 		return -EPROTO;
3337 	}
3338 
3339 	return decode_pldm_package_firmware_device_id_record_errno(
3340 		pkg->hdr, &pkg->iter.field, rec);
3341 }
3342 
3343 LIBPLDM_ABI_STABLE
pldm_package_downstream_device_id_record_iter_init(struct pldm_package * pkg)3344 int pldm_package_downstream_device_id_record_iter_init(struct pldm_package *pkg)
3345 {
3346 	struct pldm_package_iter *iter;
3347 	PLDM_MSGBUF_RO_DEFINE_P(buf);
3348 	int rc;
3349 
3350 	if (!pkg || !pkg->pin || !pkg->hdr) {
3351 		return -EINVAL;
3352 	}
3353 
3354 	assert(pkg->pin->format.revision >=
3355 	       PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H);
3356 	assert(pkg->pin->format.revision <=
3357 	       PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H);
3358 	assert(pkg->hdr->package_header_format_revision >=
3359 	       PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H);
3360 	assert(pkg->hdr->package_header_format_revision <=
3361 	       pkg->pin->format.revision);
3362 
3363 	if (pkg->state != PLDM_PACKAGE_PARSE_FIRMWARE_DEVICES) {
3364 		return -EPROTO;
3365 	}
3366 
3367 	if (pkg->pin->format.revision ==
3368 	    PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H) {
3369 		return -EPROTO;
3370 	}
3371 
3372 	if (!pkg->iter.field.ptr) {
3373 		return -EINVAL;
3374 	}
3375 	iter = &pkg->iter;
3376 
3377 	pkg->state = PLDM_PACKAGE_PARSE_DOWNSTREAM_DEVICES;
3378 
3379 	/* Where:
3380 	 *
3381 	 * 1. The pin revision is greater than 1, and
3382 	 * 2. The package header format revision is 1
3383 	 *
3384 	 * We must account for the invocation of this function but present no downstream
3385    * devices, as they're not specified.
3386 	 */
3387 	if (pkg->hdr->package_header_format_revision ==
3388 	    PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H) {
3389 		iter->entries = 0;
3390 		return 0;
3391 	}
3392 
3393 	/* Extract the dd record id count */
3394 	rc = pldm_msgbuf_init_errno(buf, 1, iter->field.ptr,
3395 				    iter->field.length);
3396 	if (rc) {
3397 		return rc;
3398 	}
3399 
3400 	pldm_msgbuf_extract_uint8_to_size(buf, iter->entries);
3401 	pldm_msgbuf_span_remaining(buf, (const void **)&iter->field.ptr,
3402 				   &iter->field.length);
3403 
3404 	return pldm_msgbuf_complete(buf);
3405 }
3406 
3407 #define PLDM_FWUP_DOWNSTREAM_DEVICE_ID_RECORD_MIN_SIZE 11
3408 LIBPLDM_ABI_STABLE
decode_pldm_package_downstream_device_id_record_from_iter(struct pldm_package * pkg,struct pldm_package_downstream_device_id_record * rec)3409 int decode_pldm_package_downstream_device_id_record_from_iter(
3410 	struct pldm_package *pkg,
3411 	struct pldm_package_downstream_device_id_record *rec)
3412 {
3413 	struct pldm_package_iter *iter;
3414 	size_t package_data_offset;
3415 	PLDM_MSGBUF_RO_DEFINE_P(buf);
3416 	uint16_t record_len = 0;
3417 	int rc;
3418 
3419 	if (!pkg || !rec || !pkg->hdr) {
3420 		return -EINVAL;
3421 	}
3422 
3423 	if (pkg->state != PLDM_PACKAGE_PARSE_DOWNSTREAM_DEVICES) {
3424 		return -EPROTO;
3425 	}
3426 
3427 	assert(pkg->hdr->package_header_format_revision >
3428 	       PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H);
3429 
3430 	if (!pkg->iter.field.ptr) {
3431 		return -EINVAL;
3432 	}
3433 	iter = &pkg->iter;
3434 
3435 	rc = pldm_msgbuf_init_dynamic_uint16(
3436 		buf, PLDM_FWUP_DOWNSTREAM_DEVICE_ID_RECORD_MIN_SIZE,
3437 		(void *)iter->field.ptr, iter->field.length,
3438 		(void **)&iter->field.ptr, &iter->field.length);
3439 	if (rc) {
3440 		return pldm_msgbuf_discard(buf, rc);
3441 	}
3442 
3443 	pldm_msgbuf_extract(buf, record_len);
3444 	pldm_msgbuf_extract(buf, rec->descriptor_count);
3445 
3446 	rc = pldm_msgbuf_extract(buf, rec->update_option_flags.value);
3447 	if (rc) {
3448 		return pldm_msgbuf_discard(buf, rc);
3449 	}
3450 
3451 	rc = pldm_msgbuf_extract(
3452 		buf, rec->self_contained_activation_min_version_string_type);
3453 	if (rc) {
3454 		return pldm_msgbuf_discard(buf, rc);
3455 	}
3456 	if (!is_string_type_valid(
3457 		    rec->self_contained_activation_min_version_string_type)) {
3458 		return pldm_msgbuf_discard(buf, -EPROTO);
3459 	}
3460 
3461 	rc = pldm_msgbuf_extract_uint8_to_size(
3462 		buf, rec->self_contained_activation_min_version_string.length);
3463 	if (rc) {
3464 		return pldm_msgbuf_discard(buf, rc);
3465 	}
3466 
3467 	rc = pldm_msgbuf_extract_uint16_to_size(buf, rec->package_data.length);
3468 	if (rc) {
3469 		return pldm_msgbuf_discard(buf, rc);
3470 	}
3471 
3472 	if (pkg->hdr->package_header_format_revision >=
3473 	    PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H) {
3474 		pldm_msgbuf_extract_uint32_to_size(
3475 			buf, rec->reference_manifest_data.length);
3476 	} else {
3477 		rec->reference_manifest_data.length = 0;
3478 	}
3479 
3480 	assert((pkg->hdr->component_bitmap_bit_length & 7) == 0);
3481 	rc = pldm_msgbuf_span_required(
3482 		buf, pkg->hdr->component_bitmap_bit_length / 8,
3483 		(const void **)&rec->applicable_components.bitmap.ptr);
3484 	if (rc) {
3485 		return pldm_msgbuf_discard(buf, rc);
3486 	}
3487 	rec->applicable_components.bitmap.length =
3488 		pkg->hdr->component_bitmap_bit_length / 8;
3489 
3490 	pldm_msgbuf_span_required(
3491 		buf, rec->self_contained_activation_min_version_string.length,
3492 		(const void **)&rec
3493 			->self_contained_activation_min_version_string.ptr);
3494 	if (rec->update_option_flags.bits.bit0) {
3495 		pldm_msgbuf_extract(
3496 			buf,
3497 			rec->self_contained_activation_min_version_comparison_stamp);
3498 	} else {
3499 		rec->self_contained_activation_min_version_comparison_stamp = 0;
3500 	}
3501 
3502 	/* The total length reserved for `package_data` and `reference_manifest_data` */
3503 	package_data_offset =
3504 		rec->package_data.length + rec->reference_manifest_data.length;
3505 
3506 	pldm_msgbuf_span_until(buf, package_data_offset,
3507 			       (const void **)&rec->record_descriptors.ptr,
3508 			       &rec->record_descriptors.length);
3509 
3510 	pldm_msgbuf_span_required(buf, rec->package_data.length,
3511 				  (const void **)&rec->package_data.ptr);
3512 
3513 	/* Supported in package header revision 1.3 (FR04H) and above. */
3514 	if (pkg->hdr->package_header_format_revision >=
3515 	    PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H) {
3516 		pldm_msgbuf_span_required(
3517 			buf, rec->reference_manifest_data.length,
3518 			(const void **)&rec->reference_manifest_data.ptr);
3519 	} else {
3520 		assert(rec->reference_manifest_data.length == 0);
3521 		rec->reference_manifest_data.ptr = NULL;
3522 	}
3523 
3524 	return pldm_msgbuf_complete_consumed(buf);
3525 }
3526 
3527 LIBPLDM_ABI_STABLE
pldm_package_component_image_information_iter_init(struct pldm_package * pkg)3528 int pldm_package_component_image_information_iter_init(struct pldm_package *pkg)
3529 {
3530 	struct pldm_package_iter *iter;
3531 	uint16_t component_image_count;
3532 	PLDM_MSGBUF_RO_DEFINE_P(buf);
3533 	int rc;
3534 
3535 	if (!pkg || !pkg->pin || !pkg->hdr) {
3536 		return -EINVAL;
3537 	}
3538 
3539 	assert(pkg->pin->format.revision >=
3540 	       PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H);
3541 	assert(pkg->pin->format.revision <=
3542 	       PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR04H);
3543 	assert(pkg->hdr->package_header_format_revision >=
3544 	       PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H);
3545 	assert(pkg->hdr->package_header_format_revision <=
3546 	       pkg->pin->format.revision);
3547 
3548 	if (pkg->state == PLDM_PACKAGE_PARSE_FIRMWARE_DEVICES) {
3549 		if (pkg->pin->format.revision !=
3550 			    PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H ||
3551 		    pkg->hdr->package_header_format_revision !=
3552 			    pkg->pin->format.revision) {
3553 			return -EPROTO;
3554 		}
3555 	} else if (pkg->state == PLDM_PACKAGE_PARSE_DOWNSTREAM_DEVICES) {
3556 		assert(pkg->pin->format.revision !=
3557 		       PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR01H);
3558 	} else {
3559 		return -EPROTO;
3560 	}
3561 
3562 	if (!pkg->iter.field.ptr) {
3563 		return -EINVAL;
3564 	}
3565 	iter = &pkg->iter;
3566 
3567 	pkg->state = PLDM_PACKAGE_PARSE_COMPONENT_IMAGE_INFORMATION;
3568 
3569 	/* Extract the component image count */
3570 	rc = pldm_msgbuf_init_errno(buf, 1, iter->field.ptr,
3571 				    iter->field.length);
3572 	if (rc) {
3573 		return rc;
3574 	}
3575 
3576 	rc = pldm_msgbuf_extract(buf, component_image_count);
3577 	if (rc) {
3578 		return pldm_msgbuf_discard(buf, rc);
3579 	}
3580 	iter->entries = component_image_count;
3581 
3582 	pldm_msgbuf_span_remaining(buf, (const void **)&iter->field.ptr,
3583 				   &iter->field.length);
3584 
3585 	return pldm_msgbuf_complete(buf);
3586 }
3587 
3588 #define PLDM_FWUP_COMPONENT_IMAGE_INFORMATION_MIN_SIZE 22
3589 LIBPLDM_ABI_STABLE
decode_pldm_package_component_image_information_from_iter(struct pldm_package * pkg,struct pldm_package_component_image_information * info)3590 int decode_pldm_package_component_image_information_from_iter(
3591 	struct pldm_package *pkg,
3592 	struct pldm_package_component_image_information *info)
3593 {
3594 	uint32_t component_location_offset = 0;
3595 	struct pldm_package_iter *iter;
3596 	uint32_t component_size = 0;
3597 	PLDM_MSGBUF_RO_DEFINE_P(buf);
3598 	int rc;
3599 
3600 	if (!pkg || !info) {
3601 		return -EINVAL;
3602 	}
3603 
3604 	if (pkg->state != PLDM_PACKAGE_PARSE_COMPONENT_IMAGE_INFORMATION) {
3605 		return -EPROTO;
3606 	}
3607 
3608 	if (!pkg->iter.field.ptr) {
3609 		return -EINVAL;
3610 	}
3611 	iter = &pkg->iter;
3612 
3613 	rc = pldm_msgbuf_init_errno(
3614 		buf, PLDM_FWUP_COMPONENT_IMAGE_INFORMATION_MIN_SIZE,
3615 		iter->field.ptr, iter->field.length);
3616 	if (rc) {
3617 		return rc;
3618 	}
3619 
3620 	pldm_msgbuf_extract(buf, info->component_classification);
3621 	pldm_msgbuf_extract(buf, info->component_identifier);
3622 	pldm_msgbuf_extract(buf, info->component_comparison_stamp);
3623 	pldm_msgbuf_extract(buf, info->component_options.value);
3624 	pldm_msgbuf_extract(buf,
3625 			    info->requested_component_activation_method.value);
3626 	pldm_msgbuf_extract(buf, component_location_offset);
3627 	pldm_msgbuf_extract(buf, component_size);
3628 
3629 	rc = pldm_msgbuf_extract(buf, info->component_version_string_type);
3630 	if (rc) {
3631 		return pldm_msgbuf_discard(buf, rc);
3632 	}
3633 	if (!is_string_type_valid(info->component_version_string_type)) {
3634 		return pldm_msgbuf_discard(buf, -EPROTO);
3635 	}
3636 
3637 	rc = pldm_msgbuf_extract_uint8_to_size(
3638 		buf, info->component_version_string.length);
3639 	if (rc) {
3640 		return pldm_msgbuf_discard(buf, rc);
3641 	}
3642 
3643 	pldm_msgbuf_span_required(
3644 		buf, info->component_version_string.length,
3645 		(const void **)&info->component_version_string.ptr);
3646 
3647 	/* Supported in package header revision 1.2 (FR03H) and above. */
3648 	if (pkg->hdr->package_header_format_revision >=
3649 	    PLDM_PACKAGE_HEADER_FORMAT_REVISION_FR03H) {
3650 		rc = pldm_msgbuf_extract_uint32_to_size(
3651 			buf, info->component_opaque_data.length);
3652 		if (rc) {
3653 			return pldm_msgbuf_discard(buf, rc);
3654 		}
3655 		pldm_msgbuf_span_required(
3656 			buf, info->component_opaque_data.length,
3657 			(const void **)&info->component_opaque_data.ptr);
3658 	} else {
3659 		info->component_opaque_data.length = 0;
3660 	}
3661 
3662 	if (info->component_opaque_data.length == 0) {
3663 		info->component_opaque_data.ptr = NULL;
3664 	}
3665 
3666 	pldm_msgbuf_span_remaining(buf, (const void **)&iter->field.ptr,
3667 				   &iter->field.length);
3668 
3669 	rc = pldm_msgbuf_complete_consumed(buf);
3670 	if (rc) {
3671 		return rc;
3672 	}
3673 
3674 	if (info->component_classification > 0x000d &&
3675 	    info->component_classification < 0x8000) {
3676 		return -EPROTO;
3677 	}
3678 
3679 	/* Resolve the component image in memory */
3680 	rc = pldm_msgbuf_init_errno(buf, 0, pkg->package.ptr,
3681 				    pkg->package.length);
3682 	if (rc) {
3683 		return rc;
3684 	}
3685 
3686 	pldm_msgbuf_span_required(buf, component_location_offset, NULL);
3687 	pldm_msgbuf_span_required(buf, component_size,
3688 				  (const void **)&info->component_image.ptr);
3689 
3690 	rc = pldm_msgbuf_complete(buf);
3691 	if (rc) {
3692 		return rc;
3693 	}
3694 
3695 	info->component_image.length = component_size;
3696 
3697 	return 0;
3698 }
3699