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 void *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 (const uint8_t *)data + 378 sizeof(struct pldm_package_header_information); 379 package_version_str->length = 380 package_header_info->package_version_string_length; 381 382 return 0; 383 } 384 385 LIBPLDM_ABI_STABLE 386 int decode_pldm_package_header_info( 387 const uint8_t *data, size_t length, 388 struct pldm_package_header_information *package_header_info, 389 struct variable_field *package_version_str) 390 { 391 int rc; 392 393 rc = decode_pldm_package_header_info_errno( 394 data, length, package_header_info, package_version_str); 395 if (rc < 0) { 396 return pldm_xlate_errno(rc); 397 } 398 399 return PLDM_SUCCESS; 400 } 401 402 static int decode_firmware_device_id_record_errno( 403 const void *data, size_t length, 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 (const uint8_t *)data + 467 sizeof(struct pldm_firmware_device_id_record); 468 applicable_components->length = applicable_components_length; 469 470 comp_image_set_version_str->ptr = 471 applicable_components->ptr + applicable_components->length; 472 comp_image_set_version_str->length = 473 fw_device_id_record->comp_image_set_version_string_length; 474 475 record_descriptors->ptr = comp_image_set_version_str->ptr + 476 comp_image_set_version_str->length; 477 record_descriptors->length = 478 fw_device_id_record->record_length - 479 sizeof(struct pldm_firmware_device_id_record) - 480 applicable_components_length - 481 fw_device_id_record->comp_image_set_version_string_length - 482 fw_device_id_record->fw_device_pkg_data_length; 483 484 if (fw_device_id_record->fw_device_pkg_data_length) { 485 fw_device_pkg_data->ptr = 486 record_descriptors->ptr + record_descriptors->length; 487 fw_device_pkg_data->length = 488 fw_device_id_record->fw_device_pkg_data_length; 489 } 490 491 return 0; 492 } 493 494 LIBPLDM_ABI_STABLE 495 int decode_firmware_device_id_record( 496 const uint8_t *data, size_t length, 497 uint16_t component_bitmap_bit_length, 498 struct pldm_firmware_device_id_record *fw_device_id_record, 499 struct variable_field *applicable_components, 500 struct variable_field *comp_image_set_version_str, 501 struct variable_field *record_descriptors, 502 struct variable_field *fw_device_pkg_data) 503 { 504 int rc; 505 506 rc = decode_firmware_device_id_record_errno( 507 data, length, component_bitmap_bit_length, fw_device_id_record, 508 applicable_components, comp_image_set_version_str, 509 record_descriptors, fw_device_pkg_data); 510 if (rc < 0) { 511 return pldm_xlate_errno(rc); 512 } 513 514 return PLDM_SUCCESS; 515 } 516 517 LIBPLDM_ABI_STABLE 518 int decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter *iter, 519 struct pldm_descriptor *desc) 520 { 521 PLDM_MSGBUF_DEFINE_P(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 pldm_msgbuf_discard(buf, 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_complete(buf); 548 } 549 550 static int decode_descriptor_type_length_value_errno( 551 const void *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 void *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 void *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 = (const uint8_t *)data + 724 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 PLDM_MSGBUF_DEFINE_P(buf); 820 int rc; 821 822 if (descriptors == NULL || msg == NULL || payload_length == NULL) { 823 return -EINVAL; 824 } 825 826 if (descriptor_count < 1) { 827 return -EINVAL; 828 } 829 830 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 831 PLDM_QUERY_DEVICE_IDENTIFIERS, msg); 832 if (rc) { 833 return -EINVAL; 834 } 835 836 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 837 if (rc) { 838 return rc; 839 } 840 841 /* Determine total length */ 842 uint32_t device_identifiers_len = 0; 843 for (uint8_t i = 0; i < descriptor_count; i++) { 844 const struct pldm_descriptor *d = &descriptors[i]; 845 device_identifiers_len += 846 2 * sizeof(uint16_t) + d->descriptor_length; 847 } 848 849 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 850 pldm_msgbuf_insert(buf, device_identifiers_len); 851 pldm_msgbuf_insert(buf, descriptor_count); 852 853 for (uint8_t i = 0; i < descriptor_count; i++) { 854 const struct pldm_descriptor *d = &descriptors[i]; 855 pldm_msgbuf_insert(buf, d->descriptor_type); 856 pldm_msgbuf_insert(buf, d->descriptor_length); 857 if (d->descriptor_data == NULL) { 858 return pldm_msgbuf_discard(buf, -EINVAL); 859 } 860 rc = pldm_msgbuf_insert_array( 861 buf, d->descriptor_length, 862 (const uint8_t *)d->descriptor_data, 863 d->descriptor_length); 864 if (rc) { 865 return pldm_msgbuf_discard(buf, rc); 866 } 867 } 868 869 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length); 870 } 871 872 LIBPLDM_ABI_STABLE 873 int encode_get_firmware_parameters_req(uint8_t instance_id, 874 size_t payload_length, 875 struct pldm_msg *msg) 876 { 877 if (msg == NULL) { 878 return PLDM_ERROR_INVALID_DATA; 879 } 880 881 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) { 882 return PLDM_ERROR_INVALID_LENGTH; 883 } 884 885 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 886 PLDM_GET_FIRMWARE_PARAMETERS, msg); 887 } 888 889 LIBPLDM_ABI_STABLE 890 int decode_get_firmware_parameters_resp( 891 const struct pldm_msg *msg, size_t payload_length, 892 struct pldm_get_firmware_parameters_resp *resp_data, 893 struct variable_field *active_comp_image_set_ver_str, 894 struct variable_field *pending_comp_image_set_ver_str, 895 struct variable_field *comp_parameter_table) 896 { 897 if (msg == NULL || resp_data == NULL || 898 active_comp_image_set_ver_str == NULL || 899 pending_comp_image_set_ver_str == NULL || 900 comp_parameter_table == NULL || !payload_length) { 901 return PLDM_ERROR_INVALID_DATA; 902 } 903 904 resp_data->completion_code = msg->payload[0]; 905 if (PLDM_SUCCESS != resp_data->completion_code) { 906 return PLDM_SUCCESS; 907 } 908 909 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) { 910 return PLDM_ERROR_INVALID_LENGTH; 911 } 912 913 struct pldm_get_firmware_parameters_resp *response = 914 (struct pldm_get_firmware_parameters_resp *)msg->payload; 915 916 if (!is_string_type_valid( 917 response->active_comp_image_set_ver_str_type) || 918 (response->active_comp_image_set_ver_str_len == 0)) { 919 return PLDM_ERROR_INVALID_DATA; 920 } 921 922 if (response->pending_comp_image_set_ver_str_len == 0) { 923 if (response->pending_comp_image_set_ver_str_type != 924 PLDM_STR_TYPE_UNKNOWN) { 925 return PLDM_ERROR_INVALID_DATA; 926 } 927 } else { 928 if (!is_string_type_valid( 929 response->pending_comp_image_set_ver_str_type)) { 930 return PLDM_ERROR_INVALID_DATA; 931 } 932 } 933 934 size_t partial_response_length = 935 sizeof(struct pldm_get_firmware_parameters_resp) + 936 response->active_comp_image_set_ver_str_len + 937 response->pending_comp_image_set_ver_str_len; 938 939 if (payload_length < partial_response_length) { 940 return PLDM_ERROR_INVALID_LENGTH; 941 } 942 943 resp_data->capabilities_during_update.value = 944 le32toh(response->capabilities_during_update.value); 945 resp_data->comp_count = le16toh(response->comp_count); 946 resp_data->active_comp_image_set_ver_str_type = 947 response->active_comp_image_set_ver_str_type; 948 resp_data->active_comp_image_set_ver_str_len = 949 response->active_comp_image_set_ver_str_len; 950 resp_data->pending_comp_image_set_ver_str_type = 951 response->pending_comp_image_set_ver_str_type; 952 resp_data->pending_comp_image_set_ver_str_len = 953 response->pending_comp_image_set_ver_str_len; 954 955 active_comp_image_set_ver_str->ptr = 956 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp); 957 active_comp_image_set_ver_str->length = 958 resp_data->active_comp_image_set_ver_str_len; 959 960 if (resp_data->pending_comp_image_set_ver_str_len != 0) { 961 pending_comp_image_set_ver_str->ptr = 962 msg->payload + 963 sizeof(struct pldm_get_firmware_parameters_resp) + 964 resp_data->active_comp_image_set_ver_str_len; 965 pending_comp_image_set_ver_str->length = 966 resp_data->pending_comp_image_set_ver_str_len; 967 } else { 968 pending_comp_image_set_ver_str->ptr = NULL; 969 pending_comp_image_set_ver_str->length = 0; 970 } 971 972 if (payload_length > partial_response_length && resp_data->comp_count) { 973 comp_parameter_table->ptr = 974 msg->payload + 975 sizeof(struct pldm_get_firmware_parameters_resp) + 976 resp_data->active_comp_image_set_ver_str_len + 977 resp_data->pending_comp_image_set_ver_str_len; 978 comp_parameter_table->length = 979 payload_length - partial_response_length; 980 } else { 981 comp_parameter_table->ptr = NULL; 982 comp_parameter_table->length = 0; 983 } 984 985 return PLDM_SUCCESS; 986 } 987 988 LIBPLDM_ABI_TESTING 989 int encode_get_firmware_parameters_resp( 990 uint8_t instance_id, 991 const struct pldm_get_firmware_parameters_resp_full *resp_data, 992 struct pldm_msg *msg, size_t *payload_length) 993 { 994 PLDM_MSGBUF_DEFINE_P(buf); 995 int rc; 996 997 if (resp_data == NULL || msg == NULL || payload_length == NULL) { 998 return -EINVAL; 999 } 1000 1001 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 1002 PLDM_GET_FIRMWARE_PARAMETERS, msg); 1003 if (rc) { 1004 return -EINVAL; 1005 } 1006 1007 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 1008 if (rc) { 1009 return rc; 1010 } 1011 1012 pldm_msgbuf_insert(buf, resp_data->completion_code); 1013 pldm_msgbuf_insert(buf, resp_data->capabilities_during_update.value); 1014 pldm_msgbuf_insert(buf, resp_data->comp_count); 1015 pldm_msgbuf_insert(buf, 1016 resp_data->active_comp_image_set_ver_str.str_type); 1017 pldm_msgbuf_insert(buf, 1018 resp_data->active_comp_image_set_ver_str.str_len); 1019 pldm_msgbuf_insert(buf, 1020 resp_data->pending_comp_image_set_ver_str.str_type); 1021 pldm_msgbuf_insert(buf, 1022 resp_data->pending_comp_image_set_ver_str.str_len); 1023 /* String data appended */ 1024 rc = pldm_msgbuf_insert_array( 1025 buf, resp_data->active_comp_image_set_ver_str.str_len, 1026 resp_data->active_comp_image_set_ver_str.str_data, 1027 resp_data->active_comp_image_set_ver_str.str_len); 1028 if (rc) { 1029 return pldm_msgbuf_discard(buf, rc); 1030 } 1031 rc = pldm_msgbuf_insert_array( 1032 buf, resp_data->pending_comp_image_set_ver_str.str_len, 1033 resp_data->pending_comp_image_set_ver_str.str_data, 1034 resp_data->pending_comp_image_set_ver_str.str_len); 1035 if (rc) { 1036 return pldm_msgbuf_discard(buf, rc); 1037 } 1038 1039 /* Further calls to encode_get_firmware_parameters_resp_comp_entry 1040 * will populate the remainder */ 1041 1042 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length); 1043 } 1044 1045 LIBPLDM_ABI_TESTING 1046 int encode_get_firmware_parameters_resp_comp_entry( 1047 const struct pldm_component_parameter_entry_full *comp, 1048 uint8_t *payload, size_t *payload_length) 1049 { 1050 PLDM_MSGBUF_DEFINE_P(buf); 1051 int rc; 1052 1053 if (comp == NULL || payload == NULL || payload_length == NULL) { 1054 return -EINVAL; 1055 } 1056 1057 rc = pldm_msgbuf_init_errno(buf, 0, payload, *payload_length); 1058 if (rc) { 1059 return rc; 1060 } 1061 1062 pldm_msgbuf_insert(buf, comp->comp_classification); 1063 pldm_msgbuf_insert(buf, comp->comp_identifier); 1064 pldm_msgbuf_insert(buf, comp->comp_classification_index); 1065 1066 pldm_msgbuf_insert(buf, comp->active_ver.comparison_stamp); 1067 pldm_msgbuf_insert(buf, (uint8_t)comp->active_ver.str.str_type); 1068 pldm_msgbuf_insert(buf, comp->active_ver.str.str_len); 1069 rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 1070 comp->active_ver.date, 1071 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN); 1072 if (rc) { 1073 return pldm_msgbuf_discard(buf, rc); 1074 } 1075 1076 pldm_msgbuf_insert(buf, comp->pending_ver.comparison_stamp); 1077 pldm_msgbuf_insert(buf, (uint8_t)comp->pending_ver.str.str_type); 1078 pldm_msgbuf_insert(buf, comp->pending_ver.str.str_len); 1079 rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 1080 comp->pending_ver.date, 1081 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN); 1082 if (rc) { 1083 return pldm_msgbuf_discard(buf, rc); 1084 } 1085 1086 pldm_msgbuf_insert(buf, comp->comp_activation_methods.value); 1087 pldm_msgbuf_insert(buf, comp->capabilities_during_update.value); 1088 1089 rc = pldm_msgbuf_insert_array(buf, comp->active_ver.str.str_len, 1090 comp->active_ver.str.str_data, 1091 comp->active_ver.str.str_len); 1092 if (rc) { 1093 return pldm_msgbuf_discard(buf, rc); 1094 } 1095 rc = pldm_msgbuf_insert_array(buf, comp->pending_ver.str.str_len, 1096 comp->pending_ver.str.str_data, 1097 comp->pending_ver.str.str_len); 1098 if (rc) { 1099 return pldm_msgbuf_discard(buf, rc); 1100 } 1101 1102 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length); 1103 } 1104 1105 LIBPLDM_ABI_STABLE 1106 int decode_get_firmware_parameters_resp_comp_entry( 1107 const uint8_t *data, size_t length, 1108 struct pldm_component_parameter_entry *component_data, 1109 struct variable_field *active_comp_ver_str, 1110 struct variable_field *pending_comp_ver_str) 1111 { 1112 if (data == NULL || component_data == NULL || 1113 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) { 1114 return PLDM_ERROR_INVALID_DATA; 1115 } 1116 1117 if (length < sizeof(struct pldm_component_parameter_entry)) { 1118 return PLDM_ERROR_INVALID_LENGTH; 1119 } 1120 1121 struct pldm_component_parameter_entry *entry = 1122 (struct pldm_component_parameter_entry *)(data); 1123 1124 size_t entry_length = sizeof(struct pldm_component_parameter_entry) + 1125 entry->active_comp_ver_str_len + 1126 entry->pending_comp_ver_str_len; 1127 1128 if (length < entry_length) { 1129 return PLDM_ERROR_INVALID_LENGTH; 1130 } 1131 1132 component_data->comp_classification = 1133 le16toh(entry->comp_classification); 1134 component_data->comp_identifier = le16toh(entry->comp_identifier); 1135 component_data->comp_classification_index = 1136 entry->comp_classification_index; 1137 component_data->active_comp_comparison_stamp = 1138 le32toh(entry->active_comp_comparison_stamp); 1139 component_data->active_comp_ver_str_type = 1140 entry->active_comp_ver_str_type; 1141 component_data->active_comp_ver_str_len = 1142 entry->active_comp_ver_str_len; 1143 memcpy(component_data->active_comp_release_date, 1144 entry->active_comp_release_date, 1145 sizeof(entry->active_comp_release_date)); 1146 component_data->pending_comp_comparison_stamp = 1147 le32toh(entry->pending_comp_comparison_stamp); 1148 component_data->pending_comp_ver_str_type = 1149 entry->pending_comp_ver_str_type; 1150 component_data->pending_comp_ver_str_len = 1151 entry->pending_comp_ver_str_len; 1152 memcpy(component_data->pending_comp_release_date, 1153 entry->pending_comp_release_date, 1154 sizeof(entry->pending_comp_release_date)); 1155 component_data->comp_activation_methods.value = 1156 le16toh(entry->comp_activation_methods.value); 1157 component_data->capabilities_during_update.value = 1158 le32toh(entry->capabilities_during_update.value); 1159 1160 if (entry->active_comp_ver_str_len != 0) { 1161 active_comp_ver_str->ptr = 1162 data + sizeof(struct pldm_component_parameter_entry); 1163 active_comp_ver_str->length = entry->active_comp_ver_str_len; 1164 } else { 1165 active_comp_ver_str->ptr = NULL; 1166 active_comp_ver_str->length = 0; 1167 } 1168 1169 if (entry->pending_comp_ver_str_len != 0) { 1170 pending_comp_ver_str->ptr = 1171 data + sizeof(struct pldm_component_parameter_entry) + 1172 entry->active_comp_ver_str_len; 1173 pending_comp_ver_str->length = entry->pending_comp_ver_str_len; 1174 } else { 1175 pending_comp_ver_str->ptr = NULL; 1176 pending_comp_ver_str->length = 0; 1177 } 1178 return PLDM_SUCCESS; 1179 } 1180 1181 LIBPLDM_ABI_STABLE 1182 int encode_query_downstream_devices_req(uint8_t instance_id, 1183 struct pldm_msg *msg) 1184 { 1185 if (msg == NULL) { 1186 return -EINVAL; 1187 } 1188 1189 return encode_pldm_header_only_errno(PLDM_REQUEST, instance_id, 1190 PLDM_FWUP, 1191 PLDM_QUERY_DOWNSTREAM_DEVICES, 1192 msg); 1193 } 1194 1195 LIBPLDM_ABI_STABLE 1196 int decode_query_downstream_devices_resp( 1197 const struct pldm_msg *msg, size_t payload_length, 1198 struct pldm_query_downstream_devices_resp *resp_data) 1199 { 1200 PLDM_MSGBUF_DEFINE_P(buf); 1201 int rc; 1202 1203 if (msg == NULL || resp_data == NULL || !payload_length) { 1204 return -EINVAL; 1205 } 1206 1207 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 1208 msg->payload, payload_length); 1209 if (rc) { 1210 return rc; 1211 } 1212 1213 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 1214 if (rc) { 1215 return pldm_msgbuf_discard(buf, rc); 1216 } 1217 if (PLDM_SUCCESS != resp_data->completion_code) { 1218 // Return the CC directly without decoding the rest of the payload 1219 return pldm_msgbuf_complete(buf); 1220 } 1221 1222 if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) { 1223 return pldm_msgbuf_discard(buf, -EBADMSG); 1224 } 1225 1226 rc = pldm_msgbuf_extract(buf, 1227 resp_data->downstream_device_update_supported); 1228 if (rc) { 1229 return pldm_msgbuf_discard(buf, rc); 1230 } 1231 1232 if (!is_downstream_device_update_support_valid( 1233 resp_data->downstream_device_update_supported)) { 1234 return pldm_msgbuf_discard(buf, -EINVAL); 1235 } 1236 1237 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices); 1238 pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices); 1239 pldm_msgbuf_extract(buf, resp_data->capabilities.value); 1240 1241 return pldm_msgbuf_complete_consumed(buf); 1242 } 1243 1244 LIBPLDM_ABI_STABLE 1245 int encode_query_downstream_identifiers_req( 1246 uint8_t instance_id, 1247 const struct pldm_query_downstream_identifiers_req *params_req, 1248 struct pldm_msg *msg, size_t payload_length) 1249 { 1250 PLDM_MSGBUF_DEFINE_P(buf); 1251 int rc; 1252 1253 if (!msg || !params_req) { 1254 return -EINVAL; 1255 } 1256 1257 if (!is_transfer_operation_flag_valid( 1258 (enum transfer_op_flag) 1259 params_req->transfer_operation_flag)) { 1260 return -EINVAL; 1261 } 1262 1263 struct pldm_header_info header = { 0 }; 1264 header.instance = instance_id; 1265 header.msg_type = PLDM_REQUEST; 1266 header.pldm_type = PLDM_FWUP; 1267 header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS; 1268 rc = pack_pldm_header_errno(&header, &(msg->hdr)); 1269 if (rc) { 1270 return rc; 1271 } 1272 1273 rc = pldm_msgbuf_init_errno(buf, 1274 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES, 1275 msg->payload, payload_length); 1276 if (rc) { 1277 return rc; 1278 } 1279 1280 pldm_msgbuf_insert(buf, params_req->data_transfer_handle); 1281 // Data correctness has been verified, cast it to 1-byte data directly. 1282 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag); 1283 1284 return pldm_msgbuf_complete(buf); 1285 } 1286 1287 LIBPLDM_ABI_STABLE 1288 int decode_query_downstream_identifiers_resp( 1289 const struct pldm_msg *msg, size_t payload_length, 1290 struct pldm_query_downstream_identifiers_resp *resp_data, 1291 struct pldm_downstream_device_iter *iter) 1292 { 1293 PLDM_MSGBUF_DEFINE_P(buf); 1294 void *remaining = NULL; 1295 int rc = 0; 1296 1297 if (msg == NULL || resp_data == NULL || iter == NULL || 1298 !payload_length) { 1299 return -EINVAL; 1300 } 1301 1302 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 1303 msg->payload, payload_length); 1304 if (rc) { 1305 return rc; 1306 } 1307 1308 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 1309 if (rc) { 1310 return pldm_msgbuf_discard(buf, rc); 1311 } 1312 if (PLDM_SUCCESS != resp_data->completion_code) { 1313 return pldm_msgbuf_complete(buf); 1314 } 1315 1316 if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) { 1317 return pldm_msgbuf_discard(buf, -EBADMSG); 1318 } 1319 1320 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle); 1321 pldm_msgbuf_extract(buf, resp_data->transfer_flag); 1322 1323 rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length); 1324 if (rc) { 1325 return pldm_msgbuf_discard(buf, rc); 1326 } 1327 1328 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices); 1329 pldm_msgbuf_span_required(buf, resp_data->downstream_devices_length, 1330 &remaining); 1331 1332 rc = pldm_msgbuf_complete(buf); 1333 if (rc) { 1334 return rc; 1335 } 1336 1337 iter->field.ptr = remaining; 1338 iter->field.length = resp_data->downstream_devices_length; 1339 iter->devs = resp_data->number_of_downstream_devices; 1340 1341 return 0; 1342 } 1343 1344 LIBPLDM_ABI_STABLE 1345 int decode_pldm_downstream_device_from_iter( 1346 struct pldm_downstream_device_iter *iter, 1347 struct pldm_downstream_device *dev) 1348 { 1349 PLDM_MSGBUF_DEFINE_P(buf); 1350 int rc; 1351 1352 if (!iter || !iter->field.ptr || !dev) { 1353 return -EINVAL; 1354 } 1355 1356 rc = pldm_msgbuf_init_errno(buf, 3, iter->field.ptr, 1357 iter->field.length); 1358 if (rc) { 1359 return rc; 1360 } 1361 1362 pldm_msgbuf_extract(buf, dev->downstream_device_index); 1363 pldm_msgbuf_extract(buf, dev->downstream_descriptor_count); 1364 pldm_msgbuf_span_remaining(buf, (void **)&iter->field.ptr, 1365 &iter->field.length); 1366 1367 return pldm_msgbuf_complete(buf); 1368 } 1369 1370 LIBPLDM_ABI_STABLE 1371 int encode_get_downstream_firmware_parameters_req( 1372 uint8_t instance_id, 1373 const struct pldm_get_downstream_firmware_parameters_req *params_req, 1374 struct pldm_msg *msg, size_t payload_length) 1375 { 1376 PLDM_MSGBUF_DEFINE_P(buf); 1377 int rc; 1378 1379 if (!msg || !params_req) { 1380 return -EINVAL; 1381 } 1382 1383 if (!is_transfer_operation_flag_valid( 1384 (enum transfer_op_flag) 1385 params_req->transfer_operation_flag)) { 1386 return -EBADMSG; 1387 } 1388 1389 struct pldm_header_info header = { 0 }; 1390 header.instance = instance_id; 1391 header.msg_type = PLDM_REQUEST; 1392 header.pldm_type = PLDM_FWUP; 1393 header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS; 1394 rc = pack_pldm_header_errno(&header, &msg->hdr); 1395 if (rc < 0) { 1396 return rc; 1397 } 1398 1399 rc = pldm_msgbuf_init_errno( 1400 buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES, 1401 msg->payload, payload_length); 1402 if (rc < 0) { 1403 return rc; 1404 } 1405 1406 pldm_msgbuf_insert(buf, params_req->data_transfer_handle); 1407 // Data correctness has been verified, cast it to 1-byte data directly. 1408 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag); 1409 1410 return pldm_msgbuf_complete(buf); 1411 } 1412 1413 LIBPLDM_ABI_STABLE 1414 int decode_get_downstream_firmware_parameters_resp( 1415 const struct pldm_msg *msg, size_t payload_length, 1416 struct pldm_get_downstream_firmware_parameters_resp *resp_data, 1417 struct pldm_downstream_device_parameters_iter *iter) 1418 { 1419 PLDM_MSGBUF_DEFINE_P(buf); 1420 void *remaining = NULL; 1421 size_t length; 1422 int rc; 1423 1424 if (msg == NULL || resp_data == NULL || iter == NULL) { 1425 return -EINVAL; 1426 } 1427 1428 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 1429 msg->payload, payload_length); 1430 if (rc < 0) { 1431 return rc; 1432 } 1433 1434 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 1435 if (rc < 0) { 1436 return pldm_msgbuf_discard(buf, rc); 1437 } 1438 if (PLDM_SUCCESS != resp_data->completion_code) { 1439 return pldm_msgbuf_complete(buf); 1440 } 1441 1442 if (payload_length < 1443 PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN) { 1444 return pldm_msgbuf_discard(buf, -EBADMSG); 1445 } 1446 1447 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle); 1448 pldm_msgbuf_extract(buf, resp_data->transfer_flag); 1449 pldm_msgbuf_extract(buf, 1450 resp_data->fdp_capabilities_during_update.value); 1451 pldm_msgbuf_extract(buf, resp_data->downstream_device_count); 1452 1453 rc = pldm_msgbuf_span_remaining(buf, &remaining, &length); 1454 if (rc) { 1455 return pldm_msgbuf_discard(buf, rc); 1456 } 1457 1458 rc = pldm_msgbuf_complete(buf); 1459 if (rc) { 1460 return rc; 1461 } 1462 1463 iter->field.ptr = remaining; 1464 iter->field.length = length; 1465 iter->entries = resp_data->downstream_device_count; 1466 1467 return 0; 1468 } 1469 1470 LIBPLDM_ABI_STABLE 1471 int decode_pldm_downstream_device_parameters_entry_from_iter( 1472 struct pldm_downstream_device_parameters_iter *iter, 1473 struct pldm_downstream_device_parameters_entry *entry) 1474 { 1475 PLDM_MSGBUF_DEFINE_P(buf); 1476 void *comp_ver_str; 1477 size_t remaining; 1478 void *cursor; 1479 int rc; 1480 1481 if (iter == NULL || iter->field.ptr == NULL || entry == NULL) { 1482 return -EINVAL; 1483 } 1484 1485 rc = pldm_msgbuf_init_errno( 1486 buf, PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN, 1487 iter->field.ptr, iter->field.length); 1488 if (rc < 0) { 1489 return rc; 1490 } 1491 1492 pldm_msgbuf_extract(buf, entry->downstream_device_index); 1493 pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp); 1494 pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type); 1495 rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len); 1496 if (rc < 0) { 1497 return pldm_msgbuf_discard(buf, rc); 1498 } 1499 rc = pldm_msgbuf_extract_array(buf, 1500 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 1501 entry->active_comp_release_date, 1502 sizeof(entry->active_comp_release_date)); 1503 if (rc < 0) { 1504 return pldm_msgbuf_discard(buf, rc); 1505 } 1506 1507 // Fill the last byte with NULL character 1508 entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] = 1509 '\0'; 1510 1511 pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp); 1512 pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type); 1513 rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len); 1514 if (rc < 0) { 1515 return pldm_msgbuf_discard(buf, rc); 1516 } 1517 1518 rc = pldm_msgbuf_extract_array( 1519 buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 1520 entry->pending_comp_release_date, 1521 sizeof(entry->pending_comp_release_date)); 1522 if (rc < 0) { 1523 return pldm_msgbuf_discard(buf, rc); 1524 } 1525 1526 // Fill the last byte with NULL character 1527 entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] = 1528 '\0'; 1529 1530 pldm_msgbuf_extract(buf, entry->comp_activation_methods.value); 1531 pldm_msgbuf_extract(buf, entry->capabilities_during_update.value); 1532 1533 rc = pldm_msgbuf_span_required(buf, entry->active_comp_ver_str_len, 1534 &comp_ver_str); 1535 if (rc < 0) { 1536 return pldm_msgbuf_discard(buf, rc); 1537 } 1538 entry->active_comp_ver_str = comp_ver_str; 1539 1540 rc = pldm_msgbuf_span_required(buf, entry->pending_comp_ver_str_len, 1541 &comp_ver_str); 1542 if (rc < 0) { 1543 return pldm_msgbuf_discard(buf, rc); 1544 } 1545 entry->pending_comp_ver_str = comp_ver_str; 1546 1547 rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining); 1548 if (rc < 0) { 1549 return pldm_msgbuf_discard(buf, rc); 1550 } 1551 1552 iter->field.ptr = cursor; 1553 iter->field.length = remaining; 1554 1555 return pldm_msgbuf_complete(buf); 1556 } 1557 1558 LIBPLDM_ABI_TESTING 1559 int encode_request_downstream_device_update_req( 1560 uint8_t instance_id, 1561 const struct pldm_request_downstream_device_update_req *req_data, 1562 struct pldm_msg *msg, size_t *payload_length) 1563 { 1564 PLDM_MSGBUF_DEFINE_P(buf); 1565 int rc; 1566 1567 if (!req_data || !msg || !payload_length || 1568 req_data->maximum_downstream_device_transfer_size < 1569 PLDM_FWUP_BASELINE_TRANSFER_SIZE || 1570 req_data->maximum_outstanding_transfer_requests < 1571 PLDM_FWUP_MIN_OUTSTANDING_REQ) { 1572 return -EINVAL; 1573 } 1574 1575 rc = encode_pldm_header_only_errno( 1576 PLDM_REQUEST, instance_id, PLDM_FWUP, 1577 PLDM_REQUEST_DOWNSTREAM_DEVICE_UPDATE, msg); 1578 if (rc) { 1579 return rc; 1580 } 1581 1582 rc = pldm_msgbuf_init_errno(buf, 1583 PLDM_DOWNSTREAM_DEVICE_UPDATE_REQUEST_BYTES, 1584 msg->payload, *payload_length); 1585 if (rc) { 1586 return rc; 1587 } 1588 1589 pldm_msgbuf_insert(buf, 1590 req_data->maximum_downstream_device_transfer_size); 1591 pldm_msgbuf_insert(buf, 1592 req_data->maximum_outstanding_transfer_requests); 1593 pldm_msgbuf_insert(buf, 1594 req_data->downstream_device_package_data_length); 1595 1596 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length); 1597 } 1598 1599 LIBPLDM_ABI_TESTING 1600 int decode_request_downstream_device_update_req( 1601 const struct pldm_msg *msg, size_t payload_length, 1602 struct pldm_request_downstream_device_update_req *req) 1603 { 1604 int rc; 1605 PLDM_MSGBUF_DEFINE_P(buf); 1606 1607 if (!msg || !req) { 1608 return -EINVAL; 1609 } 1610 1611 rc = pldm_msgbuf_init_errno(buf, 1612 PLDM_DOWNSTREAM_DEVICE_UPDATE_REQUEST_BYTES, 1613 msg->payload, payload_length); 1614 if (rc) { 1615 return rc; 1616 } 1617 1618 pldm_msgbuf_extract(buf, req->maximum_downstream_device_transfer_size); 1619 pldm_msgbuf_extract(buf, req->maximum_outstanding_transfer_requests); 1620 pldm_msgbuf_extract(buf, req->downstream_device_package_data_length); 1621 1622 return pldm_msgbuf_complete_consumed(buf); 1623 } 1624 1625 LIBPLDM_ABI_TESTING 1626 int encode_request_downstream_device_update_resp( 1627 uint8_t instance_id, 1628 const struct pldm_request_downstream_device_update_resp *resp_data, 1629 struct pldm_msg *msg, size_t *payload_length) 1630 { 1631 PLDM_MSGBUF_DEFINE_P(buf); 1632 int rc; 1633 1634 if (!resp_data || !msg || !payload_length) { 1635 return -EINVAL; 1636 } 1637 1638 rc = encode_pldm_header_only_errno( 1639 PLDM_RESPONSE, instance_id, PLDM_FWUP, 1640 PLDM_REQUEST_DOWNSTREAM_DEVICE_UPDATE, msg); 1641 if (rc) { 1642 return rc; 1643 } 1644 1645 rc = pldm_msgbuf_init_errno( 1646 buf, PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES, msg->payload, 1647 *payload_length); 1648 if (rc) { 1649 return rc; 1650 } 1651 1652 pldm_msgbuf_insert(buf, resp_data->completion_code); 1653 pldm_msgbuf_insert(buf, resp_data->downstream_device_meta_data_length); 1654 pldm_msgbuf_insert( 1655 buf, resp_data->downstream_device_will_send_get_package_data); 1656 pldm_msgbuf_insert(buf, 1657 resp_data->get_package_data_maximum_transfer_size); 1658 1659 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length); 1660 } 1661 1662 LIBPLDM_ABI_TESTING 1663 int decode_request_downstream_device_update_resp( 1664 const struct pldm_msg *msg, size_t payload_length, 1665 struct pldm_request_downstream_device_update_resp *resp_data) 1666 { 1667 PLDM_MSGBUF_DEFINE_P(buf); 1668 int rc; 1669 1670 if (!msg || !resp_data) { 1671 return -EINVAL; 1672 } 1673 1674 rc = pldm_msg_has_error(msg, 1675 PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES); 1676 if (rc) { 1677 resp_data->completion_code = rc; 1678 return 0; 1679 } 1680 1681 rc = pldm_msgbuf_init_errno( 1682 buf, PLDM_DOWNSTREAM_DEVICE_UPDATE_RESPONSE_BYTES, msg->payload, 1683 payload_length); 1684 if (rc) { 1685 return rc; 1686 } 1687 1688 pldm_msgbuf_extract(buf, resp_data->completion_code); 1689 pldm_msgbuf_extract(buf, resp_data->downstream_device_meta_data_length); 1690 pldm_msgbuf_extract( 1691 buf, resp_data->downstream_device_will_send_get_package_data); 1692 pldm_msgbuf_extract(buf, 1693 resp_data->get_package_data_maximum_transfer_size); 1694 1695 return pldm_msgbuf_complete_consumed(buf); 1696 } 1697 1698 LIBPLDM_ABI_STABLE 1699 int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size, 1700 uint16_t num_of_comp, 1701 uint8_t max_outstanding_transfer_req, 1702 uint16_t pkg_data_len, 1703 uint8_t comp_image_set_ver_str_type, 1704 uint8_t comp_image_set_ver_str_len, 1705 const struct variable_field *comp_img_set_ver_str, 1706 struct pldm_msg *msg, size_t payload_length) 1707 { 1708 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL || 1709 msg == NULL) { 1710 return PLDM_ERROR_INVALID_DATA; 1711 } 1712 1713 if (payload_length != sizeof(struct pldm_request_update_req) + 1714 comp_img_set_ver_str->length) { 1715 return PLDM_ERROR_INVALID_LENGTH; 1716 } 1717 1718 if ((comp_image_set_ver_str_len == 0) || 1719 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) { 1720 return PLDM_ERROR_INVALID_DATA; 1721 } 1722 1723 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) || 1724 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) { 1725 return PLDM_ERROR_INVALID_DATA; 1726 } 1727 1728 if (!is_string_type_valid(comp_image_set_ver_str_type)) { 1729 return PLDM_ERROR_INVALID_DATA; 1730 } 1731 1732 struct pldm_header_info header = { 0 }; 1733 header.instance = instance_id; 1734 header.msg_type = PLDM_REQUEST; 1735 header.pldm_type = PLDM_FWUP; 1736 header.command = PLDM_REQUEST_UPDATE; 1737 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1738 if (rc) { 1739 return rc; 1740 } 1741 1742 struct pldm_request_update_req *request = 1743 (struct pldm_request_update_req *)msg->payload; 1744 1745 request->max_transfer_size = htole32(max_transfer_size); 1746 request->num_of_comp = htole16(num_of_comp); 1747 request->max_outstanding_transfer_req = max_outstanding_transfer_req; 1748 request->pkg_data_len = htole16(pkg_data_len); 1749 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type; 1750 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len; 1751 1752 memcpy(msg->payload + sizeof(struct pldm_request_update_req), 1753 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length); 1754 1755 return PLDM_SUCCESS; 1756 } 1757 1758 LIBPLDM_ABI_TESTING 1759 int decode_request_update_req(const struct pldm_msg *msg, size_t payload_length, 1760 struct pldm_request_update_req_full *req) 1761 { 1762 int rc; 1763 uint8_t t; 1764 PLDM_MSGBUF_DEFINE_P(buf); 1765 1766 if (msg == NULL || req == NULL) { 1767 return -EINVAL; 1768 } 1769 1770 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length); 1771 if (rc) { 1772 return rc; 1773 } 1774 1775 pldm_msgbuf_extract(buf, req->max_transfer_size); 1776 pldm_msgbuf_extract(buf, req->num_of_comp); 1777 pldm_msgbuf_extract(buf, req->max_outstanding_transfer_req); 1778 pldm_msgbuf_extract(buf, req->pkg_data_len); 1779 rc = pldm_msgbuf_extract(buf, t); 1780 if (rc) { 1781 return pldm_msgbuf_discard(buf, rc); 1782 } 1783 if (t > PLDM_STR_TYPE_UTF_16BE) { 1784 return pldm_msgbuf_discard(buf, -EBADMSG); 1785 } 1786 req->image_set_ver.str_type = (enum pldm_firmware_update_string_type)t; 1787 pldm_msgbuf_extract(buf, req->image_set_ver.str_len); 1788 if (rc) { 1789 return pldm_msgbuf_discard(buf, rc); 1790 } 1791 1792 rc = pldm_msgbuf_extract_array(buf, req->image_set_ver.str_len, 1793 req->image_set_ver.str_data, 1794 PLDM_FIRMWARE_MAX_STRING); 1795 if (rc) { 1796 return pldm_msgbuf_discard(buf, rc); 1797 } 1798 1799 return pldm_msgbuf_complete_consumed(buf); 1800 } 1801 1802 LIBPLDM_ABI_STABLE 1803 int decode_request_update_resp(const struct pldm_msg *msg, 1804 size_t payload_length, uint8_t *completion_code, 1805 uint16_t *fd_meta_data_len, 1806 uint8_t *fd_will_send_pkg_data) 1807 { 1808 if (msg == NULL || completion_code == NULL || 1809 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL || 1810 !payload_length) { 1811 return PLDM_ERROR_INVALID_DATA; 1812 } 1813 1814 *completion_code = msg->payload[0]; 1815 if (*completion_code != PLDM_SUCCESS) { 1816 return PLDM_SUCCESS; 1817 } 1818 1819 if (payload_length != sizeof(struct pldm_request_update_resp)) { 1820 return PLDM_ERROR_INVALID_LENGTH; 1821 } 1822 1823 struct pldm_request_update_resp *response = 1824 (struct pldm_request_update_resp *)msg->payload; 1825 1826 *fd_meta_data_len = le16toh(response->fd_meta_data_len); 1827 *fd_will_send_pkg_data = response->fd_will_send_pkg_data; 1828 1829 return PLDM_SUCCESS; 1830 } 1831 1832 LIBPLDM_ABI_TESTING 1833 int encode_request_update_resp(uint8_t instance_id, 1834 const struct pldm_request_update_resp *resp_data, 1835 struct pldm_msg *msg, size_t *payload_length) 1836 { 1837 PLDM_MSGBUF_DEFINE_P(buf); 1838 int rc; 1839 1840 if (msg == NULL || payload_length == NULL) { 1841 return -EINVAL; 1842 } 1843 1844 struct pldm_header_info header = { 1845 .instance = instance_id, 1846 .msg_type = PLDM_RESPONSE, 1847 .pldm_type = PLDM_FWUP, 1848 .command = PLDM_REQUEST_UPDATE, 1849 }; 1850 rc = pack_pldm_header(&header, &(msg->hdr)); 1851 if (rc) { 1852 return -EINVAL; 1853 } 1854 1855 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 1856 if (rc) { 1857 return rc; 1858 } 1859 1860 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 1861 pldm_msgbuf_insert(buf, resp_data->fd_meta_data_len); 1862 pldm_msgbuf_insert(buf, resp_data->fd_will_send_pkg_data); 1863 1864 /* TODO: DSP0267 1.3.0 adds GetPackageDataMaximumTransferSize */ 1865 1866 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length); 1867 } 1868 1869 LIBPLDM_ABI_STABLE 1870 int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag, 1871 uint16_t comp_classification, 1872 uint16_t comp_identifier, 1873 uint8_t comp_classification_index, 1874 uint32_t comp_comparison_stamp, 1875 uint8_t comp_ver_str_type, 1876 uint8_t comp_ver_str_len, 1877 const struct variable_field *comp_ver_str, 1878 struct pldm_msg *msg, size_t payload_length) 1879 { 1880 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) { 1881 return PLDM_ERROR_INVALID_DATA; 1882 } 1883 1884 if (payload_length != sizeof(struct pldm_pass_component_table_req) + 1885 comp_ver_str->length) { 1886 return PLDM_ERROR_INVALID_LENGTH; 1887 } 1888 1889 if ((comp_ver_str_len == 0) || 1890 (comp_ver_str_len != comp_ver_str->length)) { 1891 return PLDM_ERROR_INVALID_DATA; 1892 } 1893 1894 if (!is_transfer_flag_valid(transfer_flag)) { 1895 return PLDM_INVALID_TRANSFER_OPERATION_FLAG; 1896 } 1897 1898 if (!is_string_type_valid(comp_ver_str_type)) { 1899 return PLDM_ERROR_INVALID_DATA; 1900 } 1901 1902 struct pldm_header_info header = { 0 }; 1903 header.instance = instance_id; 1904 header.msg_type = PLDM_REQUEST; 1905 header.pldm_type = PLDM_FWUP; 1906 header.command = PLDM_PASS_COMPONENT_TABLE; 1907 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1908 if (rc) { 1909 return rc; 1910 } 1911 1912 struct pldm_pass_component_table_req *request = 1913 (struct pldm_pass_component_table_req *)msg->payload; 1914 1915 request->transfer_flag = transfer_flag; 1916 request->comp_classification = htole16(comp_classification); 1917 request->comp_identifier = htole16(comp_identifier); 1918 request->comp_classification_index = comp_classification_index; 1919 request->comp_comparison_stamp = htole32(comp_comparison_stamp); 1920 request->comp_ver_str_type = comp_ver_str_type; 1921 request->comp_ver_str_len = comp_ver_str_len; 1922 1923 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req), 1924 comp_ver_str->ptr, comp_ver_str->length); 1925 1926 return PLDM_SUCCESS; 1927 } 1928 1929 LIBPLDM_ABI_TESTING 1930 int decode_pass_component_table_req( 1931 const struct pldm_msg *msg, size_t payload_length, 1932 struct pldm_pass_component_table_req_full *pcomp) 1933 { 1934 int rc; 1935 uint8_t t; 1936 PLDM_MSGBUF_DEFINE_P(buf); 1937 1938 if (msg == NULL || pcomp == NULL) { 1939 return -EINVAL; 1940 } 1941 1942 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length); 1943 if (rc) { 1944 return rc; 1945 } 1946 1947 pldm_msgbuf_extract(buf, pcomp->transfer_flag); 1948 pldm_msgbuf_extract(buf, pcomp->comp_classification); 1949 pldm_msgbuf_extract(buf, pcomp->comp_identifier); 1950 pldm_msgbuf_extract(buf, pcomp->comp_classification_index); 1951 pldm_msgbuf_extract(buf, pcomp->comp_comparison_stamp); 1952 rc = pldm_msgbuf_extract(buf, t); 1953 if (rc) { 1954 return pldm_msgbuf_discard(buf, rc); 1955 } 1956 if (t > PLDM_STR_TYPE_UTF_16BE) { 1957 return pldm_msgbuf_discard(buf, -EBADMSG); 1958 } 1959 pcomp->version.str_type = (enum pldm_firmware_update_string_type)t; 1960 rc = pldm_msgbuf_extract(buf, pcomp->version.str_len); 1961 if (rc) { 1962 return pldm_msgbuf_discard(buf, rc); 1963 } 1964 rc = pldm_msgbuf_extract_array(buf, pcomp->version.str_len, 1965 pcomp->version.str_data, 1966 PLDM_FIRMWARE_MAX_STRING); 1967 if (rc) { 1968 return pldm_msgbuf_discard(buf, rc); 1969 } 1970 1971 return pldm_msgbuf_complete_consumed(buf); 1972 } 1973 1974 LIBPLDM_ABI_STABLE 1975 int decode_pass_component_table_resp(const struct pldm_msg *msg, 1976 const size_t payload_length, 1977 uint8_t *completion_code, 1978 uint8_t *comp_resp, 1979 uint8_t *comp_resp_code) 1980 { 1981 if (msg == NULL || completion_code == NULL || comp_resp == NULL || 1982 comp_resp_code == NULL || !payload_length) { 1983 return PLDM_ERROR_INVALID_DATA; 1984 } 1985 1986 *completion_code = msg->payload[0]; 1987 if (*completion_code != PLDM_SUCCESS) { 1988 return PLDM_SUCCESS; 1989 } 1990 1991 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) { 1992 return PLDM_ERROR_INVALID_LENGTH; 1993 } 1994 1995 struct pldm_pass_component_table_resp *response = 1996 (struct pldm_pass_component_table_resp *)msg->payload; 1997 1998 if (!is_comp_resp_valid(response->comp_resp)) { 1999 return PLDM_ERROR_INVALID_DATA; 2000 } 2001 2002 if (!is_comp_resp_code_valid(response->comp_resp_code)) { 2003 return PLDM_ERROR_INVALID_DATA; 2004 } 2005 2006 *comp_resp = response->comp_resp; 2007 *comp_resp_code = response->comp_resp_code; 2008 2009 return PLDM_SUCCESS; 2010 } 2011 2012 LIBPLDM_ABI_TESTING 2013 int encode_pass_component_table_resp( 2014 uint8_t instance_id, 2015 const struct pldm_pass_component_table_resp *resp_data, 2016 struct pldm_msg *msg, size_t *payload_length) 2017 { 2018 PLDM_MSGBUF_DEFINE_P(buf); 2019 int rc; 2020 2021 if (msg == NULL || payload_length == NULL) { 2022 return -EINVAL; 2023 } 2024 2025 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 2026 PLDM_PASS_COMPONENT_TABLE, msg); 2027 if (rc) { 2028 return -EINVAL; 2029 } 2030 2031 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2032 if (rc) { 2033 return rc; 2034 } 2035 2036 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 2037 pldm_msgbuf_insert(buf, resp_data->comp_resp); 2038 pldm_msgbuf_insert(buf, resp_data->comp_resp_code); 2039 2040 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length); 2041 } 2042 2043 LIBPLDM_ABI_STABLE 2044 int encode_update_component_req( 2045 uint8_t instance_id, uint16_t comp_classification, 2046 uint16_t comp_identifier, uint8_t comp_classification_index, 2047 uint32_t comp_comparison_stamp, uint32_t comp_image_size, 2048 bitfield32_t update_option_flags, uint8_t comp_ver_str_type, 2049 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str, 2050 struct pldm_msg *msg, size_t payload_length) 2051 { 2052 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) { 2053 return PLDM_ERROR_INVALID_DATA; 2054 } 2055 2056 if (payload_length != 2057 sizeof(struct pldm_update_component_req) + comp_ver_str->length) { 2058 return PLDM_ERROR_INVALID_LENGTH; 2059 } 2060 2061 if (!comp_image_size) { 2062 return PLDM_ERROR_INVALID_DATA; 2063 } 2064 2065 if ((comp_ver_str_len == 0) || 2066 (comp_ver_str_len != comp_ver_str->length)) { 2067 return PLDM_ERROR_INVALID_DATA; 2068 } 2069 2070 if (!is_string_type_valid(comp_ver_str_type)) { 2071 return PLDM_ERROR_INVALID_DATA; 2072 } 2073 2074 struct pldm_header_info header = { 0 }; 2075 header.instance = instance_id; 2076 header.msg_type = PLDM_REQUEST; 2077 header.pldm_type = PLDM_FWUP; 2078 header.command = PLDM_UPDATE_COMPONENT; 2079 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2080 if (rc) { 2081 return rc; 2082 } 2083 2084 struct pldm_update_component_req *request = 2085 (struct pldm_update_component_req *)msg->payload; 2086 2087 request->comp_classification = htole16(comp_classification); 2088 request->comp_identifier = htole16(comp_identifier); 2089 request->comp_classification_index = comp_classification_index; 2090 request->comp_comparison_stamp = htole32(comp_comparison_stamp); 2091 request->comp_image_size = htole32(comp_image_size); 2092 request->update_option_flags.value = htole32(update_option_flags.value); 2093 request->comp_ver_str_type = comp_ver_str_type; 2094 request->comp_ver_str_len = comp_ver_str_len; 2095 2096 memcpy(msg->payload + sizeof(struct pldm_update_component_req), 2097 comp_ver_str->ptr, comp_ver_str->length); 2098 2099 return PLDM_SUCCESS; 2100 } 2101 2102 LIBPLDM_ABI_TESTING 2103 int decode_update_component_req(const struct pldm_msg *msg, 2104 size_t payload_length, 2105 struct pldm_update_component_req_full *up) 2106 { 2107 int rc; 2108 uint8_t t; 2109 PLDM_MSGBUF_DEFINE_P(buf); 2110 2111 if (msg == NULL || up == NULL) { 2112 return -EINVAL; 2113 } 2114 2115 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length); 2116 if (rc) { 2117 return rc; 2118 } 2119 2120 pldm_msgbuf_extract(buf, up->comp_classification); 2121 pldm_msgbuf_extract(buf, up->comp_identifier); 2122 pldm_msgbuf_extract(buf, up->comp_classification_index); 2123 pldm_msgbuf_extract(buf, up->comp_comparison_stamp); 2124 pldm_msgbuf_extract(buf, up->comp_image_size); 2125 pldm_msgbuf_extract(buf, up->update_option_flags.value); 2126 rc = pldm_msgbuf_extract(buf, t); 2127 if (rc) { 2128 return pldm_msgbuf_discard(buf, rc); 2129 } 2130 if (t > PLDM_STR_TYPE_UTF_16BE) { 2131 return pldm_msgbuf_discard(buf, -EBADMSG); 2132 } 2133 up->version.str_type = (enum pldm_firmware_update_string_type)t; 2134 rc = pldm_msgbuf_extract(buf, up->version.str_len); 2135 if (rc) { 2136 return pldm_msgbuf_discard(buf, rc); 2137 } 2138 rc = pldm_msgbuf_extract_array(buf, up->version.str_len, 2139 up->version.str_data, 2140 PLDM_FIRMWARE_MAX_STRING); 2141 if (rc) { 2142 return pldm_msgbuf_discard(buf, rc); 2143 } 2144 2145 return pldm_msgbuf_complete_consumed(buf); 2146 } 2147 2148 LIBPLDM_ABI_STABLE 2149 int decode_update_component_resp(const struct pldm_msg *msg, 2150 size_t payload_length, 2151 uint8_t *completion_code, 2152 uint8_t *comp_compatibility_resp, 2153 uint8_t *comp_compatibility_resp_code, 2154 bitfield32_t *update_option_flags_enabled, 2155 uint16_t *time_before_req_fw_data) 2156 { 2157 if (msg == NULL || completion_code == NULL || 2158 comp_compatibility_resp == NULL || 2159 comp_compatibility_resp_code == NULL || 2160 update_option_flags_enabled == NULL || 2161 time_before_req_fw_data == NULL || !payload_length) { 2162 return PLDM_ERROR_INVALID_DATA; 2163 } 2164 2165 *completion_code = msg->payload[0]; 2166 if (*completion_code != PLDM_SUCCESS) { 2167 return PLDM_SUCCESS; 2168 } 2169 2170 if (payload_length != sizeof(struct pldm_update_component_resp)) { 2171 return PLDM_ERROR_INVALID_LENGTH; 2172 } 2173 2174 struct pldm_update_component_resp *response = 2175 (struct pldm_update_component_resp *)msg->payload; 2176 2177 if (!is_comp_compatibility_resp_valid( 2178 response->comp_compatibility_resp)) { 2179 return PLDM_ERROR_INVALID_DATA; 2180 } 2181 2182 if (!is_comp_compatibility_resp_code_valid( 2183 response->comp_compatibility_resp_code)) { 2184 return PLDM_ERROR_INVALID_DATA; 2185 } 2186 2187 *comp_compatibility_resp = response->comp_compatibility_resp; 2188 *comp_compatibility_resp_code = response->comp_compatibility_resp_code; 2189 update_option_flags_enabled->value = 2190 le32toh(response->update_option_flags_enabled.value); 2191 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data); 2192 2193 return PLDM_SUCCESS; 2194 } 2195 2196 LIBPLDM_ABI_TESTING 2197 int encode_update_component_resp( 2198 uint8_t instance_id, const struct pldm_update_component_resp *resp_data, 2199 struct pldm_msg *msg, size_t *payload_length) 2200 { 2201 PLDM_MSGBUF_DEFINE_P(buf); 2202 int rc; 2203 2204 if (msg == NULL || payload_length == NULL) { 2205 return -EINVAL; 2206 } 2207 2208 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 2209 PLDM_UPDATE_COMPONENT, msg); 2210 if (rc) { 2211 return -EINVAL; 2212 } 2213 2214 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2215 if (rc) { 2216 return rc; 2217 } 2218 2219 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 2220 pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp); 2221 pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp_code); 2222 pldm_msgbuf_insert(buf, resp_data->update_option_flags_enabled.value); 2223 pldm_msgbuf_insert(buf, resp_data->time_before_req_fw_data); 2224 2225 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length); 2226 } 2227 2228 LIBPLDM_ABI_STABLE 2229 int decode_request_firmware_data_req(const struct pldm_msg *msg, 2230 size_t payload_length, uint32_t *offset, 2231 uint32_t *length) 2232 { 2233 if (msg == NULL || offset == NULL || length == NULL) { 2234 return PLDM_ERROR_INVALID_DATA; 2235 } 2236 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) { 2237 return PLDM_ERROR_INVALID_LENGTH; 2238 } 2239 struct pldm_request_firmware_data_req *request = 2240 (struct pldm_request_firmware_data_req *)msg->payload; 2241 *offset = le32toh(request->offset); 2242 *length = le32toh(request->length); 2243 2244 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) { 2245 return PLDM_FWUP_INVALID_TRANSFER_LENGTH; 2246 } 2247 2248 return PLDM_SUCCESS; 2249 } 2250 2251 LIBPLDM_ABI_TESTING 2252 int encode_request_firmware_data_req( 2253 uint8_t instance_id, 2254 const struct pldm_request_firmware_data_req *req_params, 2255 struct pldm_msg *msg, size_t *payload_length) 2256 { 2257 PLDM_MSGBUF_DEFINE_P(buf); 2258 int rc; 2259 2260 if (msg == NULL || payload_length == NULL) { 2261 return -EINVAL; 2262 } 2263 2264 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 2265 PLDM_REQUEST_FIRMWARE_DATA, msg); 2266 if (rc) { 2267 return -EINVAL; 2268 } 2269 2270 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2271 if (rc) { 2272 return rc; 2273 } 2274 2275 pldm_msgbuf_insert(buf, req_params->offset); 2276 pldm_msgbuf_insert(buf, req_params->length); 2277 2278 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length); 2279 } 2280 2281 LIBPLDM_ABI_STABLE 2282 int encode_request_firmware_data_resp(uint8_t instance_id, 2283 uint8_t completion_code, 2284 struct pldm_msg *msg, 2285 size_t payload_length) 2286 { 2287 if (msg == NULL || !payload_length) { 2288 return PLDM_ERROR_INVALID_DATA; 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_REQUEST_FIRMWARE_DATA; 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_transfer_complete_req(const struct pldm_msg *msg, 2308 size_t payload_length, 2309 uint8_t *transfer_result) 2310 { 2311 if (msg == NULL || transfer_result == NULL) { 2312 return PLDM_ERROR_INVALID_DATA; 2313 } 2314 2315 if (payload_length != sizeof(*transfer_result)) { 2316 return PLDM_ERROR_INVALID_LENGTH; 2317 } 2318 2319 *transfer_result = msg->payload[0]; 2320 return PLDM_SUCCESS; 2321 } 2322 2323 LIBPLDM_ABI_TESTING 2324 int encode_transfer_complete_req(uint8_t instance_id, uint8_t transfer_result, 2325 struct pldm_msg *msg, size_t *payload_length) 2326 { 2327 PLDM_MSGBUF_DEFINE_P(buf); 2328 int rc; 2329 2330 if (msg == NULL || payload_length == NULL) { 2331 return -EINVAL; 2332 } 2333 2334 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 2335 PLDM_TRANSFER_COMPLETE, msg); 2336 if (rc) { 2337 return -EINVAL; 2338 } 2339 2340 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2341 if (rc) { 2342 return rc; 2343 } 2344 2345 pldm_msgbuf_insert(buf, transfer_result); 2346 2347 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length); 2348 } 2349 2350 LIBPLDM_ABI_STABLE 2351 int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code, 2352 struct pldm_msg *msg, size_t payload_length) 2353 { 2354 if (msg == NULL) { 2355 return PLDM_ERROR_INVALID_DATA; 2356 } 2357 2358 if (payload_length != sizeof(completion_code)) { 2359 return PLDM_ERROR_INVALID_LENGTH; 2360 } 2361 2362 struct pldm_header_info header = { 0 }; 2363 header.instance = instance_id; 2364 header.msg_type = PLDM_RESPONSE; 2365 header.pldm_type = PLDM_FWUP; 2366 header.command = PLDM_TRANSFER_COMPLETE; 2367 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2368 if (rc) { 2369 return rc; 2370 } 2371 2372 msg->payload[0] = completion_code; 2373 2374 return PLDM_SUCCESS; 2375 } 2376 2377 LIBPLDM_ABI_STABLE 2378 int decode_verify_complete_req(const struct pldm_msg *msg, 2379 size_t payload_length, uint8_t *verify_result) 2380 { 2381 if (msg == NULL || verify_result == NULL) { 2382 return PLDM_ERROR_INVALID_DATA; 2383 } 2384 2385 if (payload_length != sizeof(*verify_result)) { 2386 return PLDM_ERROR_INVALID_LENGTH; 2387 } 2388 2389 *verify_result = msg->payload[0]; 2390 return PLDM_SUCCESS; 2391 } 2392 2393 LIBPLDM_ABI_TESTING 2394 int encode_verify_complete_req(uint8_t instance_id, uint8_t verify_result, 2395 struct pldm_msg *msg, size_t *payload_length) 2396 { 2397 PLDM_MSGBUF_DEFINE_P(buf); 2398 int rc; 2399 2400 if (msg == NULL || payload_length == NULL) { 2401 return -EINVAL; 2402 } 2403 2404 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 2405 PLDM_VERIFY_COMPLETE, msg); 2406 if (rc) { 2407 return EINVAL; 2408 } 2409 2410 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2411 if (rc) { 2412 return rc; 2413 } 2414 2415 pldm_msgbuf_insert(buf, verify_result); 2416 2417 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length); 2418 } 2419 2420 LIBPLDM_ABI_STABLE 2421 int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code, 2422 struct pldm_msg *msg, size_t payload_length) 2423 { 2424 if (msg == NULL) { 2425 return PLDM_ERROR_INVALID_DATA; 2426 } 2427 2428 if (payload_length != sizeof(completion_code)) { 2429 return PLDM_ERROR_INVALID_LENGTH; 2430 } 2431 2432 struct pldm_header_info header = { 0 }; 2433 header.instance = instance_id; 2434 header.msg_type = PLDM_RESPONSE; 2435 header.pldm_type = PLDM_FWUP; 2436 header.command = PLDM_VERIFY_COMPLETE; 2437 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2438 if (rc) { 2439 return rc; 2440 } 2441 2442 msg->payload[0] = completion_code; 2443 2444 return PLDM_SUCCESS; 2445 } 2446 2447 LIBPLDM_ABI_STABLE 2448 int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length, 2449 uint8_t *apply_result, 2450 bitfield16_t *comp_activation_methods_modification) 2451 { 2452 if (msg == NULL || apply_result == NULL || 2453 comp_activation_methods_modification == NULL) { 2454 return PLDM_ERROR_INVALID_DATA; 2455 } 2456 2457 if (payload_length != sizeof(struct pldm_apply_complete_req)) { 2458 return PLDM_ERROR_INVALID_LENGTH; 2459 } 2460 2461 struct pldm_apply_complete_req *request = 2462 (struct pldm_apply_complete_req *)msg->payload; 2463 2464 *apply_result = request->apply_result; 2465 comp_activation_methods_modification->value = 2466 le16toh(request->comp_activation_methods_modification.value); 2467 2468 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) && 2469 comp_activation_methods_modification->value) { 2470 return PLDM_ERROR_INVALID_DATA; 2471 } 2472 2473 return PLDM_SUCCESS; 2474 } 2475 2476 LIBPLDM_ABI_TESTING 2477 int encode_apply_complete_req(uint8_t instance_id, 2478 const struct pldm_apply_complete_req *req_data, 2479 struct pldm_msg *msg, size_t *payload_length) 2480 { 2481 PLDM_MSGBUF_DEFINE_P(buf); 2482 int rc; 2483 2484 if (msg == NULL || payload_length == NULL) { 2485 return -EINVAL; 2486 } 2487 2488 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 2489 PLDM_APPLY_COMPLETE, msg); 2490 if (rc) { 2491 return -EINVAL; 2492 } 2493 2494 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2495 if (rc) { 2496 return rc; 2497 } 2498 2499 pldm_msgbuf_insert(buf, req_data->apply_result); 2500 pldm_msgbuf_insert( 2501 buf, req_data->comp_activation_methods_modification.value); 2502 2503 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length); 2504 } 2505 2506 LIBPLDM_ABI_STABLE 2507 int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code, 2508 struct pldm_msg *msg, size_t payload_length) 2509 { 2510 if (msg == NULL) { 2511 return PLDM_ERROR_INVALID_DATA; 2512 } 2513 2514 if (payload_length != sizeof(completion_code)) { 2515 return PLDM_ERROR_INVALID_LENGTH; 2516 } 2517 2518 struct pldm_header_info header = { 0 }; 2519 header.instance = instance_id; 2520 header.msg_type = PLDM_RESPONSE; 2521 header.pldm_type = PLDM_FWUP; 2522 header.command = PLDM_APPLY_COMPLETE; 2523 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2524 if (rc) { 2525 return rc; 2526 } 2527 2528 msg->payload[0] = completion_code; 2529 2530 return PLDM_SUCCESS; 2531 } 2532 2533 LIBPLDM_ABI_TESTING 2534 int decode_activate_firmware_req(const struct pldm_msg *msg, 2535 size_t payload_length, bool *self_contained) 2536 { 2537 uint8_t self_contained_u8 = 0; 2538 PLDM_MSGBUF_DEFINE_P(buf); 2539 int rc; 2540 2541 if (msg == NULL || self_contained == NULL) { 2542 return -EINVAL; 2543 } 2544 2545 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length); 2546 if (rc) { 2547 return 0; 2548 } 2549 2550 pldm_msgbuf_extract(buf, self_contained_u8); 2551 2552 rc = pldm_msgbuf_complete_consumed(buf); 2553 if (rc) { 2554 return rc; 2555 } 2556 2557 *self_contained = (bool)self_contained_u8; 2558 return 0; 2559 } 2560 2561 LIBPLDM_ABI_STABLE 2562 int encode_activate_firmware_req(uint8_t instance_id, 2563 bool8_t self_contained_activation_req, 2564 struct pldm_msg *msg, size_t payload_length) 2565 { 2566 if (msg == NULL) { 2567 return PLDM_ERROR_INVALID_DATA; 2568 } 2569 2570 if (payload_length != sizeof(struct pldm_activate_firmware_req)) { 2571 return PLDM_ERROR_INVALID_LENGTH; 2572 } 2573 2574 if (!is_self_contained_activation_req_valid( 2575 self_contained_activation_req)) { 2576 return PLDM_ERROR_INVALID_DATA; 2577 } 2578 2579 struct pldm_header_info header = { 0 }; 2580 header.instance = instance_id; 2581 header.msg_type = PLDM_REQUEST; 2582 header.pldm_type = PLDM_FWUP; 2583 header.command = PLDM_ACTIVATE_FIRMWARE; 2584 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2585 if (rc) { 2586 return rc; 2587 } 2588 2589 struct pldm_activate_firmware_req *request = 2590 (struct pldm_activate_firmware_req *)msg->payload; 2591 2592 request->self_contained_activation_req = self_contained_activation_req; 2593 2594 return PLDM_SUCCESS; 2595 } 2596 2597 LIBPLDM_ABI_STABLE 2598 int decode_activate_firmware_resp(const struct pldm_msg *msg, 2599 size_t payload_length, 2600 uint8_t *completion_code, 2601 uint16_t *estimated_time_activation) 2602 { 2603 if (msg == NULL || completion_code == NULL || 2604 estimated_time_activation == NULL || !payload_length) { 2605 return PLDM_ERROR_INVALID_DATA; 2606 } 2607 2608 *completion_code = msg->payload[0]; 2609 if (*completion_code != PLDM_SUCCESS) { 2610 return PLDM_SUCCESS; 2611 } 2612 2613 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) { 2614 return PLDM_ERROR_INVALID_LENGTH; 2615 } 2616 2617 struct pldm_activate_firmware_resp *response = 2618 (struct pldm_activate_firmware_resp *)msg->payload; 2619 2620 *estimated_time_activation = 2621 le16toh(response->estimated_time_activation); 2622 2623 return PLDM_SUCCESS; 2624 } 2625 2626 LIBPLDM_ABI_TESTING 2627 int encode_activate_firmware_resp( 2628 uint8_t instance_id, 2629 const struct pldm_activate_firmware_resp *resp_data, 2630 struct pldm_msg *msg, size_t *payload_length) 2631 { 2632 PLDM_MSGBUF_DEFINE_P(buf); 2633 int rc; 2634 2635 if (msg == NULL || payload_length == NULL) { 2636 return -EINVAL; 2637 } 2638 2639 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 2640 PLDM_ACTIVATE_FIRMWARE, msg); 2641 if (rc) { 2642 return -EINVAL; 2643 } 2644 2645 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2646 if (rc) { 2647 return rc; 2648 } 2649 2650 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 2651 pldm_msgbuf_insert(buf, resp_data->estimated_time_activation); 2652 2653 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length); 2654 } 2655 2656 LIBPLDM_ABI_STABLE 2657 int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg, 2658 size_t payload_length) 2659 { 2660 if (msg == NULL) { 2661 return PLDM_ERROR_INVALID_DATA; 2662 } 2663 2664 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) { 2665 return PLDM_ERROR_INVALID_LENGTH; 2666 } 2667 2668 struct pldm_header_info header = { 0 }; 2669 header.instance = instance_id; 2670 header.msg_type = PLDM_REQUEST; 2671 header.pldm_type = PLDM_FWUP; 2672 header.command = PLDM_GET_STATUS; 2673 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2674 if (rc) { 2675 return rc; 2676 } 2677 2678 return PLDM_SUCCESS; 2679 } 2680 2681 LIBPLDM_ABI_STABLE 2682 int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length, 2683 uint8_t *completion_code, uint8_t *current_state, 2684 uint8_t *previous_state, uint8_t *aux_state, 2685 uint8_t *aux_state_status, uint8_t *progress_percent, 2686 uint8_t *reason_code, 2687 bitfield32_t *update_option_flags_enabled) 2688 { 2689 if (msg == NULL || completion_code == NULL || current_state == NULL || 2690 previous_state == NULL || aux_state == NULL || 2691 aux_state_status == NULL || progress_percent == NULL || 2692 reason_code == NULL || update_option_flags_enabled == NULL || 2693 !payload_length) { 2694 return PLDM_ERROR_INVALID_DATA; 2695 } 2696 2697 *completion_code = msg->payload[0]; 2698 if (*completion_code != PLDM_SUCCESS) { 2699 return PLDM_SUCCESS; 2700 } 2701 2702 if (payload_length != sizeof(struct pldm_get_status_resp)) { 2703 return PLDM_ERROR_INVALID_LENGTH; 2704 } 2705 struct pldm_get_status_resp *response = 2706 (struct pldm_get_status_resp *)msg->payload; 2707 2708 if (!is_state_valid(response->current_state)) { 2709 return PLDM_ERROR_INVALID_DATA; 2710 } 2711 if (!is_state_valid(response->previous_state)) { 2712 return PLDM_ERROR_INVALID_DATA; 2713 } 2714 if (!is_aux_state_valid(response->aux_state)) { 2715 return PLDM_ERROR_INVALID_DATA; 2716 } 2717 if (!is_aux_state_status_valid(response->aux_state_status)) { 2718 return PLDM_ERROR_INVALID_DATA; 2719 } 2720 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) { 2721 return PLDM_ERROR_INVALID_DATA; 2722 } 2723 if (!is_reason_code_valid(response->reason_code)) { 2724 return PLDM_ERROR_INVALID_DATA; 2725 } 2726 2727 if ((response->current_state == PLDM_FD_STATE_IDLE) || 2728 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) || 2729 (response->current_state == PLDM_FD_STATE_READY_XFER)) { 2730 if (response->aux_state != 2731 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) { 2732 return PLDM_ERROR_INVALID_DATA; 2733 } 2734 } 2735 2736 *current_state = response->current_state; 2737 *previous_state = response->previous_state; 2738 *aux_state = response->aux_state; 2739 *aux_state_status = response->aux_state_status; 2740 *progress_percent = response->progress_percent; 2741 *reason_code = response->reason_code; 2742 update_option_flags_enabled->value = 2743 le32toh(response->update_option_flags_enabled.value); 2744 2745 return PLDM_SUCCESS; 2746 } 2747 2748 LIBPLDM_ABI_TESTING 2749 int encode_get_status_resp(uint8_t instance_id, 2750 const struct pldm_get_status_resp *status, 2751 struct pldm_msg *msg, size_t *payload_length) 2752 { 2753 PLDM_MSGBUF_DEFINE_P(buf); 2754 int rc; 2755 2756 if (status == NULL || msg == NULL || payload_length == NULL) { 2757 return -EINVAL; 2758 } 2759 2760 if (status->completion_code != PLDM_SUCCESS) { 2761 return -EINVAL; 2762 } 2763 2764 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 2765 PLDM_GET_STATUS, msg); 2766 if (rc) { 2767 return -EINVAL; 2768 } 2769 2770 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2771 if (rc) { 2772 return rc; 2773 } 2774 2775 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 2776 pldm_msgbuf_insert(buf, status->current_state); 2777 pldm_msgbuf_insert(buf, status->previous_state); 2778 pldm_msgbuf_insert(buf, status->aux_state); 2779 pldm_msgbuf_insert(buf, status->aux_state_status); 2780 pldm_msgbuf_insert(buf, status->progress_percent); 2781 pldm_msgbuf_insert(buf, status->reason_code); 2782 pldm_msgbuf_insert(buf, status->update_option_flags_enabled.value); 2783 2784 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length); 2785 } 2786 2787 LIBPLDM_ABI_STABLE 2788 int encode_cancel_update_component_req(uint8_t instance_id, 2789 struct pldm_msg *msg, 2790 size_t payload_length) 2791 { 2792 if (msg == NULL) { 2793 return PLDM_ERROR_INVALID_DATA; 2794 } 2795 2796 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) { 2797 return PLDM_ERROR_INVALID_LENGTH; 2798 } 2799 2800 struct pldm_header_info header = { 0 }; 2801 header.instance = instance_id; 2802 header.msg_type = PLDM_REQUEST; 2803 header.pldm_type = PLDM_FWUP; 2804 header.command = PLDM_CANCEL_UPDATE_COMPONENT; 2805 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2806 if (rc) { 2807 return rc; 2808 } 2809 2810 return PLDM_SUCCESS; 2811 } 2812 2813 LIBPLDM_ABI_STABLE 2814 int decode_cancel_update_component_resp(const struct pldm_msg *msg, 2815 size_t payload_length, 2816 uint8_t *completion_code) 2817 { 2818 if (msg == NULL || completion_code == NULL) { 2819 return PLDM_ERROR_INVALID_DATA; 2820 } 2821 2822 if (payload_length != sizeof(*completion_code)) { 2823 return PLDM_ERROR_INVALID_LENGTH; 2824 } 2825 2826 *completion_code = msg->payload[0]; 2827 return PLDM_SUCCESS; 2828 } 2829 2830 LIBPLDM_ABI_STABLE 2831 int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg, 2832 size_t payload_length) 2833 { 2834 if (msg == NULL) { 2835 return PLDM_ERROR_INVALID_DATA; 2836 } 2837 2838 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) { 2839 return PLDM_ERROR_INVALID_LENGTH; 2840 } 2841 2842 struct pldm_header_info header = { 0 }; 2843 header.instance = instance_id; 2844 header.msg_type = PLDM_REQUEST; 2845 header.pldm_type = PLDM_FWUP; 2846 header.command = PLDM_CANCEL_UPDATE; 2847 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2848 if (rc) { 2849 return rc; 2850 } 2851 2852 return PLDM_SUCCESS; 2853 } 2854 2855 LIBPLDM_ABI_STABLE 2856 int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length, 2857 uint8_t *completion_code, 2858 bool8_t *non_functioning_component_indication, 2859 bitfield64_t *non_functioning_component_bitmap) 2860 { 2861 if (msg == NULL || completion_code == NULL || 2862 non_functioning_component_indication == NULL || 2863 non_functioning_component_bitmap == NULL || !payload_length) { 2864 return PLDM_ERROR_INVALID_DATA; 2865 } 2866 2867 *completion_code = msg->payload[0]; 2868 if (*completion_code != PLDM_SUCCESS) { 2869 return PLDM_SUCCESS; 2870 } 2871 2872 if (payload_length != sizeof(struct pldm_cancel_update_resp)) { 2873 return PLDM_ERROR_INVALID_LENGTH; 2874 } 2875 struct pldm_cancel_update_resp *response = 2876 (struct pldm_cancel_update_resp *)msg->payload; 2877 2878 if (!is_non_functioning_component_indication_valid( 2879 response->non_functioning_component_indication)) { 2880 return PLDM_ERROR_INVALID_DATA; 2881 } 2882 2883 *non_functioning_component_indication = 2884 response->non_functioning_component_indication; 2885 2886 if (*non_functioning_component_indication) { 2887 non_functioning_component_bitmap->value = 2888 le64toh(response->non_functioning_component_bitmap); 2889 } 2890 2891 return PLDM_SUCCESS; 2892 } 2893 2894 LIBPLDM_ABI_TESTING 2895 int encode_cancel_update_resp(uint8_t instance_id, 2896 const struct pldm_cancel_update_resp *resp_data, 2897 struct pldm_msg *msg, size_t *payload_length) 2898 { 2899 PLDM_MSGBUF_DEFINE_P(buf); 2900 int rc; 2901 2902 if (msg == NULL || payload_length == NULL) { 2903 return -EINVAL; 2904 } 2905 2906 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 2907 PLDM_CANCEL_UPDATE, msg); 2908 if (rc) { 2909 return -EINVAL; 2910 } 2911 2912 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2913 if (rc) { 2914 return rc; 2915 } 2916 2917 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 2918 pldm_msgbuf_insert(buf, 2919 resp_data->non_functioning_component_indication); 2920 pldm_msgbuf_insert(buf, resp_data->non_functioning_component_bitmap); 2921 2922 return pldm_msgbuf_complete_used(buf, *payload_length, payload_length); 2923 } 2924