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 static int decode_pldm_package_header_info_errno( 330 const uint8_t *data, size_t length, 331 struct pldm_package_header_information *package_header_info, 332 struct variable_field *package_version_str) 333 { 334 if (data == NULL || package_header_info == NULL || 335 package_version_str == NULL) { 336 return -EINVAL; 337 } 338 339 if (length < sizeof(struct pldm_package_header_information)) { 340 return -EOVERFLOW; 341 } 342 343 struct pldm_package_header_information *data_header = 344 (struct pldm_package_header_information *)(data); 345 346 if (!is_string_type_valid(data_header->package_version_string_type) || 347 (data_header->package_version_string_length == 0)) { 348 return -EBADMSG; 349 } 350 351 if (length < sizeof(struct pldm_package_header_information) + 352 data_header->package_version_string_length) { 353 return -EOVERFLOW; 354 } 355 356 if ((data_header->component_bitmap_bit_length % 357 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) { 358 return -EBADMSG; 359 } 360 361 memcpy(package_header_info->uuid, data_header->uuid, 362 sizeof(data_header->uuid)); 363 package_header_info->package_header_format_version = 364 data_header->package_header_format_version; 365 package_header_info->package_header_size = 366 le16toh(data_header->package_header_size); 367 memcpy(package_header_info->package_release_date_time, 368 data_header->package_release_date_time, 369 sizeof(data_header->package_release_date_time)); 370 package_header_info->component_bitmap_bit_length = 371 le16toh(data_header->component_bitmap_bit_length); 372 package_header_info->package_version_string_type = 373 data_header->package_version_string_type; 374 package_header_info->package_version_string_length = 375 data_header->package_version_string_length; 376 package_version_str->ptr = 377 data + sizeof(struct pldm_package_header_information); 378 package_version_str->length = 379 package_header_info->package_version_string_length; 380 381 return 0; 382 } 383 384 LIBPLDM_ABI_STABLE 385 int decode_pldm_package_header_info( 386 const uint8_t *data, size_t length, 387 struct pldm_package_header_information *package_header_info, 388 struct variable_field *package_version_str) 389 { 390 int rc; 391 392 rc = decode_pldm_package_header_info_errno( 393 data, length, package_header_info, package_version_str); 394 if (rc < 0) { 395 return pldm_xlate_errno(rc); 396 } 397 398 return PLDM_SUCCESS; 399 } 400 401 static int decode_firmware_device_id_record_errno( 402 const uint8_t *data, size_t length, 403 uint16_t component_bitmap_bit_length, 404 struct pldm_firmware_device_id_record *fw_device_id_record, 405 struct variable_field *applicable_components, 406 struct variable_field *comp_image_set_version_str, 407 struct variable_field *record_descriptors, 408 struct variable_field *fw_device_pkg_data) 409 { 410 if (data == NULL || fw_device_id_record == NULL || 411 applicable_components == NULL || 412 comp_image_set_version_str == NULL || record_descriptors == NULL || 413 fw_device_pkg_data == NULL) { 414 return -EINVAL; 415 } 416 417 if (length < sizeof(struct pldm_firmware_device_id_record)) { 418 return -EOVERFLOW; 419 } 420 421 if ((component_bitmap_bit_length % 422 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) { 423 return -EBADMSG; 424 } 425 426 struct pldm_firmware_device_id_record *data_record = 427 (struct pldm_firmware_device_id_record *)(data); 428 429 if (!is_string_type_valid( 430 data_record->comp_image_set_version_string_type) || 431 (data_record->comp_image_set_version_string_length == 0)) { 432 return -EBADMSG; 433 } 434 435 fw_device_id_record->record_length = 436 le16toh(data_record->record_length); 437 fw_device_id_record->descriptor_count = data_record->descriptor_count; 438 fw_device_id_record->device_update_option_flags.value = 439 le32toh(data_record->device_update_option_flags.value); 440 fw_device_id_record->comp_image_set_version_string_type = 441 data_record->comp_image_set_version_string_type; 442 fw_device_id_record->comp_image_set_version_string_length = 443 data_record->comp_image_set_version_string_length; 444 fw_device_id_record->fw_device_pkg_data_length = 445 le16toh(data_record->fw_device_pkg_data_length); 446 447 if (length < fw_device_id_record->record_length) { 448 return -EOVERFLOW; 449 } 450 451 uint16_t applicable_components_length = 452 component_bitmap_bit_length / 453 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE; 454 size_t calc_min_record_length = 455 sizeof(struct pldm_firmware_device_id_record) + 456 applicable_components_length + 457 data_record->comp_image_set_version_string_length + 458 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN + 459 fw_device_id_record->fw_device_pkg_data_length; 460 461 if (fw_device_id_record->record_length < calc_min_record_length) { 462 return -EOVERFLOW; 463 } 464 465 applicable_components->ptr = 466 data + sizeof(struct pldm_firmware_device_id_record); 467 applicable_components->length = applicable_components_length; 468 469 comp_image_set_version_str->ptr = 470 applicable_components->ptr + applicable_components->length; 471 comp_image_set_version_str->length = 472 fw_device_id_record->comp_image_set_version_string_length; 473 474 record_descriptors->ptr = comp_image_set_version_str->ptr + 475 comp_image_set_version_str->length; 476 record_descriptors->length = 477 fw_device_id_record->record_length - 478 sizeof(struct pldm_firmware_device_id_record) - 479 applicable_components_length - 480 fw_device_id_record->comp_image_set_version_string_length - 481 fw_device_id_record->fw_device_pkg_data_length; 482 483 if (fw_device_id_record->fw_device_pkg_data_length) { 484 fw_device_pkg_data->ptr = 485 record_descriptors->ptr + record_descriptors->length; 486 fw_device_pkg_data->length = 487 fw_device_id_record->fw_device_pkg_data_length; 488 } 489 490 return 0; 491 } 492 493 LIBPLDM_ABI_STABLE 494 int decode_firmware_device_id_record( 495 const uint8_t *data, size_t length, 496 uint16_t component_bitmap_bit_length, 497 struct pldm_firmware_device_id_record *fw_device_id_record, 498 struct variable_field *applicable_components, 499 struct variable_field *comp_image_set_version_str, 500 struct variable_field *record_descriptors, 501 struct variable_field *fw_device_pkg_data) 502 { 503 int rc; 504 505 rc = decode_firmware_device_id_record_errno( 506 data, length, component_bitmap_bit_length, fw_device_id_record, 507 applicable_components, comp_image_set_version_str, 508 record_descriptors, fw_device_pkg_data); 509 if (rc < 0) { 510 return pldm_xlate_errno(rc); 511 } 512 513 return PLDM_SUCCESS; 514 } 515 516 LIBPLDM_ABI_STABLE 517 int decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter *iter, 518 struct pldm_descriptor *desc) 519 { 520 struct pldm_msgbuf _buf; 521 struct pldm_msgbuf *buf = &_buf; 522 int rc; 523 524 if (!iter || !iter->field || !desc) { 525 return -EINVAL; 526 } 527 528 rc = pldm_msgbuf_init_errno(buf, PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN, 529 iter->field->ptr, iter->field->length); 530 if (rc) { 531 return rc; 532 } 533 534 pldm_msgbuf_extract(buf, desc->descriptor_type); 535 rc = pldm_msgbuf_extract(buf, desc->descriptor_length); 536 if (rc) { 537 return rc; 538 } 539 540 desc->descriptor_data = NULL; 541 pldm_msgbuf_span_required(buf, desc->descriptor_length, 542 (void **)&desc->descriptor_data); 543 iter->field->ptr = NULL; 544 pldm_msgbuf_span_remaining(buf, (void **)&iter->field->ptr, 545 &iter->field->length); 546 547 return pldm_msgbuf_destroy(buf); 548 } 549 550 static int decode_descriptor_type_length_value_errno( 551 const uint8_t *data, size_t length, uint16_t *descriptor_type, 552 struct variable_field *descriptor_data) 553 { 554 uint16_t descriptor_length = 0; 555 556 if (data == NULL || descriptor_type == NULL || 557 descriptor_data == NULL) { 558 return -EINVAL; 559 } 560 561 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) { 562 return -EOVERFLOW; 563 } 564 565 struct pldm_descriptor_tlv *entry = 566 (struct pldm_descriptor_tlv *)(data); 567 568 *descriptor_type = le16toh(entry->descriptor_type); 569 descriptor_length = le16toh(entry->descriptor_length); 570 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) { 571 if (descriptor_length != 572 get_descriptor_type_length(*descriptor_type)) { 573 return -EBADMSG; 574 } 575 } 576 577 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) + 578 descriptor_length)) { 579 return -EOVERFLOW; 580 } 581 582 descriptor_data->ptr = entry->descriptor_data; 583 descriptor_data->length = descriptor_length; 584 585 return 0; 586 } 587 588 LIBPLDM_ABI_STABLE 589 int decode_descriptor_type_length_value(const uint8_t *data, size_t length, 590 uint16_t *descriptor_type, 591 struct variable_field *descriptor_data) 592 { 593 int rc; 594 595 rc = decode_descriptor_type_length_value_errno( 596 data, length, descriptor_type, descriptor_data); 597 if (rc < 0) { 598 return pldm_xlate_errno(rc); 599 } 600 601 return PLDM_SUCCESS; 602 } 603 604 static int decode_vendor_defined_descriptor_value_errno( 605 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type, 606 struct variable_field *descriptor_title_str, 607 struct variable_field *descriptor_data) 608 { 609 if (data == NULL || descriptor_title_str_type == NULL || 610 descriptor_title_str == NULL || descriptor_data == NULL) { 611 return -EINVAL; 612 } 613 614 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) { 615 return -EOVERFLOW; 616 } 617 618 struct pldm_vendor_defined_descriptor_title_data *entry = 619 (struct pldm_vendor_defined_descriptor_title_data *)(data); 620 if (!is_string_type_valid( 621 entry->vendor_defined_descriptor_title_str_type) || 622 (entry->vendor_defined_descriptor_title_str_len == 0)) { 623 return -EBADMSG; 624 } 625 626 // Assuming at least 1 byte of VendorDefinedDescriptorData 627 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) + 628 entry->vendor_defined_descriptor_title_str_len)) { 629 return -EOVERFLOW; 630 } 631 632 *descriptor_title_str_type = 633 entry->vendor_defined_descriptor_title_str_type; 634 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str; 635 descriptor_title_str->length = 636 entry->vendor_defined_descriptor_title_str_len; 637 638 descriptor_data->ptr = 639 descriptor_title_str->ptr + descriptor_title_str->length; 640 descriptor_data->length = 641 length - 642 sizeof(entry->vendor_defined_descriptor_title_str_type) - 643 sizeof(entry->vendor_defined_descriptor_title_str_len) - 644 descriptor_title_str->length; 645 646 return 0; 647 } 648 649 LIBPLDM_ABI_STABLE 650 int decode_vendor_defined_descriptor_value( 651 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type, 652 struct variable_field *descriptor_title_str, 653 struct variable_field *descriptor_data) 654 { 655 int rc; 656 657 rc = decode_vendor_defined_descriptor_value_errno( 658 data, length, descriptor_title_str_type, descriptor_title_str, 659 descriptor_data); 660 if (rc < 0) { 661 return pldm_xlate_errno(rc); 662 } 663 664 return PLDM_SUCCESS; 665 } 666 667 static int decode_pldm_comp_image_info_errno( 668 const uint8_t *data, size_t length, 669 struct pldm_component_image_information *pldm_comp_image_info, 670 struct variable_field *comp_version_str) 671 { 672 if (data == NULL || pldm_comp_image_info == NULL || 673 comp_version_str == NULL) { 674 return -EINVAL; 675 } 676 677 if (length < sizeof(struct pldm_component_image_information)) { 678 return -EOVERFLOW; 679 } 680 681 struct pldm_component_image_information *data_header = 682 (struct pldm_component_image_information *)(data); 683 684 if (!is_string_type_valid(data_header->comp_version_string_type) || 685 (data_header->comp_version_string_length == 0)) { 686 return -EBADMSG; 687 } 688 689 if (length < sizeof(struct pldm_component_image_information) + 690 data_header->comp_version_string_length) { 691 return -EOVERFLOW; 692 } 693 694 pldm_comp_image_info->comp_classification = 695 le16toh(data_header->comp_classification); 696 pldm_comp_image_info->comp_identifier = 697 le16toh(data_header->comp_identifier); 698 pldm_comp_image_info->comp_comparison_stamp = 699 le32toh(data_header->comp_comparison_stamp); 700 pldm_comp_image_info->comp_options.value = 701 le16toh(data_header->comp_options.value); 702 pldm_comp_image_info->requested_comp_activation_method.value = 703 le16toh(data_header->requested_comp_activation_method.value); 704 pldm_comp_image_info->comp_location_offset = 705 le32toh(data_header->comp_location_offset); 706 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size); 707 pldm_comp_image_info->comp_version_string_type = 708 data_header->comp_version_string_type; 709 pldm_comp_image_info->comp_version_string_length = 710 data_header->comp_version_string_length; 711 712 if ((pldm_comp_image_info->comp_options.bits.bit1 == false && 713 pldm_comp_image_info->comp_comparison_stamp != 714 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) { 715 return -EBADMSG; 716 } 717 718 if (pldm_comp_image_info->comp_location_offset == 0 || 719 pldm_comp_image_info->comp_size == 0) { 720 return -EBADMSG; 721 } 722 723 comp_version_str->ptr = 724 data + sizeof(struct pldm_component_image_information); 725 comp_version_str->length = 726 pldm_comp_image_info->comp_version_string_length; 727 728 return 0; 729 } 730 731 LIBPLDM_ABI_STABLE 732 int decode_pldm_comp_image_info( 733 const uint8_t *data, size_t length, 734 struct pldm_component_image_information *pldm_comp_image_info, 735 struct variable_field *comp_version_str) 736 { 737 int rc; 738 739 rc = decode_pldm_comp_image_info_errno( 740 data, length, pldm_comp_image_info, comp_version_str); 741 if (rc < 0) { 742 return pldm_xlate_errno(rc); 743 } 744 745 return PLDM_SUCCESS; 746 } 747 748 LIBPLDM_ABI_STABLE 749 int encode_query_device_identifiers_req(uint8_t instance_id, 750 size_t payload_length, 751 struct pldm_msg *msg) 752 { 753 if (msg == NULL) { 754 return PLDM_ERROR_INVALID_DATA; 755 } 756 757 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) { 758 return PLDM_ERROR_INVALID_LENGTH; 759 } 760 761 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 762 PLDM_QUERY_DEVICE_IDENTIFIERS, msg); 763 } 764 765 LIBPLDM_ABI_STABLE 766 int decode_query_device_identifiers_resp(const struct pldm_msg *msg, 767 size_t payload_length, 768 uint8_t *completion_code, 769 uint32_t *device_identifiers_len, 770 uint8_t *descriptor_count, 771 uint8_t **descriptor_data) 772 { 773 if (msg == NULL || completion_code == NULL || 774 device_identifiers_len == NULL || descriptor_count == NULL || 775 descriptor_data == NULL) { 776 return PLDM_ERROR_INVALID_DATA; 777 } 778 779 *completion_code = msg->payload[0]; 780 if (PLDM_SUCCESS != *completion_code) { 781 return PLDM_SUCCESS; 782 } 783 784 if (payload_length < 785 sizeof(struct pldm_query_device_identifiers_resp)) { 786 return PLDM_ERROR_INVALID_LENGTH; 787 } 788 789 struct pldm_query_device_identifiers_resp *response = 790 (struct pldm_query_device_identifiers_resp *)msg->payload; 791 *device_identifiers_len = le32toh(response->device_identifiers_len); 792 793 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) { 794 return PLDM_ERROR_INVALID_LENGTH; 795 } 796 797 if (payload_length != 798 sizeof(struct pldm_query_device_identifiers_resp) + 799 *device_identifiers_len) { 800 return PLDM_ERROR_INVALID_LENGTH; 801 } 802 *descriptor_count = response->descriptor_count; 803 804 if (*descriptor_count == 0) { 805 return PLDM_ERROR_INVALID_DATA; 806 } 807 *descriptor_data = 808 (uint8_t *)(msg->payload + 809 sizeof(struct pldm_query_device_identifiers_resp)); 810 return PLDM_SUCCESS; 811 } 812 813 LIBPLDM_ABI_TESTING 814 int encode_query_device_identifiers_resp( 815 uint8_t instance_id, uint8_t descriptor_count, 816 const struct pldm_descriptor *descriptors, struct pldm_msg *msg, 817 size_t *payload_length) 818 { 819 int rc; 820 struct pldm_msgbuf _buf; 821 struct pldm_msgbuf *buf = &_buf; 822 823 if (descriptors == NULL || msg == NULL || payload_length == NULL) { 824 return -EINVAL; 825 } 826 827 if (descriptor_count < 1) { 828 return -EINVAL; 829 } 830 831 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 832 PLDM_QUERY_DEVICE_IDENTIFIERS, msg); 833 if (rc) { 834 return -EINVAL; 835 } 836 837 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 838 if (rc) { 839 return rc; 840 } 841 842 /* Determine total length */ 843 uint32_t device_identifiers_len = 0; 844 for (uint8_t i = 0; i < descriptor_count; i++) { 845 const struct pldm_descriptor *d = &descriptors[i]; 846 device_identifiers_len += 847 2 * sizeof(uint16_t) + d->descriptor_length; 848 } 849 850 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 851 pldm_msgbuf_insert(buf, device_identifiers_len); 852 pldm_msgbuf_insert(buf, descriptor_count); 853 854 for (uint8_t i = 0; i < descriptor_count; i++) { 855 const struct pldm_descriptor *d = &descriptors[i]; 856 pldm_msgbuf_insert(buf, d->descriptor_type); 857 pldm_msgbuf_insert(buf, d->descriptor_length); 858 if (d->descriptor_data == NULL) { 859 return -EINVAL; 860 } 861 rc = pldm_msgbuf_insert_array( 862 buf, d->descriptor_length, 863 (const uint8_t *)d->descriptor_data, 864 d->descriptor_length); 865 if (rc) { 866 return rc; 867 } 868 } 869 870 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 871 } 872 873 LIBPLDM_ABI_STABLE 874 int encode_get_firmware_parameters_req(uint8_t instance_id, 875 size_t payload_length, 876 struct pldm_msg *msg) 877 { 878 if (msg == NULL) { 879 return PLDM_ERROR_INVALID_DATA; 880 } 881 882 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) { 883 return PLDM_ERROR_INVALID_LENGTH; 884 } 885 886 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 887 PLDM_GET_FIRMWARE_PARAMETERS, msg); 888 } 889 890 LIBPLDM_ABI_STABLE 891 int decode_get_firmware_parameters_resp( 892 const struct pldm_msg *msg, size_t payload_length, 893 struct pldm_get_firmware_parameters_resp *resp_data, 894 struct variable_field *active_comp_image_set_ver_str, 895 struct variable_field *pending_comp_image_set_ver_str, 896 struct variable_field *comp_parameter_table) 897 { 898 if (msg == NULL || resp_data == NULL || 899 active_comp_image_set_ver_str == NULL || 900 pending_comp_image_set_ver_str == NULL || 901 comp_parameter_table == NULL || !payload_length) { 902 return PLDM_ERROR_INVALID_DATA; 903 } 904 905 resp_data->completion_code = msg->payload[0]; 906 if (PLDM_SUCCESS != resp_data->completion_code) { 907 return PLDM_SUCCESS; 908 } 909 910 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) { 911 return PLDM_ERROR_INVALID_LENGTH; 912 } 913 914 struct pldm_get_firmware_parameters_resp *response = 915 (struct pldm_get_firmware_parameters_resp *)msg->payload; 916 917 if (!is_string_type_valid( 918 response->active_comp_image_set_ver_str_type) || 919 (response->active_comp_image_set_ver_str_len == 0)) { 920 return PLDM_ERROR_INVALID_DATA; 921 } 922 923 if (response->pending_comp_image_set_ver_str_len == 0) { 924 if (response->pending_comp_image_set_ver_str_type != 925 PLDM_STR_TYPE_UNKNOWN) { 926 return PLDM_ERROR_INVALID_DATA; 927 } 928 } else { 929 if (!is_string_type_valid( 930 response->pending_comp_image_set_ver_str_type)) { 931 return PLDM_ERROR_INVALID_DATA; 932 } 933 } 934 935 size_t partial_response_length = 936 sizeof(struct pldm_get_firmware_parameters_resp) + 937 response->active_comp_image_set_ver_str_len + 938 response->pending_comp_image_set_ver_str_len; 939 940 if (payload_length < partial_response_length) { 941 return PLDM_ERROR_INVALID_LENGTH; 942 } 943 944 resp_data->capabilities_during_update.value = 945 le32toh(response->capabilities_during_update.value); 946 resp_data->comp_count = le16toh(response->comp_count); 947 resp_data->active_comp_image_set_ver_str_type = 948 response->active_comp_image_set_ver_str_type; 949 resp_data->active_comp_image_set_ver_str_len = 950 response->active_comp_image_set_ver_str_len; 951 resp_data->pending_comp_image_set_ver_str_type = 952 response->pending_comp_image_set_ver_str_type; 953 resp_data->pending_comp_image_set_ver_str_len = 954 response->pending_comp_image_set_ver_str_len; 955 956 active_comp_image_set_ver_str->ptr = 957 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp); 958 active_comp_image_set_ver_str->length = 959 resp_data->active_comp_image_set_ver_str_len; 960 961 if (resp_data->pending_comp_image_set_ver_str_len != 0) { 962 pending_comp_image_set_ver_str->ptr = 963 msg->payload + 964 sizeof(struct pldm_get_firmware_parameters_resp) + 965 resp_data->active_comp_image_set_ver_str_len; 966 pending_comp_image_set_ver_str->length = 967 resp_data->pending_comp_image_set_ver_str_len; 968 } else { 969 pending_comp_image_set_ver_str->ptr = NULL; 970 pending_comp_image_set_ver_str->length = 0; 971 } 972 973 if (payload_length > partial_response_length && resp_data->comp_count) { 974 comp_parameter_table->ptr = 975 msg->payload + 976 sizeof(struct pldm_get_firmware_parameters_resp) + 977 resp_data->active_comp_image_set_ver_str_len + 978 resp_data->pending_comp_image_set_ver_str_len; 979 comp_parameter_table->length = 980 payload_length - partial_response_length; 981 } else { 982 comp_parameter_table->ptr = NULL; 983 comp_parameter_table->length = 0; 984 } 985 986 return PLDM_SUCCESS; 987 } 988 989 LIBPLDM_ABI_TESTING 990 int encode_get_firmware_parameters_resp( 991 uint8_t instance_id, 992 const struct pldm_get_firmware_parameters_resp_full *resp_data, 993 struct pldm_msg *msg, size_t *payload_length) 994 { 995 int rc; 996 struct pldm_msgbuf _buf; 997 struct pldm_msgbuf *buf = &_buf; 998 999 if (resp_data == NULL || msg == NULL || payload_length == NULL) { 1000 return -EINVAL; 1001 } 1002 1003 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 1004 PLDM_GET_FIRMWARE_PARAMETERS, msg); 1005 if (rc) { 1006 return -EINVAL; 1007 } 1008 1009 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 1010 if (rc) { 1011 return rc; 1012 } 1013 1014 pldm_msgbuf_insert(buf, resp_data->completion_code); 1015 pldm_msgbuf_insert(buf, resp_data->capabilities_during_update.value); 1016 pldm_msgbuf_insert(buf, resp_data->comp_count); 1017 pldm_msgbuf_insert(buf, 1018 resp_data->active_comp_image_set_ver_str.str_type); 1019 pldm_msgbuf_insert(buf, 1020 resp_data->active_comp_image_set_ver_str.str_len); 1021 pldm_msgbuf_insert(buf, 1022 resp_data->pending_comp_image_set_ver_str.str_type); 1023 pldm_msgbuf_insert(buf, 1024 resp_data->pending_comp_image_set_ver_str.str_len); 1025 /* String data appended */ 1026 rc = pldm_msgbuf_insert_array( 1027 buf, resp_data->active_comp_image_set_ver_str.str_len, 1028 resp_data->active_comp_image_set_ver_str.str_data, 1029 resp_data->active_comp_image_set_ver_str.str_len); 1030 if (rc) { 1031 return rc; 1032 } 1033 rc = pldm_msgbuf_insert_array( 1034 buf, resp_data->pending_comp_image_set_ver_str.str_len, 1035 resp_data->pending_comp_image_set_ver_str.str_data, 1036 resp_data->pending_comp_image_set_ver_str.str_len); 1037 if (rc) { 1038 return rc; 1039 } 1040 1041 /* Further calls to encode_get_firmware_parameters_resp_comp_entry 1042 * will populate the remainder */ 1043 1044 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 1045 } 1046 1047 LIBPLDM_ABI_TESTING 1048 int encode_get_firmware_parameters_resp_comp_entry( 1049 const struct pldm_component_parameter_entry_full *comp, 1050 uint8_t *payload, size_t *payload_length) 1051 { 1052 int rc; 1053 struct pldm_msgbuf _buf; 1054 struct pldm_msgbuf *buf = &_buf; 1055 1056 if (comp == NULL || payload == NULL || payload_length == NULL) { 1057 return -EINVAL; 1058 } 1059 1060 rc = pldm_msgbuf_init_errno(buf, 0, payload, *payload_length); 1061 if (rc) { 1062 return rc; 1063 } 1064 1065 pldm_msgbuf_insert(buf, comp->comp_classification); 1066 pldm_msgbuf_insert(buf, comp->comp_identifier); 1067 pldm_msgbuf_insert(buf, comp->comp_classification_index); 1068 1069 pldm_msgbuf_insert(buf, comp->active_ver.comparison_stamp); 1070 pldm_msgbuf_insert(buf, (uint8_t)comp->active_ver.str.str_type); 1071 pldm_msgbuf_insert(buf, comp->active_ver.str.str_len); 1072 rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 1073 comp->active_ver.date, 1074 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN); 1075 if (rc) { 1076 return rc; 1077 } 1078 1079 pldm_msgbuf_insert(buf, comp->pending_ver.comparison_stamp); 1080 pldm_msgbuf_insert(buf, (uint8_t)comp->pending_ver.str.str_type); 1081 pldm_msgbuf_insert(buf, comp->pending_ver.str.str_len); 1082 rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 1083 comp->pending_ver.date, 1084 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN); 1085 if (rc) { 1086 return rc; 1087 } 1088 1089 pldm_msgbuf_insert(buf, comp->comp_activation_methods.value); 1090 pldm_msgbuf_insert(buf, comp->capabilities_during_update.value); 1091 1092 rc = pldm_msgbuf_insert_array(buf, comp->active_ver.str.str_len, 1093 comp->active_ver.str.str_data, 1094 comp->active_ver.str.str_len); 1095 if (rc) { 1096 return rc; 1097 } 1098 rc = pldm_msgbuf_insert_array(buf, comp->pending_ver.str.str_len, 1099 comp->pending_ver.str.str_data, 1100 comp->pending_ver.str.str_len); 1101 if (rc) { 1102 return rc; 1103 } 1104 1105 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 1106 } 1107 1108 LIBPLDM_ABI_STABLE 1109 int decode_get_firmware_parameters_resp_comp_entry( 1110 const uint8_t *data, size_t length, 1111 struct pldm_component_parameter_entry *component_data, 1112 struct variable_field *active_comp_ver_str, 1113 struct variable_field *pending_comp_ver_str) 1114 { 1115 if (data == NULL || component_data == NULL || 1116 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) { 1117 return PLDM_ERROR_INVALID_DATA; 1118 } 1119 1120 if (length < sizeof(struct pldm_component_parameter_entry)) { 1121 return PLDM_ERROR_INVALID_LENGTH; 1122 } 1123 1124 struct pldm_component_parameter_entry *entry = 1125 (struct pldm_component_parameter_entry *)(data); 1126 1127 size_t entry_length = sizeof(struct pldm_component_parameter_entry) + 1128 entry->active_comp_ver_str_len + 1129 entry->pending_comp_ver_str_len; 1130 1131 if (length < entry_length) { 1132 return PLDM_ERROR_INVALID_LENGTH; 1133 } 1134 1135 component_data->comp_classification = 1136 le16toh(entry->comp_classification); 1137 component_data->comp_identifier = le16toh(entry->comp_identifier); 1138 component_data->comp_classification_index = 1139 entry->comp_classification_index; 1140 component_data->active_comp_comparison_stamp = 1141 le32toh(entry->active_comp_comparison_stamp); 1142 component_data->active_comp_ver_str_type = 1143 entry->active_comp_ver_str_type; 1144 component_data->active_comp_ver_str_len = 1145 entry->active_comp_ver_str_len; 1146 memcpy(component_data->active_comp_release_date, 1147 entry->active_comp_release_date, 1148 sizeof(entry->active_comp_release_date)); 1149 component_data->pending_comp_comparison_stamp = 1150 le32toh(entry->pending_comp_comparison_stamp); 1151 component_data->pending_comp_ver_str_type = 1152 entry->pending_comp_ver_str_type; 1153 component_data->pending_comp_ver_str_len = 1154 entry->pending_comp_ver_str_len; 1155 memcpy(component_data->pending_comp_release_date, 1156 entry->pending_comp_release_date, 1157 sizeof(entry->pending_comp_release_date)); 1158 component_data->comp_activation_methods.value = 1159 le16toh(entry->comp_activation_methods.value); 1160 component_data->capabilities_during_update.value = 1161 le32toh(entry->capabilities_during_update.value); 1162 1163 if (entry->active_comp_ver_str_len != 0) { 1164 active_comp_ver_str->ptr = 1165 data + sizeof(struct pldm_component_parameter_entry); 1166 active_comp_ver_str->length = entry->active_comp_ver_str_len; 1167 } else { 1168 active_comp_ver_str->ptr = NULL; 1169 active_comp_ver_str->length = 0; 1170 } 1171 1172 if (entry->pending_comp_ver_str_len != 0) { 1173 pending_comp_ver_str->ptr = 1174 data + sizeof(struct pldm_component_parameter_entry) + 1175 entry->active_comp_ver_str_len; 1176 pending_comp_ver_str->length = entry->pending_comp_ver_str_len; 1177 } else { 1178 pending_comp_ver_str->ptr = NULL; 1179 pending_comp_ver_str->length = 0; 1180 } 1181 return PLDM_SUCCESS; 1182 } 1183 1184 LIBPLDM_ABI_STABLE 1185 int encode_query_downstream_devices_req(uint8_t instance_id, 1186 struct pldm_msg *msg) 1187 { 1188 if (msg == NULL) { 1189 return -EINVAL; 1190 } 1191 1192 return encode_pldm_header_only_errno(PLDM_REQUEST, instance_id, 1193 PLDM_FWUP, 1194 PLDM_QUERY_DOWNSTREAM_DEVICES, 1195 msg); 1196 } 1197 1198 LIBPLDM_ABI_STABLE 1199 int decode_query_downstream_devices_resp( 1200 const struct pldm_msg *msg, size_t payload_length, 1201 struct pldm_query_downstream_devices_resp *resp_data) 1202 { 1203 struct pldm_msgbuf _buf; 1204 struct pldm_msgbuf *buf = &_buf; 1205 int rc; 1206 1207 if (msg == NULL || resp_data == NULL || !payload_length) { 1208 return -EINVAL; 1209 } 1210 1211 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 1212 msg->payload, payload_length); 1213 if (rc) { 1214 return rc; 1215 } 1216 1217 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 1218 if (rc) { 1219 return rc; 1220 } 1221 if (PLDM_SUCCESS != resp_data->completion_code) { 1222 // Return the CC directly without decoding the rest of the payload 1223 return 0; 1224 } 1225 1226 if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) { 1227 return -EBADMSG; 1228 } 1229 1230 rc = pldm_msgbuf_extract(buf, 1231 resp_data->downstream_device_update_supported); 1232 if (rc) { 1233 return rc; 1234 } 1235 1236 if (!is_downstream_device_update_support_valid( 1237 resp_data->downstream_device_update_supported)) { 1238 return -EINVAL; 1239 } 1240 1241 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices); 1242 pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices); 1243 pldm_msgbuf_extract(buf, resp_data->capabilities.value); 1244 1245 return pldm_msgbuf_destroy_consumed(buf); 1246 } 1247 1248 LIBPLDM_ABI_STABLE 1249 int encode_query_downstream_identifiers_req( 1250 uint8_t instance_id, 1251 const struct pldm_query_downstream_identifiers_req *params_req, 1252 struct pldm_msg *msg, size_t payload_length) 1253 { 1254 struct pldm_msgbuf _buf; 1255 struct pldm_msgbuf *buf = &_buf; 1256 int rc; 1257 1258 if (!msg || !params_req) { 1259 return -EINVAL; 1260 } 1261 1262 if (!is_transfer_operation_flag_valid( 1263 (enum transfer_op_flag) 1264 params_req->transfer_operation_flag)) { 1265 return -EINVAL; 1266 } 1267 1268 struct pldm_header_info header = { 0 }; 1269 header.instance = instance_id; 1270 header.msg_type = PLDM_REQUEST; 1271 header.pldm_type = PLDM_FWUP; 1272 header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS; 1273 rc = pack_pldm_header_errno(&header, &(msg->hdr)); 1274 if (rc) { 1275 return rc; 1276 } 1277 1278 rc = pldm_msgbuf_init_errno(buf, 1279 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES, 1280 msg->payload, payload_length); 1281 if (rc) { 1282 return rc; 1283 } 1284 1285 pldm_msgbuf_insert(buf, params_req->data_transfer_handle); 1286 // Data correctness has been verified, cast it to 1-byte data directly. 1287 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag); 1288 1289 return pldm_msgbuf_destroy(buf); 1290 } 1291 1292 LIBPLDM_ABI_STABLE 1293 int decode_query_downstream_identifiers_resp( 1294 const struct pldm_msg *msg, size_t payload_length, 1295 struct pldm_query_downstream_identifiers_resp *resp_data, 1296 struct pldm_downstream_device_iter *iter) 1297 { 1298 struct pldm_msgbuf _buf; 1299 struct pldm_msgbuf *buf = &_buf; 1300 void *remaining = NULL; 1301 int rc = 0; 1302 1303 if (msg == NULL || resp_data == NULL || iter == NULL || 1304 !payload_length) { 1305 return -EINVAL; 1306 } 1307 1308 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 1309 msg->payload, payload_length); 1310 if (rc) { 1311 return rc; 1312 } 1313 1314 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 1315 if (rc) { 1316 return rc; 1317 } 1318 if (PLDM_SUCCESS != resp_data->completion_code) { 1319 return 0; 1320 } 1321 1322 if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) { 1323 return -EBADMSG; 1324 } 1325 1326 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle); 1327 pldm_msgbuf_extract(buf, resp_data->transfer_flag); 1328 1329 rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length); 1330 if (rc) { 1331 return rc; 1332 } 1333 1334 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices); 1335 rc = pldm_msgbuf_span_required( 1336 buf, resp_data->downstream_devices_length, &remaining); 1337 if (rc) { 1338 return rc; 1339 } 1340 1341 rc = pldm_msgbuf_destroy(buf); 1342 if (rc) { 1343 return rc; 1344 } 1345 1346 iter->field.ptr = remaining; 1347 iter->field.length = resp_data->downstream_devices_length; 1348 iter->devs = resp_data->number_of_downstream_devices; 1349 1350 return 0; 1351 } 1352 1353 LIBPLDM_ABI_STABLE 1354 int decode_pldm_downstream_device_from_iter( 1355 struct pldm_downstream_device_iter *iter, 1356 struct pldm_downstream_device *dev) 1357 { 1358 struct pldm_msgbuf _buf; 1359 struct pldm_msgbuf *buf = &_buf; 1360 int rc; 1361 1362 if (!iter || !dev) { 1363 return -EINVAL; 1364 } 1365 1366 rc = pldm_msgbuf_init_errno(buf, 3, iter->field.ptr, 1367 iter->field.length); 1368 if (rc) { 1369 return rc; 1370 } 1371 1372 pldm_msgbuf_extract(buf, dev->downstream_device_index); 1373 pldm_msgbuf_extract(buf, dev->downstream_descriptor_count); 1374 iter->field.ptr = NULL; 1375 pldm_msgbuf_span_remaining(buf, (void **)&iter->field.ptr, 1376 &iter->field.length); 1377 1378 return pldm_msgbuf_destroy(buf); 1379 } 1380 1381 LIBPLDM_ABI_STABLE 1382 int encode_get_downstream_firmware_parameters_req( 1383 uint8_t instance_id, 1384 const struct pldm_get_downstream_firmware_parameters_req *params_req, 1385 struct pldm_msg *msg, size_t payload_length) 1386 { 1387 struct pldm_msgbuf _buf; 1388 struct pldm_msgbuf *buf = &_buf; 1389 int rc; 1390 1391 if (!msg || !params_req) { 1392 return -EINVAL; 1393 } 1394 1395 rc = pldm_msgbuf_init_errno( 1396 buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES, 1397 msg->payload, payload_length); 1398 if (rc < 0) { 1399 return rc; 1400 } 1401 1402 if (!is_transfer_operation_flag_valid( 1403 (enum transfer_op_flag) 1404 params_req->transfer_operation_flag)) { 1405 return -EBADMSG; 1406 } 1407 1408 struct pldm_header_info header = { 0 }; 1409 header.instance = instance_id; 1410 header.msg_type = PLDM_REQUEST; 1411 header.pldm_type = PLDM_FWUP; 1412 header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS; 1413 rc = pack_pldm_header_errno(&header, &msg->hdr); 1414 if (rc < 0) { 1415 return rc; 1416 } 1417 1418 pldm_msgbuf_insert(buf, params_req->data_transfer_handle); 1419 // Data correctness has been verified, cast it to 1-byte data directly. 1420 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag); 1421 1422 return pldm_msgbuf_destroy(buf); 1423 } 1424 1425 LIBPLDM_ABI_STABLE 1426 int decode_get_downstream_firmware_parameters_resp( 1427 const struct pldm_msg *msg, size_t payload_length, 1428 struct pldm_get_downstream_firmware_parameters_resp *resp_data, 1429 struct pldm_downstream_device_parameters_iter *iter) 1430 { 1431 struct pldm_msgbuf _buf; 1432 struct pldm_msgbuf *buf = &_buf; 1433 void *remaining = NULL; 1434 size_t length; 1435 int rc; 1436 1437 if (msg == NULL || resp_data == NULL || iter == NULL) { 1438 return -EINVAL; 1439 } 1440 1441 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 1442 msg->payload, payload_length); 1443 if (rc < 0) { 1444 return rc; 1445 } 1446 1447 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 1448 if (rc < 0) { 1449 return rc; 1450 } 1451 if (PLDM_SUCCESS != resp_data->completion_code) { 1452 return 0; 1453 } 1454 1455 if (payload_length < 1456 PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN) { 1457 return -EBADMSG; 1458 } 1459 1460 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle); 1461 pldm_msgbuf_extract(buf, resp_data->transfer_flag); 1462 pldm_msgbuf_extract(buf, 1463 resp_data->fdp_capabilities_during_update.value); 1464 pldm_msgbuf_extract(buf, resp_data->downstream_device_count); 1465 1466 rc = pldm_msgbuf_span_remaining(buf, &remaining, &length); 1467 if (rc) { 1468 return rc; 1469 } 1470 1471 rc = pldm_msgbuf_destroy(buf); 1472 if (rc) { 1473 return rc; 1474 } 1475 1476 iter->field.ptr = remaining; 1477 iter->field.length = length; 1478 iter->entries = resp_data->downstream_device_count; 1479 1480 return 0; 1481 } 1482 1483 LIBPLDM_ABI_STABLE 1484 int decode_pldm_downstream_device_parameters_entry_from_iter( 1485 struct pldm_downstream_device_parameters_iter *iter, 1486 struct pldm_downstream_device_parameters_entry *entry) 1487 { 1488 struct pldm_msgbuf _buf; 1489 struct pldm_msgbuf *buf = &_buf; 1490 void *comp_ver_str; 1491 size_t remaining; 1492 void *cursor; 1493 int rc; 1494 1495 if (iter == NULL || entry == NULL) { 1496 return -EINVAL; 1497 } 1498 1499 rc = pldm_msgbuf_init_errno( 1500 buf, PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN, 1501 iter->field.ptr, iter->field.length); 1502 if (rc < 0) { 1503 return rc; 1504 } 1505 1506 pldm_msgbuf_extract(buf, entry->downstream_device_index); 1507 pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp); 1508 pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type); 1509 rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len); 1510 if (rc < 0) { 1511 return rc; 1512 } 1513 rc = pldm_msgbuf_extract_array(buf, 1514 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 1515 entry->active_comp_release_date, 1516 sizeof(entry->active_comp_release_date)); 1517 if (rc < 0) { 1518 return rc; 1519 } 1520 1521 // Fill the last byte with NULL character 1522 entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] = 1523 '\0'; 1524 1525 pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp); 1526 pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type); 1527 rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len); 1528 if (rc < 0) { 1529 return rc; 1530 } 1531 1532 rc = pldm_msgbuf_extract_array( 1533 buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 1534 entry->pending_comp_release_date, 1535 sizeof(entry->pending_comp_release_date)); 1536 if (rc < 0) { 1537 return rc; 1538 } 1539 1540 // Fill the last byte with NULL character 1541 entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] = 1542 '\0'; 1543 1544 pldm_msgbuf_extract(buf, entry->comp_activation_methods.value); 1545 pldm_msgbuf_extract(buf, entry->capabilities_during_update.value); 1546 1547 comp_ver_str = NULL; 1548 pldm_msgbuf_span_required(buf, entry->active_comp_ver_str_len, 1549 &comp_ver_str); 1550 entry->active_comp_ver_str = comp_ver_str; 1551 1552 comp_ver_str = NULL; 1553 pldm_msgbuf_span_required(buf, entry->pending_comp_ver_str_len, 1554 &comp_ver_str); 1555 entry->pending_comp_ver_str = comp_ver_str; 1556 1557 cursor = NULL; 1558 rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining); 1559 if (rc < 0) { 1560 return rc; 1561 } 1562 1563 iter->field.ptr = cursor; 1564 iter->field.length = remaining; 1565 1566 return 0; 1567 } 1568 1569 LIBPLDM_ABI_STABLE 1570 int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size, 1571 uint16_t num_of_comp, 1572 uint8_t max_outstanding_transfer_req, 1573 uint16_t pkg_data_len, 1574 uint8_t comp_image_set_ver_str_type, 1575 uint8_t comp_image_set_ver_str_len, 1576 const struct variable_field *comp_img_set_ver_str, 1577 struct pldm_msg *msg, size_t payload_length) 1578 { 1579 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL || 1580 msg == NULL) { 1581 return PLDM_ERROR_INVALID_DATA; 1582 } 1583 1584 if (payload_length != sizeof(struct pldm_request_update_req) + 1585 comp_img_set_ver_str->length) { 1586 return PLDM_ERROR_INVALID_LENGTH; 1587 } 1588 1589 if ((comp_image_set_ver_str_len == 0) || 1590 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) { 1591 return PLDM_ERROR_INVALID_DATA; 1592 } 1593 1594 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) || 1595 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) { 1596 return PLDM_ERROR_INVALID_DATA; 1597 } 1598 1599 if (!is_string_type_valid(comp_image_set_ver_str_type)) { 1600 return PLDM_ERROR_INVALID_DATA; 1601 } 1602 1603 struct pldm_header_info header = { 0 }; 1604 header.instance = instance_id; 1605 header.msg_type = PLDM_REQUEST; 1606 header.pldm_type = PLDM_FWUP; 1607 header.command = PLDM_REQUEST_UPDATE; 1608 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1609 if (rc) { 1610 return rc; 1611 } 1612 1613 struct pldm_request_update_req *request = 1614 (struct pldm_request_update_req *)msg->payload; 1615 1616 request->max_transfer_size = htole32(max_transfer_size); 1617 request->num_of_comp = htole16(num_of_comp); 1618 request->max_outstanding_transfer_req = max_outstanding_transfer_req; 1619 request->pkg_data_len = htole16(pkg_data_len); 1620 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type; 1621 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len; 1622 1623 memcpy(msg->payload + sizeof(struct pldm_request_update_req), 1624 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length); 1625 1626 return PLDM_SUCCESS; 1627 } 1628 1629 LIBPLDM_ABI_TESTING 1630 int decode_request_update_req(const struct pldm_msg *msg, size_t payload_length, 1631 struct pldm_request_update_req_full *req) 1632 { 1633 int rc; 1634 uint8_t t; 1635 struct pldm_msgbuf _buf; 1636 struct pldm_msgbuf *buf = &_buf; 1637 1638 if (msg == NULL || req == NULL) { 1639 return -EINVAL; 1640 } 1641 1642 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length); 1643 if (rc) { 1644 return rc; 1645 } 1646 1647 pldm_msgbuf_extract(buf, req->max_transfer_size); 1648 pldm_msgbuf_extract(buf, req->num_of_comp); 1649 pldm_msgbuf_extract(buf, req->max_outstanding_transfer_req); 1650 pldm_msgbuf_extract(buf, req->pkg_data_len); 1651 rc = pldm_msgbuf_extract(buf, t); 1652 if (rc) { 1653 return rc; 1654 } 1655 if (t > PLDM_STR_TYPE_UTF_16BE) { 1656 return -EBADMSG; 1657 } 1658 req->image_set_ver.str_type = (enum pldm_firmware_update_string_type)t; 1659 pldm_msgbuf_extract(buf, req->image_set_ver.str_len); 1660 if (rc) { 1661 return rc; 1662 } 1663 1664 rc = pldm_msgbuf_extract_array(buf, req->image_set_ver.str_len, 1665 req->image_set_ver.str_data, 1666 PLDM_FIRMWARE_MAX_STRING); 1667 if (rc) { 1668 return rc; 1669 } 1670 1671 return pldm_msgbuf_destroy_consumed(buf); 1672 } 1673 1674 LIBPLDM_ABI_STABLE 1675 int decode_request_update_resp(const struct pldm_msg *msg, 1676 size_t payload_length, uint8_t *completion_code, 1677 uint16_t *fd_meta_data_len, 1678 uint8_t *fd_will_send_pkg_data) 1679 { 1680 if (msg == NULL || completion_code == NULL || 1681 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL || 1682 !payload_length) { 1683 return PLDM_ERROR_INVALID_DATA; 1684 } 1685 1686 *completion_code = msg->payload[0]; 1687 if (*completion_code != PLDM_SUCCESS) { 1688 return PLDM_SUCCESS; 1689 } 1690 1691 if (payload_length != sizeof(struct pldm_request_update_resp)) { 1692 return PLDM_ERROR_INVALID_LENGTH; 1693 } 1694 1695 struct pldm_request_update_resp *response = 1696 (struct pldm_request_update_resp *)msg->payload; 1697 1698 *fd_meta_data_len = le16toh(response->fd_meta_data_len); 1699 *fd_will_send_pkg_data = response->fd_will_send_pkg_data; 1700 1701 return PLDM_SUCCESS; 1702 } 1703 1704 LIBPLDM_ABI_TESTING 1705 int encode_request_update_resp(uint8_t instance_id, 1706 const struct pldm_request_update_resp *resp_data, 1707 struct pldm_msg *msg, size_t *payload_length) 1708 { 1709 int rc; 1710 struct pldm_msgbuf _buf; 1711 struct pldm_msgbuf *buf = &_buf; 1712 1713 if (msg == NULL || payload_length == NULL) { 1714 return -EINVAL; 1715 } 1716 1717 struct pldm_header_info header = { 1718 .instance = instance_id, 1719 .msg_type = PLDM_RESPONSE, 1720 .pldm_type = PLDM_FWUP, 1721 .command = PLDM_REQUEST_UPDATE, 1722 }; 1723 rc = pack_pldm_header(&header, &(msg->hdr)); 1724 if (rc) { 1725 return -EINVAL; 1726 } 1727 1728 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 1729 if (rc) { 1730 return rc; 1731 } 1732 1733 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 1734 pldm_msgbuf_insert(buf, resp_data->fd_meta_data_len); 1735 pldm_msgbuf_insert(buf, resp_data->fd_will_send_pkg_data); 1736 1737 /* TODO: DSP0267 1.3.0 adds GetPackageDataMaximumTransferSize */ 1738 1739 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 1740 } 1741 1742 LIBPLDM_ABI_STABLE 1743 int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag, 1744 uint16_t comp_classification, 1745 uint16_t comp_identifier, 1746 uint8_t comp_classification_index, 1747 uint32_t comp_comparison_stamp, 1748 uint8_t comp_ver_str_type, 1749 uint8_t comp_ver_str_len, 1750 const struct variable_field *comp_ver_str, 1751 struct pldm_msg *msg, size_t payload_length) 1752 { 1753 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) { 1754 return PLDM_ERROR_INVALID_DATA; 1755 } 1756 1757 if (payload_length != sizeof(struct pldm_pass_component_table_req) + 1758 comp_ver_str->length) { 1759 return PLDM_ERROR_INVALID_LENGTH; 1760 } 1761 1762 if ((comp_ver_str_len == 0) || 1763 (comp_ver_str_len != comp_ver_str->length)) { 1764 return PLDM_ERROR_INVALID_DATA; 1765 } 1766 1767 if (!is_transfer_flag_valid(transfer_flag)) { 1768 return PLDM_INVALID_TRANSFER_OPERATION_FLAG; 1769 } 1770 1771 if (!is_string_type_valid(comp_ver_str_type)) { 1772 return PLDM_ERROR_INVALID_DATA; 1773 } 1774 1775 struct pldm_header_info header = { 0 }; 1776 header.instance = instance_id; 1777 header.msg_type = PLDM_REQUEST; 1778 header.pldm_type = PLDM_FWUP; 1779 header.command = PLDM_PASS_COMPONENT_TABLE; 1780 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1781 if (rc) { 1782 return rc; 1783 } 1784 1785 struct pldm_pass_component_table_req *request = 1786 (struct pldm_pass_component_table_req *)msg->payload; 1787 1788 request->transfer_flag = transfer_flag; 1789 request->comp_classification = htole16(comp_classification); 1790 request->comp_identifier = htole16(comp_identifier); 1791 request->comp_classification_index = comp_classification_index; 1792 request->comp_comparison_stamp = htole32(comp_comparison_stamp); 1793 request->comp_ver_str_type = comp_ver_str_type; 1794 request->comp_ver_str_len = comp_ver_str_len; 1795 1796 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req), 1797 comp_ver_str->ptr, comp_ver_str->length); 1798 1799 return PLDM_SUCCESS; 1800 } 1801 1802 LIBPLDM_ABI_TESTING 1803 int decode_pass_component_table_req( 1804 const struct pldm_msg *msg, size_t payload_length, 1805 struct pldm_pass_component_table_req_full *pcomp) 1806 { 1807 int rc; 1808 uint8_t t; 1809 struct pldm_msgbuf _buf; 1810 struct pldm_msgbuf *buf = &_buf; 1811 1812 if (msg == NULL || pcomp == NULL) { 1813 return -EINVAL; 1814 } 1815 1816 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length); 1817 if (rc) { 1818 return rc; 1819 } 1820 1821 pldm_msgbuf_extract(buf, pcomp->transfer_flag); 1822 pldm_msgbuf_extract(buf, pcomp->comp_classification); 1823 pldm_msgbuf_extract(buf, pcomp->comp_identifier); 1824 pldm_msgbuf_extract(buf, pcomp->comp_classification_index); 1825 pldm_msgbuf_extract(buf, pcomp->comp_comparison_stamp); 1826 rc = pldm_msgbuf_extract(buf, t); 1827 if (rc) { 1828 return rc; 1829 } 1830 if (t > PLDM_STR_TYPE_UTF_16BE) { 1831 return -EBADMSG; 1832 } 1833 pcomp->version.str_type = (enum pldm_firmware_update_string_type)t; 1834 rc = pldm_msgbuf_extract(buf, pcomp->version.str_len); 1835 if (rc) { 1836 return rc; 1837 } 1838 rc = pldm_msgbuf_extract_array(buf, pcomp->version.str_len, 1839 pcomp->version.str_data, 1840 PLDM_FIRMWARE_MAX_STRING); 1841 if (rc) { 1842 return rc; 1843 } 1844 1845 return pldm_msgbuf_destroy_consumed(buf); 1846 } 1847 1848 LIBPLDM_ABI_STABLE 1849 int decode_pass_component_table_resp(const struct pldm_msg *msg, 1850 const size_t payload_length, 1851 uint8_t *completion_code, 1852 uint8_t *comp_resp, 1853 uint8_t *comp_resp_code) 1854 { 1855 if (msg == NULL || completion_code == NULL || comp_resp == NULL || 1856 comp_resp_code == NULL || !payload_length) { 1857 return PLDM_ERROR_INVALID_DATA; 1858 } 1859 1860 *completion_code = msg->payload[0]; 1861 if (*completion_code != PLDM_SUCCESS) { 1862 return PLDM_SUCCESS; 1863 } 1864 1865 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) { 1866 return PLDM_ERROR_INVALID_LENGTH; 1867 } 1868 1869 struct pldm_pass_component_table_resp *response = 1870 (struct pldm_pass_component_table_resp *)msg->payload; 1871 1872 if (!is_comp_resp_valid(response->comp_resp)) { 1873 return PLDM_ERROR_INVALID_DATA; 1874 } 1875 1876 if (!is_comp_resp_code_valid(response->comp_resp_code)) { 1877 return PLDM_ERROR_INVALID_DATA; 1878 } 1879 1880 *comp_resp = response->comp_resp; 1881 *comp_resp_code = response->comp_resp_code; 1882 1883 return PLDM_SUCCESS; 1884 } 1885 1886 LIBPLDM_ABI_TESTING 1887 int encode_pass_component_table_resp( 1888 uint8_t instance_id, 1889 const struct pldm_pass_component_table_resp *resp_data, 1890 struct pldm_msg *msg, size_t *payload_length) 1891 { 1892 int rc; 1893 struct pldm_msgbuf _buf; 1894 struct pldm_msgbuf *buf = &_buf; 1895 1896 if (msg == NULL || payload_length == NULL) { 1897 return -EINVAL; 1898 } 1899 1900 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 1901 PLDM_PASS_COMPONENT_TABLE, msg); 1902 if (rc) { 1903 return -EINVAL; 1904 } 1905 1906 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 1907 if (rc) { 1908 return rc; 1909 } 1910 1911 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 1912 pldm_msgbuf_insert(buf, resp_data->comp_resp); 1913 pldm_msgbuf_insert(buf, resp_data->comp_resp_code); 1914 1915 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 1916 } 1917 1918 LIBPLDM_ABI_STABLE 1919 int encode_update_component_req( 1920 uint8_t instance_id, uint16_t comp_classification, 1921 uint16_t comp_identifier, uint8_t comp_classification_index, 1922 uint32_t comp_comparison_stamp, uint32_t comp_image_size, 1923 bitfield32_t update_option_flags, uint8_t comp_ver_str_type, 1924 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str, 1925 struct pldm_msg *msg, size_t payload_length) 1926 { 1927 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) { 1928 return PLDM_ERROR_INVALID_DATA; 1929 } 1930 1931 if (payload_length != 1932 sizeof(struct pldm_update_component_req) + comp_ver_str->length) { 1933 return PLDM_ERROR_INVALID_LENGTH; 1934 } 1935 1936 if (!comp_image_size) { 1937 return PLDM_ERROR_INVALID_DATA; 1938 } 1939 1940 if ((comp_ver_str_len == 0) || 1941 (comp_ver_str_len != comp_ver_str->length)) { 1942 return PLDM_ERROR_INVALID_DATA; 1943 } 1944 1945 if (!is_string_type_valid(comp_ver_str_type)) { 1946 return PLDM_ERROR_INVALID_DATA; 1947 } 1948 1949 struct pldm_header_info header = { 0 }; 1950 header.instance = instance_id; 1951 header.msg_type = PLDM_REQUEST; 1952 header.pldm_type = PLDM_FWUP; 1953 header.command = PLDM_UPDATE_COMPONENT; 1954 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1955 if (rc) { 1956 return rc; 1957 } 1958 1959 struct pldm_update_component_req *request = 1960 (struct pldm_update_component_req *)msg->payload; 1961 1962 request->comp_classification = htole16(comp_classification); 1963 request->comp_identifier = htole16(comp_identifier); 1964 request->comp_classification_index = comp_classification_index; 1965 request->comp_comparison_stamp = htole32(comp_comparison_stamp); 1966 request->comp_image_size = htole32(comp_image_size); 1967 request->update_option_flags.value = htole32(update_option_flags.value); 1968 request->comp_ver_str_type = comp_ver_str_type; 1969 request->comp_ver_str_len = comp_ver_str_len; 1970 1971 memcpy(msg->payload + sizeof(struct pldm_update_component_req), 1972 comp_ver_str->ptr, comp_ver_str->length); 1973 1974 return PLDM_SUCCESS; 1975 } 1976 1977 LIBPLDM_ABI_TESTING 1978 int decode_update_component_req(const struct pldm_msg *msg, 1979 size_t payload_length, 1980 struct pldm_update_component_req_full *up) 1981 { 1982 int rc; 1983 uint8_t t; 1984 struct pldm_msgbuf _buf; 1985 struct pldm_msgbuf *buf = &_buf; 1986 1987 if (msg == NULL || up == NULL) { 1988 return -EINVAL; 1989 } 1990 1991 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length); 1992 if (rc) { 1993 return rc; 1994 } 1995 1996 pldm_msgbuf_extract(buf, up->comp_classification); 1997 pldm_msgbuf_extract(buf, up->comp_identifier); 1998 pldm_msgbuf_extract(buf, up->comp_classification_index); 1999 pldm_msgbuf_extract(buf, up->comp_comparison_stamp); 2000 pldm_msgbuf_extract(buf, up->comp_image_size); 2001 pldm_msgbuf_extract(buf, up->update_option_flags.value); 2002 rc = pldm_msgbuf_extract(buf, t); 2003 if (rc) { 2004 return rc; 2005 } 2006 if (t > PLDM_STR_TYPE_UTF_16BE) { 2007 return -EBADMSG; 2008 } 2009 up->version.str_type = (enum pldm_firmware_update_string_type)t; 2010 rc = pldm_msgbuf_extract(buf, up->version.str_len); 2011 if (rc) { 2012 return rc; 2013 } 2014 rc = pldm_msgbuf_extract_array(buf, up->version.str_len, 2015 up->version.str_data, 2016 PLDM_FIRMWARE_MAX_STRING); 2017 if (rc) { 2018 return rc; 2019 } 2020 2021 if (buf->remaining != 0) { 2022 return -EINVAL; 2023 } 2024 2025 return 0; 2026 } 2027 2028 LIBPLDM_ABI_STABLE 2029 int decode_update_component_resp(const struct pldm_msg *msg, 2030 size_t payload_length, 2031 uint8_t *completion_code, 2032 uint8_t *comp_compatibility_resp, 2033 uint8_t *comp_compatibility_resp_code, 2034 bitfield32_t *update_option_flags_enabled, 2035 uint16_t *time_before_req_fw_data) 2036 { 2037 if (msg == NULL || completion_code == NULL || 2038 comp_compatibility_resp == NULL || 2039 comp_compatibility_resp_code == NULL || 2040 update_option_flags_enabled == NULL || 2041 time_before_req_fw_data == NULL || !payload_length) { 2042 return PLDM_ERROR_INVALID_DATA; 2043 } 2044 2045 *completion_code = msg->payload[0]; 2046 if (*completion_code != PLDM_SUCCESS) { 2047 return PLDM_SUCCESS; 2048 } 2049 2050 if (payload_length != sizeof(struct pldm_update_component_resp)) { 2051 return PLDM_ERROR_INVALID_LENGTH; 2052 } 2053 2054 struct pldm_update_component_resp *response = 2055 (struct pldm_update_component_resp *)msg->payload; 2056 2057 if (!is_comp_compatibility_resp_valid( 2058 response->comp_compatibility_resp)) { 2059 return PLDM_ERROR_INVALID_DATA; 2060 } 2061 2062 if (!is_comp_compatibility_resp_code_valid( 2063 response->comp_compatibility_resp_code)) { 2064 return PLDM_ERROR_INVALID_DATA; 2065 } 2066 2067 *comp_compatibility_resp = response->comp_compatibility_resp; 2068 *comp_compatibility_resp_code = response->comp_compatibility_resp_code; 2069 update_option_flags_enabled->value = 2070 le32toh(response->update_option_flags_enabled.value); 2071 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data); 2072 2073 return PLDM_SUCCESS; 2074 } 2075 2076 LIBPLDM_ABI_TESTING 2077 int encode_update_component_resp( 2078 uint8_t instance_id, const struct pldm_update_component_resp *resp_data, 2079 struct pldm_msg *msg, size_t *payload_length) 2080 { 2081 int rc; 2082 struct pldm_msgbuf _buf; 2083 struct pldm_msgbuf *buf = &_buf; 2084 2085 if (msg == NULL || payload_length == NULL) { 2086 return -EINVAL; 2087 } 2088 2089 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 2090 PLDM_UPDATE_COMPONENT, msg); 2091 if (rc) { 2092 return -EINVAL; 2093 } 2094 2095 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2096 if (rc) { 2097 return rc; 2098 } 2099 2100 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 2101 pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp); 2102 pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp_code); 2103 pldm_msgbuf_insert(buf, resp_data->update_option_flags_enabled.value); 2104 pldm_msgbuf_insert(buf, resp_data->time_before_req_fw_data); 2105 2106 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 2107 } 2108 2109 LIBPLDM_ABI_STABLE 2110 int decode_request_firmware_data_req(const struct pldm_msg *msg, 2111 size_t payload_length, uint32_t *offset, 2112 uint32_t *length) 2113 { 2114 if (msg == NULL || offset == NULL || length == NULL) { 2115 return PLDM_ERROR_INVALID_DATA; 2116 } 2117 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) { 2118 return PLDM_ERROR_INVALID_LENGTH; 2119 } 2120 struct pldm_request_firmware_data_req *request = 2121 (struct pldm_request_firmware_data_req *)msg->payload; 2122 *offset = le32toh(request->offset); 2123 *length = le32toh(request->length); 2124 2125 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) { 2126 return PLDM_FWUP_INVALID_TRANSFER_LENGTH; 2127 } 2128 2129 return PLDM_SUCCESS; 2130 } 2131 2132 LIBPLDM_ABI_TESTING 2133 int encode_request_firmware_data_req( 2134 uint8_t instance_id, 2135 const struct pldm_request_firmware_data_req *req_params, 2136 struct pldm_msg *msg, size_t *payload_length) 2137 { 2138 int rc; 2139 struct pldm_msgbuf _buf; 2140 struct pldm_msgbuf *buf = &_buf; 2141 2142 if (msg == NULL || payload_length == NULL) { 2143 return -EINVAL; 2144 } 2145 2146 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 2147 PLDM_REQUEST_FIRMWARE_DATA, 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(buf, req_params->offset); 2158 pldm_msgbuf_insert(buf, req_params->length); 2159 2160 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 2161 } 2162 2163 LIBPLDM_ABI_STABLE 2164 int encode_request_firmware_data_resp(uint8_t instance_id, 2165 uint8_t completion_code, 2166 struct pldm_msg *msg, 2167 size_t payload_length) 2168 { 2169 if (msg == NULL || !payload_length) { 2170 return PLDM_ERROR_INVALID_DATA; 2171 } 2172 2173 struct pldm_header_info header = { 0 }; 2174 header.instance = instance_id; 2175 header.msg_type = PLDM_RESPONSE; 2176 header.pldm_type = PLDM_FWUP; 2177 header.command = PLDM_REQUEST_FIRMWARE_DATA; 2178 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2179 if (rc) { 2180 return rc; 2181 } 2182 2183 msg->payload[0] = completion_code; 2184 2185 return PLDM_SUCCESS; 2186 } 2187 2188 LIBPLDM_ABI_STABLE 2189 int decode_transfer_complete_req(const struct pldm_msg *msg, 2190 size_t payload_length, 2191 uint8_t *transfer_result) 2192 { 2193 if (msg == NULL || transfer_result == NULL) { 2194 return PLDM_ERROR_INVALID_DATA; 2195 } 2196 2197 if (payload_length != sizeof(*transfer_result)) { 2198 return PLDM_ERROR_INVALID_LENGTH; 2199 } 2200 2201 *transfer_result = msg->payload[0]; 2202 return PLDM_SUCCESS; 2203 } 2204 2205 LIBPLDM_ABI_TESTING 2206 int encode_transfer_complete_req(uint8_t instance_id, uint8_t transfer_result, 2207 struct pldm_msg *msg, size_t *payload_length) 2208 { 2209 int rc; 2210 struct pldm_msgbuf _buf; 2211 struct pldm_msgbuf *buf = &_buf; 2212 2213 if (msg == NULL || payload_length == NULL) { 2214 return -EINVAL; 2215 } 2216 2217 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 2218 PLDM_TRANSFER_COMPLETE, msg); 2219 if (rc) { 2220 return -EINVAL; 2221 } 2222 2223 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2224 if (rc) { 2225 return rc; 2226 } 2227 2228 rc = pldm_msgbuf_insert(buf, transfer_result); 2229 if (rc) { 2230 return rc; 2231 } 2232 2233 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 2234 } 2235 2236 LIBPLDM_ABI_STABLE 2237 int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code, 2238 struct pldm_msg *msg, size_t payload_length) 2239 { 2240 if (msg == NULL) { 2241 return PLDM_ERROR_INVALID_DATA; 2242 } 2243 2244 if (payload_length != sizeof(completion_code)) { 2245 return PLDM_ERROR_INVALID_LENGTH; 2246 } 2247 2248 struct pldm_header_info header = { 0 }; 2249 header.instance = instance_id; 2250 header.msg_type = PLDM_RESPONSE; 2251 header.pldm_type = PLDM_FWUP; 2252 header.command = PLDM_TRANSFER_COMPLETE; 2253 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2254 if (rc) { 2255 return rc; 2256 } 2257 2258 msg->payload[0] = completion_code; 2259 2260 return PLDM_SUCCESS; 2261 } 2262 2263 LIBPLDM_ABI_STABLE 2264 int decode_verify_complete_req(const struct pldm_msg *msg, 2265 size_t payload_length, uint8_t *verify_result) 2266 { 2267 if (msg == NULL || verify_result == NULL) { 2268 return PLDM_ERROR_INVALID_DATA; 2269 } 2270 2271 if (payload_length != sizeof(*verify_result)) { 2272 return PLDM_ERROR_INVALID_LENGTH; 2273 } 2274 2275 *verify_result = msg->payload[0]; 2276 return PLDM_SUCCESS; 2277 } 2278 2279 LIBPLDM_ABI_TESTING 2280 int encode_verify_complete_req(uint8_t instance_id, uint8_t verify_result, 2281 struct pldm_msg *msg, size_t *payload_length) 2282 { 2283 int rc; 2284 struct pldm_msgbuf _buf; 2285 struct pldm_msgbuf *buf = &_buf; 2286 2287 if (msg == NULL || payload_length == NULL) { 2288 return -EINVAL; 2289 } 2290 2291 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 2292 PLDM_VERIFY_COMPLETE, msg); 2293 if (rc) { 2294 return EINVAL; 2295 } 2296 2297 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2298 if (rc) { 2299 return rc; 2300 } 2301 2302 rc = pldm_msgbuf_insert(buf, verify_result); 2303 if (rc) { 2304 return rc; 2305 } 2306 2307 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 2308 } 2309 2310 LIBPLDM_ABI_STABLE 2311 int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code, 2312 struct pldm_msg *msg, size_t payload_length) 2313 { 2314 if (msg == NULL) { 2315 return PLDM_ERROR_INVALID_DATA; 2316 } 2317 2318 if (payload_length != sizeof(completion_code)) { 2319 return PLDM_ERROR_INVALID_LENGTH; 2320 } 2321 2322 struct pldm_header_info header = { 0 }; 2323 header.instance = instance_id; 2324 header.msg_type = PLDM_RESPONSE; 2325 header.pldm_type = PLDM_FWUP; 2326 header.command = PLDM_VERIFY_COMPLETE; 2327 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2328 if (rc) { 2329 return rc; 2330 } 2331 2332 msg->payload[0] = completion_code; 2333 2334 return PLDM_SUCCESS; 2335 } 2336 2337 LIBPLDM_ABI_STABLE 2338 int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length, 2339 uint8_t *apply_result, 2340 bitfield16_t *comp_activation_methods_modification) 2341 { 2342 if (msg == NULL || apply_result == NULL || 2343 comp_activation_methods_modification == NULL) { 2344 return PLDM_ERROR_INVALID_DATA; 2345 } 2346 2347 if (payload_length != sizeof(struct pldm_apply_complete_req)) { 2348 return PLDM_ERROR_INVALID_LENGTH; 2349 } 2350 2351 struct pldm_apply_complete_req *request = 2352 (struct pldm_apply_complete_req *)msg->payload; 2353 2354 *apply_result = request->apply_result; 2355 comp_activation_methods_modification->value = 2356 le16toh(request->comp_activation_methods_modification.value); 2357 2358 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) && 2359 comp_activation_methods_modification->value) { 2360 return PLDM_ERROR_INVALID_DATA; 2361 } 2362 2363 return PLDM_SUCCESS; 2364 } 2365 2366 LIBPLDM_ABI_TESTING 2367 int encode_apply_complete_req(uint8_t instance_id, 2368 const struct pldm_apply_complete_req *req_data, 2369 struct pldm_msg *msg, size_t *payload_length) 2370 { 2371 int rc; 2372 struct pldm_msgbuf _buf; 2373 struct pldm_msgbuf *buf = &_buf; 2374 2375 if (msg == NULL || payload_length == NULL) { 2376 return -EINVAL; 2377 } 2378 2379 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 2380 PLDM_APPLY_COMPLETE, msg); 2381 if (rc) { 2382 return -EINVAL; 2383 } 2384 2385 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2386 if (rc) { 2387 return rc; 2388 } 2389 2390 pldm_msgbuf_insert(buf, req_data->apply_result); 2391 pldm_msgbuf_insert( 2392 buf, req_data->comp_activation_methods_modification.value); 2393 2394 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 2395 } 2396 2397 LIBPLDM_ABI_STABLE 2398 int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code, 2399 struct pldm_msg *msg, size_t payload_length) 2400 { 2401 if (msg == NULL) { 2402 return PLDM_ERROR_INVALID_DATA; 2403 } 2404 2405 if (payload_length != sizeof(completion_code)) { 2406 return PLDM_ERROR_INVALID_LENGTH; 2407 } 2408 2409 struct pldm_header_info header = { 0 }; 2410 header.instance = instance_id; 2411 header.msg_type = PLDM_RESPONSE; 2412 header.pldm_type = PLDM_FWUP; 2413 header.command = PLDM_APPLY_COMPLETE; 2414 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2415 if (rc) { 2416 return rc; 2417 } 2418 2419 msg->payload[0] = completion_code; 2420 2421 return PLDM_SUCCESS; 2422 } 2423 2424 LIBPLDM_ABI_TESTING 2425 int decode_activate_firmware_req(const struct pldm_msg *msg, 2426 size_t payload_length, bool *self_contained) 2427 { 2428 int rc; 2429 struct pldm_msgbuf _buf; 2430 struct pldm_msgbuf *buf = &_buf; 2431 2432 if (msg == NULL || self_contained == NULL) { 2433 return -EINVAL; 2434 } 2435 2436 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length); 2437 if (rc) { 2438 return 0; 2439 } 2440 2441 uint8_t self_contained_u8 = 0; 2442 rc = pldm_msgbuf_extract(buf, self_contained_u8); 2443 if (rc) { 2444 return rc; 2445 } 2446 if (buf->remaining != 0) { 2447 return -EOVERFLOW; 2448 } 2449 *self_contained = (bool)self_contained_u8; 2450 return 0; 2451 } 2452 2453 LIBPLDM_ABI_STABLE 2454 int encode_activate_firmware_req(uint8_t instance_id, 2455 bool8_t self_contained_activation_req, 2456 struct pldm_msg *msg, size_t payload_length) 2457 { 2458 if (msg == NULL) { 2459 return PLDM_ERROR_INVALID_DATA; 2460 } 2461 2462 if (payload_length != sizeof(struct pldm_activate_firmware_req)) { 2463 return PLDM_ERROR_INVALID_LENGTH; 2464 } 2465 2466 if (!is_self_contained_activation_req_valid( 2467 self_contained_activation_req)) { 2468 return PLDM_ERROR_INVALID_DATA; 2469 } 2470 2471 struct pldm_header_info header = { 0 }; 2472 header.instance = instance_id; 2473 header.msg_type = PLDM_REQUEST; 2474 header.pldm_type = PLDM_FWUP; 2475 header.command = PLDM_ACTIVATE_FIRMWARE; 2476 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2477 if (rc) { 2478 return rc; 2479 } 2480 2481 struct pldm_activate_firmware_req *request = 2482 (struct pldm_activate_firmware_req *)msg->payload; 2483 2484 request->self_contained_activation_req = self_contained_activation_req; 2485 2486 return PLDM_SUCCESS; 2487 } 2488 2489 LIBPLDM_ABI_STABLE 2490 int decode_activate_firmware_resp(const struct pldm_msg *msg, 2491 size_t payload_length, 2492 uint8_t *completion_code, 2493 uint16_t *estimated_time_activation) 2494 { 2495 if (msg == NULL || completion_code == NULL || 2496 estimated_time_activation == NULL || !payload_length) { 2497 return PLDM_ERROR_INVALID_DATA; 2498 } 2499 2500 *completion_code = msg->payload[0]; 2501 if (*completion_code != PLDM_SUCCESS) { 2502 return PLDM_SUCCESS; 2503 } 2504 2505 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) { 2506 return PLDM_ERROR_INVALID_LENGTH; 2507 } 2508 2509 struct pldm_activate_firmware_resp *response = 2510 (struct pldm_activate_firmware_resp *)msg->payload; 2511 2512 *estimated_time_activation = 2513 le16toh(response->estimated_time_activation); 2514 2515 return PLDM_SUCCESS; 2516 } 2517 2518 LIBPLDM_ABI_TESTING 2519 int encode_activate_firmware_resp( 2520 uint8_t instance_id, 2521 const struct pldm_activate_firmware_resp *resp_data, 2522 struct pldm_msg *msg, size_t *payload_length) 2523 { 2524 int rc; 2525 struct pldm_msgbuf _buf; 2526 struct pldm_msgbuf *buf = &_buf; 2527 2528 if (msg == NULL || payload_length == NULL) { 2529 return -EINVAL; 2530 } 2531 2532 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 2533 PLDM_ACTIVATE_FIRMWARE, msg); 2534 if (rc) { 2535 return -EINVAL; 2536 } 2537 2538 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2539 if (rc) { 2540 return rc; 2541 } 2542 2543 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 2544 pldm_msgbuf_insert(buf, resp_data->estimated_time_activation); 2545 2546 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 2547 } 2548 2549 LIBPLDM_ABI_STABLE 2550 int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg, 2551 size_t payload_length) 2552 { 2553 if (msg == NULL) { 2554 return PLDM_ERROR_INVALID_DATA; 2555 } 2556 2557 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) { 2558 return PLDM_ERROR_INVALID_LENGTH; 2559 } 2560 2561 struct pldm_header_info header = { 0 }; 2562 header.instance = instance_id; 2563 header.msg_type = PLDM_REQUEST; 2564 header.pldm_type = PLDM_FWUP; 2565 header.command = PLDM_GET_STATUS; 2566 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2567 if (rc) { 2568 return rc; 2569 } 2570 2571 return PLDM_SUCCESS; 2572 } 2573 2574 LIBPLDM_ABI_STABLE 2575 int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length, 2576 uint8_t *completion_code, uint8_t *current_state, 2577 uint8_t *previous_state, uint8_t *aux_state, 2578 uint8_t *aux_state_status, uint8_t *progress_percent, 2579 uint8_t *reason_code, 2580 bitfield32_t *update_option_flags_enabled) 2581 { 2582 if (msg == NULL || completion_code == NULL || current_state == NULL || 2583 previous_state == NULL || aux_state == NULL || 2584 aux_state_status == NULL || progress_percent == NULL || 2585 reason_code == NULL || update_option_flags_enabled == NULL || 2586 !payload_length) { 2587 return PLDM_ERROR_INVALID_DATA; 2588 } 2589 2590 *completion_code = msg->payload[0]; 2591 if (*completion_code != PLDM_SUCCESS) { 2592 return PLDM_SUCCESS; 2593 } 2594 2595 if (payload_length != sizeof(struct pldm_get_status_resp)) { 2596 return PLDM_ERROR_INVALID_LENGTH; 2597 } 2598 struct pldm_get_status_resp *response = 2599 (struct pldm_get_status_resp *)msg->payload; 2600 2601 if (!is_state_valid(response->current_state)) { 2602 return PLDM_ERROR_INVALID_DATA; 2603 } 2604 if (!is_state_valid(response->previous_state)) { 2605 return PLDM_ERROR_INVALID_DATA; 2606 } 2607 if (!is_aux_state_valid(response->aux_state)) { 2608 return PLDM_ERROR_INVALID_DATA; 2609 } 2610 if (!is_aux_state_status_valid(response->aux_state_status)) { 2611 return PLDM_ERROR_INVALID_DATA; 2612 } 2613 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) { 2614 return PLDM_ERROR_INVALID_DATA; 2615 } 2616 if (!is_reason_code_valid(response->reason_code)) { 2617 return PLDM_ERROR_INVALID_DATA; 2618 } 2619 2620 if ((response->current_state == PLDM_FD_STATE_IDLE) || 2621 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) || 2622 (response->current_state == PLDM_FD_STATE_READY_XFER)) { 2623 if (response->aux_state != 2624 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) { 2625 return PLDM_ERROR_INVALID_DATA; 2626 } 2627 } 2628 2629 *current_state = response->current_state; 2630 *previous_state = response->previous_state; 2631 *aux_state = response->aux_state; 2632 *aux_state_status = response->aux_state_status; 2633 *progress_percent = response->progress_percent; 2634 *reason_code = response->reason_code; 2635 update_option_flags_enabled->value = 2636 le32toh(response->update_option_flags_enabled.value); 2637 2638 return PLDM_SUCCESS; 2639 } 2640 2641 LIBPLDM_ABI_TESTING 2642 int encode_get_status_resp(uint8_t instance_id, 2643 const struct pldm_get_status_resp *status, 2644 struct pldm_msg *msg, size_t *payload_length) 2645 { 2646 int rc; 2647 struct pldm_msgbuf _buf; 2648 struct pldm_msgbuf *buf = &_buf; 2649 2650 if (status == NULL || msg == NULL || payload_length == NULL) { 2651 return -EINVAL; 2652 } 2653 2654 if (status->completion_code != PLDM_SUCCESS) { 2655 return -EINVAL; 2656 } 2657 2658 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 2659 PLDM_GET_STATUS, msg); 2660 if (rc) { 2661 return -EINVAL; 2662 } 2663 2664 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2665 if (rc) { 2666 return rc; 2667 } 2668 2669 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 2670 pldm_msgbuf_insert(buf, status->current_state); 2671 pldm_msgbuf_insert(buf, status->previous_state); 2672 pldm_msgbuf_insert(buf, status->aux_state); 2673 pldm_msgbuf_insert(buf, status->aux_state_status); 2674 pldm_msgbuf_insert(buf, status->progress_percent); 2675 pldm_msgbuf_insert(buf, status->reason_code); 2676 pldm_msgbuf_insert(buf, status->update_option_flags_enabled.value); 2677 2678 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 2679 } 2680 2681 LIBPLDM_ABI_STABLE 2682 int encode_cancel_update_component_req(uint8_t instance_id, 2683 struct pldm_msg *msg, 2684 size_t payload_length) 2685 { 2686 if (msg == NULL) { 2687 return PLDM_ERROR_INVALID_DATA; 2688 } 2689 2690 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) { 2691 return PLDM_ERROR_INVALID_LENGTH; 2692 } 2693 2694 struct pldm_header_info header = { 0 }; 2695 header.instance = instance_id; 2696 header.msg_type = PLDM_REQUEST; 2697 header.pldm_type = PLDM_FWUP; 2698 header.command = PLDM_CANCEL_UPDATE_COMPONENT; 2699 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2700 if (rc) { 2701 return rc; 2702 } 2703 2704 return PLDM_SUCCESS; 2705 } 2706 2707 LIBPLDM_ABI_STABLE 2708 int decode_cancel_update_component_resp(const struct pldm_msg *msg, 2709 size_t payload_length, 2710 uint8_t *completion_code) 2711 { 2712 if (msg == NULL || completion_code == NULL) { 2713 return PLDM_ERROR_INVALID_DATA; 2714 } 2715 2716 if (payload_length != sizeof(*completion_code)) { 2717 return PLDM_ERROR_INVALID_LENGTH; 2718 } 2719 2720 *completion_code = msg->payload[0]; 2721 return PLDM_SUCCESS; 2722 } 2723 2724 LIBPLDM_ABI_STABLE 2725 int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg, 2726 size_t payload_length) 2727 { 2728 if (msg == NULL) { 2729 return PLDM_ERROR_INVALID_DATA; 2730 } 2731 2732 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) { 2733 return PLDM_ERROR_INVALID_LENGTH; 2734 } 2735 2736 struct pldm_header_info header = { 0 }; 2737 header.instance = instance_id; 2738 header.msg_type = PLDM_REQUEST; 2739 header.pldm_type = PLDM_FWUP; 2740 header.command = PLDM_CANCEL_UPDATE; 2741 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2742 if (rc) { 2743 return rc; 2744 } 2745 2746 return PLDM_SUCCESS; 2747 } 2748 2749 LIBPLDM_ABI_STABLE 2750 int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length, 2751 uint8_t *completion_code, 2752 bool8_t *non_functioning_component_indication, 2753 bitfield64_t *non_functioning_component_bitmap) 2754 { 2755 if (msg == NULL || completion_code == NULL || 2756 non_functioning_component_indication == NULL || 2757 non_functioning_component_bitmap == NULL || !payload_length) { 2758 return PLDM_ERROR_INVALID_DATA; 2759 } 2760 2761 *completion_code = msg->payload[0]; 2762 if (*completion_code != PLDM_SUCCESS) { 2763 return PLDM_SUCCESS; 2764 } 2765 2766 if (payload_length != sizeof(struct pldm_cancel_update_resp)) { 2767 return PLDM_ERROR_INVALID_LENGTH; 2768 } 2769 struct pldm_cancel_update_resp *response = 2770 (struct pldm_cancel_update_resp *)msg->payload; 2771 2772 if (!is_non_functioning_component_indication_valid( 2773 response->non_functioning_component_indication)) { 2774 return PLDM_ERROR_INVALID_DATA; 2775 } 2776 2777 *non_functioning_component_indication = 2778 response->non_functioning_component_indication; 2779 2780 if (*non_functioning_component_indication) { 2781 non_functioning_component_bitmap->value = 2782 le64toh(response->non_functioning_component_bitmap); 2783 } 2784 2785 return PLDM_SUCCESS; 2786 } 2787 2788 LIBPLDM_ABI_TESTING 2789 int encode_cancel_update_resp(uint8_t instance_id, 2790 const struct pldm_cancel_update_resp *resp_data, 2791 struct pldm_msg *msg, size_t *payload_length) 2792 { 2793 int rc; 2794 struct pldm_msgbuf _buf; 2795 struct pldm_msgbuf *buf = &_buf; 2796 2797 if (msg == NULL || payload_length == NULL) { 2798 return -EINVAL; 2799 } 2800 2801 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 2802 PLDM_CANCEL_UPDATE, msg); 2803 if (rc) { 2804 return -EINVAL; 2805 } 2806 2807 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2808 if (rc) { 2809 return rc; 2810 } 2811 2812 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 2813 pldm_msgbuf_insert(buf, 2814 resp_data->non_functioning_component_indication); 2815 pldm_msgbuf_insert(buf, resp_data->non_functioning_component_bitmap); 2816 2817 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 2818 } 2819