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