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