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