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