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