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