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