1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */ 2 #include "dsp/base.h" 3 #include "msgbuf.h" 4 #include <libpldm/firmware_update.h> 5 #include <libpldm/utils.h> 6 7 #include <endian.h> 8 #include <stdbool.h> 9 #include <string.h> 10 11 /** @brief Check whether string type value is valid 12 * 13 * @return true if string type value is valid, false if not 14 */ 15 static bool is_string_type_valid(uint8_t string_type) 16 { 17 switch (string_type) { 18 case PLDM_STR_TYPE_UNKNOWN: 19 return false; 20 case PLDM_STR_TYPE_ASCII: 21 case PLDM_STR_TYPE_UTF_8: 22 case PLDM_STR_TYPE_UTF_16: 23 case PLDM_STR_TYPE_UTF_16LE: 24 case PLDM_STR_TYPE_UTF_16BE: 25 return true; 26 default: 27 return false; 28 } 29 } 30 31 /** @brief Return the length of the descriptor type described in firmware update 32 * specification 33 * 34 * @return length of the descriptor type if descriptor type is valid else 35 * return 0 36 */ 37 static uint16_t get_descriptor_type_length(uint16_t descriptor_type) 38 { 39 switch (descriptor_type) { 40 case PLDM_FWUP_PCI_VENDOR_ID: 41 return PLDM_FWUP_PCI_VENDOR_ID_LENGTH; 42 case PLDM_FWUP_IANA_ENTERPRISE_ID: 43 return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH; 44 case PLDM_FWUP_UUID: 45 return PLDM_FWUP_UUID_LENGTH; 46 case PLDM_FWUP_PNP_VENDOR_ID: 47 return PLDM_FWUP_PNP_VENDOR_ID_LENGTH; 48 case PLDM_FWUP_ACPI_VENDOR_ID: 49 return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH; 50 case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID: 51 return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH; 52 case PLDM_FWUP_SCSI_VENDOR_ID: 53 return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH; 54 case PLDM_FWUP_PCI_DEVICE_ID: 55 return PLDM_FWUP_PCI_DEVICE_ID_LENGTH; 56 case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID: 57 return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH; 58 case PLDM_FWUP_PCI_SUBSYSTEM_ID: 59 return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH; 60 case PLDM_FWUP_PCI_REVISION_ID: 61 return PLDM_FWUP_PCI_REVISION_ID_LENGTH; 62 case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER: 63 return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH; 64 case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER: 65 return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH; 66 case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING: 67 return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH; 68 case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING: 69 return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH; 70 case PLDM_FWUP_SCSI_PRODUCT_ID: 71 return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH; 72 case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE: 73 return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH; 74 default: 75 return 0; 76 } 77 } 78 79 static bool is_downstream_device_update_support_valid(uint8_t resp) 80 { 81 switch (resp) { 82 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED: 83 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED: 84 return true; 85 default: 86 return false; 87 } 88 } 89 90 static bool 91 is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag) 92 { 93 switch (transfer_op_flag) { 94 case PLDM_GET_NEXTPART: 95 case PLDM_GET_FIRSTPART: 96 return true; 97 default: 98 return false; 99 } 100 } 101 102 /** @brief Check whether ComponentResponse is valid 103 * 104 * @return true if ComponentResponse is valid, false if not 105 */ 106 static bool is_comp_resp_valid(uint8_t comp_resp) 107 { 108 switch (comp_resp) { 109 case PLDM_CR_COMP_CAN_BE_UPDATED: 110 case PLDM_CR_COMP_MAY_BE_UPDATEABLE: 111 return true; 112 113 default: 114 return false; 115 } 116 } 117 118 /** @brief Check whether ComponentResponseCode is valid 119 * 120 * @return true if ComponentResponseCode is valid, false if not 121 */ 122 static bool is_comp_resp_code_valid(uint8_t comp_resp_code) 123 { 124 switch (comp_resp_code) { 125 case PLDM_CRC_COMP_CAN_BE_UPDATED: 126 case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL: 127 case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER: 128 case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP: 129 case PLDM_CRC_COMP_CONFLICT: 130 case PLDM_CRC_COMP_PREREQUISITES_NOT_MET: 131 case PLDM_CRC_COMP_NOT_SUPPORTED: 132 case PLDM_CRC_COMP_SECURITY_RESTRICTIONS: 133 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET: 134 case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY: 135 case PLDM_CRC_COMP_VER_STR_IDENTICAL: 136 case PLDM_CRC_COMP_VER_STR_LOWER: 137 return true; 138 139 default: 140 if (comp_resp_code >= 141 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN && 142 comp_resp_code <= 143 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) { 144 return true; 145 } 146 return false; 147 } 148 } 149 150 /** @brief Check whether ComponentCompatibilityResponse is valid 151 * 152 * @return true if ComponentCompatibilityResponse is valid, false if not 153 */ 154 static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp) 155 { 156 switch (comp_compatibility_resp) { 157 case PLDM_CCR_COMP_CAN_BE_UPDATED: 158 case PLDM_CCR_COMP_CANNOT_BE_UPDATED: 159 return true; 160 161 default: 162 return false; 163 } 164 } 165 166 /** @brief Check whether ComponentCompatibilityResponse Code is valid 167 * 168 * @return true if ComponentCompatibilityResponse Code is valid, false if not 169 */ 170 static bool 171 is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code) 172 { 173 switch (comp_compatibility_resp_code) { 174 case PLDM_CCRC_NO_RESPONSE_CODE: 175 case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL: 176 case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER: 177 case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP: 178 case PLDM_CCRC_COMP_CONFLICT: 179 case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET: 180 case PLDM_CCRC_COMP_NOT_SUPPORTED: 181 case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS: 182 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET: 183 case PLDM_CCRC_COMP_INFO_NO_MATCH: 184 case PLDM_CCRC_COMP_VER_STR_IDENTICAL: 185 case PLDM_CCRC_COMP_VER_STR_LOWER: 186 return true; 187 188 default: 189 if (comp_compatibility_resp_code >= 190 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN && 191 comp_compatibility_resp_code <= 192 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) { 193 return true; 194 } 195 return false; 196 } 197 } 198 199 /** @brief Check whether SelfContainedActivationRequest is valid 200 * 201 * @return true if SelfContainedActivationRequest is valid, false if not 202 */ 203 static bool 204 is_self_contained_activation_req_valid(bool8_t self_contained_activation_req) 205 { 206 switch (self_contained_activation_req) { 207 case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS: 208 case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS: 209 return true; 210 211 default: 212 return false; 213 } 214 } 215 216 /** @brief Check if current or previous status in GetStatus command response is 217 * valid 218 * 219 * @param[in] state - current or previous different state machine state of 220 * the FD 221 * @return true if state is valid, false if not 222 */ 223 static bool is_state_valid(uint8_t state) 224 { 225 switch (state) { 226 case PLDM_FD_STATE_IDLE: 227 case PLDM_FD_STATE_LEARN_COMPONENTS: 228 case PLDM_FD_STATE_READY_XFER: 229 case PLDM_FD_STATE_DOWNLOAD: 230 case PLDM_FD_STATE_VERIFY: 231 case PLDM_FD_STATE_APPLY: 232 case PLDM_FD_STATE_ACTIVATE: 233 return true; 234 235 default: 236 return false; 237 } 238 } 239 240 /** @brief Check if aux state in GetStatus command response is valid 241 * 242 * @param[in] aux_state - provides additional information to the UA to describe 243 * the current operation state of the FD/FDP 244 * 245 * @return true if aux state is valid, false if not 246 */ 247 static bool is_aux_state_valid(uint8_t aux_state) 248 { 249 switch (aux_state) { 250 case PLDM_FD_OPERATION_IN_PROGRESS: 251 case PLDM_FD_OPERATION_SUCCESSFUL: 252 case PLDM_FD_OPERATION_FAILED: 253 case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER: 254 return true; 255 256 default: 257 return false; 258 } 259 } 260 261 /** @brief Check if aux state status in GetStatus command response is valid 262 * 263 * @param[in] aux_state_status - aux state status 264 * 265 * @return true if aux state status is valid, false if not 266 */ 267 static bool is_aux_state_status_valid(uint8_t aux_state_status) 268 { 269 if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS || 270 aux_state_status == PLDM_FD_TIMEOUT || 271 aux_state_status == PLDM_FD_GENERIC_ERROR || 272 (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START && 273 aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) { 274 return true; 275 } 276 277 return false; 278 } 279 280 /** @brief Check if reason code in GetStatus command response is valid 281 * 282 * @param[in] reason_code - provides the reason for why the current state 283 * entered the IDLE state 284 * 285 * @return true if reason code is valid, false if not 286 */ 287 static bool is_reason_code_valid(uint8_t reason_code) 288 { 289 switch (reason_code) { 290 case PLDM_FD_INITIALIZATION: 291 case PLDM_FD_ACTIVATE_FW: 292 case PLDM_FD_CANCEL_UPDATE: 293 case PLDM_FD_TIMEOUT_LEARN_COMPONENT: 294 case PLDM_FD_TIMEOUT_READY_XFER: 295 case PLDM_FD_TIMEOUT_DOWNLOAD: 296 case PLDM_FD_TIMEOUT_VERIFY: 297 case PLDM_FD_TIMEOUT_APPLY: 298 return true; 299 300 default: 301 if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) { 302 return true; 303 } 304 return false; 305 } 306 } 307 308 /** @brief Check if non functioning component indication in CancelUpdate 309 * response is valid 310 * 311 * @return true if non functioning component indication is valid, false if not 312 */ 313 static bool is_non_functioning_component_indication_valid( 314 bool8_t non_functioning_component_indication) 315 { 316 switch (non_functioning_component_indication) { 317 case PLDM_FWUP_COMPONENTS_FUNCTIONING: 318 case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING: 319 return true; 320 321 default: 322 return false; 323 } 324 } 325 326 LIBPLDM_ABI_STABLE 327 int decode_pldm_package_header_info( 328 const uint8_t *data, size_t length, 329 struct pldm_package_header_information *package_header_info, 330 struct variable_field *package_version_str) 331 { 332 if (data == NULL || package_header_info == NULL || 333 package_version_str == NULL) { 334 return PLDM_ERROR_INVALID_DATA; 335 } 336 337 if (length < sizeof(struct pldm_package_header_information)) { 338 return PLDM_ERROR_INVALID_LENGTH; 339 } 340 341 struct pldm_package_header_information *data_header = 342 (struct pldm_package_header_information *)(data); 343 344 if (!is_string_type_valid(data_header->package_version_string_type) || 345 (data_header->package_version_string_length == 0)) { 346 return PLDM_ERROR_INVALID_DATA; 347 } 348 349 if (length < sizeof(struct pldm_package_header_information) + 350 data_header->package_version_string_length) { 351 return PLDM_ERROR_INVALID_LENGTH; 352 } 353 354 if ((data_header->component_bitmap_bit_length % 355 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) { 356 return PLDM_ERROR_INVALID_DATA; 357 } 358 359 memcpy(package_header_info->uuid, data_header->uuid, 360 sizeof(data_header->uuid)); 361 package_header_info->package_header_format_version = 362 data_header->package_header_format_version; 363 package_header_info->package_header_size = 364 le16toh(data_header->package_header_size); 365 memcpy(package_header_info->package_release_date_time, 366 data_header->package_release_date_time, 367 sizeof(data_header->package_release_date_time)); 368 package_header_info->component_bitmap_bit_length = 369 le16toh(data_header->component_bitmap_bit_length); 370 package_header_info->package_version_string_type = 371 data_header->package_version_string_type; 372 package_header_info->package_version_string_length = 373 data_header->package_version_string_length; 374 package_version_str->ptr = 375 data + sizeof(struct pldm_package_header_information); 376 package_version_str->length = 377 package_header_info->package_version_string_length; 378 379 return PLDM_SUCCESS; 380 } 381 382 LIBPLDM_ABI_STABLE 383 int decode_firmware_device_id_record( 384 const uint8_t *data, size_t length, 385 uint16_t component_bitmap_bit_length, 386 struct pldm_firmware_device_id_record *fw_device_id_record, 387 struct variable_field *applicable_components, 388 struct variable_field *comp_image_set_version_str, 389 struct variable_field *record_descriptors, 390 struct variable_field *fw_device_pkg_data) 391 { 392 if (data == NULL || fw_device_id_record == NULL || 393 applicable_components == NULL || 394 comp_image_set_version_str == NULL || record_descriptors == NULL || 395 fw_device_pkg_data == NULL) { 396 return PLDM_ERROR_INVALID_DATA; 397 } 398 399 if (length < sizeof(struct pldm_firmware_device_id_record)) { 400 return PLDM_ERROR_INVALID_LENGTH; 401 } 402 403 if ((component_bitmap_bit_length % 404 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) { 405 return PLDM_ERROR_INVALID_DATA; 406 } 407 408 struct pldm_firmware_device_id_record *data_record = 409 (struct pldm_firmware_device_id_record *)(data); 410 411 if (!is_string_type_valid( 412 data_record->comp_image_set_version_string_type) || 413 (data_record->comp_image_set_version_string_length == 0)) { 414 return PLDM_ERROR_INVALID_DATA; 415 } 416 417 fw_device_id_record->record_length = 418 le16toh(data_record->record_length); 419 fw_device_id_record->descriptor_count = data_record->descriptor_count; 420 fw_device_id_record->device_update_option_flags.value = 421 le32toh(data_record->device_update_option_flags.value); 422 fw_device_id_record->comp_image_set_version_string_type = 423 data_record->comp_image_set_version_string_type; 424 fw_device_id_record->comp_image_set_version_string_length = 425 data_record->comp_image_set_version_string_length; 426 fw_device_id_record->fw_device_pkg_data_length = 427 le16toh(data_record->fw_device_pkg_data_length); 428 429 if (length < fw_device_id_record->record_length) { 430 return PLDM_ERROR_INVALID_LENGTH; 431 } 432 433 uint16_t applicable_components_length = 434 component_bitmap_bit_length / 435 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE; 436 uint16_t calc_min_record_length = 437 sizeof(struct pldm_firmware_device_id_record) + 438 applicable_components_length + 439 data_record->comp_image_set_version_string_length + 440 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN + 441 fw_device_id_record->fw_device_pkg_data_length; 442 443 if (fw_device_id_record->record_length < calc_min_record_length) { 444 return PLDM_ERROR_INVALID_LENGTH; 445 } 446 447 applicable_components->ptr = 448 data + sizeof(struct pldm_firmware_device_id_record); 449 applicable_components->length = applicable_components_length; 450 451 comp_image_set_version_str->ptr = 452 applicable_components->ptr + applicable_components->length; 453 comp_image_set_version_str->length = 454 fw_device_id_record->comp_image_set_version_string_length; 455 456 record_descriptors->ptr = comp_image_set_version_str->ptr + 457 comp_image_set_version_str->length; 458 record_descriptors->length = 459 fw_device_id_record->record_length - 460 sizeof(struct pldm_firmware_device_id_record) - 461 applicable_components_length - 462 fw_device_id_record->comp_image_set_version_string_length - 463 fw_device_id_record->fw_device_pkg_data_length; 464 465 if (fw_device_id_record->fw_device_pkg_data_length) { 466 fw_device_pkg_data->ptr = 467 record_descriptors->ptr + record_descriptors->length; 468 fw_device_pkg_data->length = 469 fw_device_id_record->fw_device_pkg_data_length; 470 } 471 472 return PLDM_SUCCESS; 473 } 474 475 LIBPLDM_ABI_STABLE 476 int decode_descriptor_type_length_value(const uint8_t *data, size_t length, 477 uint16_t *descriptor_type, 478 struct variable_field *descriptor_data) 479 { 480 uint16_t descriptor_length = 0; 481 482 if (data == NULL || descriptor_type == NULL || 483 descriptor_data == NULL) { 484 return PLDM_ERROR_INVALID_DATA; 485 } 486 487 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) { 488 return PLDM_ERROR_INVALID_LENGTH; 489 } 490 491 struct pldm_descriptor_tlv *entry = 492 (struct pldm_descriptor_tlv *)(data); 493 494 *descriptor_type = le16toh(entry->descriptor_type); 495 descriptor_length = le16toh(entry->descriptor_length); 496 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) { 497 if (descriptor_length != 498 get_descriptor_type_length(*descriptor_type)) { 499 return PLDM_ERROR_INVALID_LENGTH; 500 } 501 } 502 503 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) + 504 descriptor_length)) { 505 return PLDM_ERROR_INVALID_LENGTH; 506 } 507 508 descriptor_data->ptr = entry->descriptor_data; 509 descriptor_data->length = descriptor_length; 510 511 return PLDM_SUCCESS; 512 } 513 514 LIBPLDM_ABI_STABLE 515 int decode_vendor_defined_descriptor_value( 516 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type, 517 struct variable_field *descriptor_title_str, 518 struct variable_field *descriptor_data) 519 { 520 if (data == NULL || descriptor_title_str_type == NULL || 521 descriptor_title_str == NULL || descriptor_data == NULL) { 522 return PLDM_ERROR_INVALID_DATA; 523 } 524 525 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) { 526 return PLDM_ERROR_INVALID_LENGTH; 527 } 528 529 struct pldm_vendor_defined_descriptor_title_data *entry = 530 (struct pldm_vendor_defined_descriptor_title_data *)(data); 531 if (!is_string_type_valid( 532 entry->vendor_defined_descriptor_title_str_type) || 533 (entry->vendor_defined_descriptor_title_str_len == 0)) { 534 return PLDM_ERROR_INVALID_DATA; 535 } 536 537 // Assuming at least 1 byte of VendorDefinedDescriptorData 538 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) + 539 entry->vendor_defined_descriptor_title_str_len)) { 540 return PLDM_ERROR_INVALID_LENGTH; 541 } 542 543 *descriptor_title_str_type = 544 entry->vendor_defined_descriptor_title_str_type; 545 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str; 546 descriptor_title_str->length = 547 entry->vendor_defined_descriptor_title_str_len; 548 549 descriptor_data->ptr = 550 descriptor_title_str->ptr + descriptor_title_str->length; 551 descriptor_data->length = 552 length - 553 sizeof(entry->vendor_defined_descriptor_title_str_type) - 554 sizeof(entry->vendor_defined_descriptor_title_str_len) - 555 descriptor_title_str->length; 556 557 return PLDM_SUCCESS; 558 } 559 560 LIBPLDM_ABI_STABLE 561 int decode_pldm_comp_image_info( 562 const uint8_t *data, size_t length, 563 struct pldm_component_image_information *pldm_comp_image_info, 564 struct variable_field *comp_version_str) 565 { 566 if (data == NULL || pldm_comp_image_info == NULL || 567 comp_version_str == NULL) { 568 return PLDM_ERROR_INVALID_DATA; 569 } 570 571 if (length < sizeof(struct pldm_component_image_information)) { 572 return PLDM_ERROR_INVALID_LENGTH; 573 } 574 575 struct pldm_component_image_information *data_header = 576 (struct pldm_component_image_information *)(data); 577 578 if (!is_string_type_valid(data_header->comp_version_string_type) || 579 (data_header->comp_version_string_length == 0)) { 580 return PLDM_ERROR_INVALID_DATA; 581 } 582 583 if (length < sizeof(struct pldm_component_image_information) + 584 data_header->comp_version_string_length) { 585 return PLDM_ERROR_INVALID_LENGTH; 586 } 587 588 pldm_comp_image_info->comp_classification = 589 le16toh(data_header->comp_classification); 590 pldm_comp_image_info->comp_identifier = 591 le16toh(data_header->comp_identifier); 592 pldm_comp_image_info->comp_comparison_stamp = 593 le32toh(data_header->comp_comparison_stamp); 594 pldm_comp_image_info->comp_options.value = 595 le16toh(data_header->comp_options.value); 596 pldm_comp_image_info->requested_comp_activation_method.value = 597 le16toh(data_header->requested_comp_activation_method.value); 598 pldm_comp_image_info->comp_location_offset = 599 le32toh(data_header->comp_location_offset); 600 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size); 601 pldm_comp_image_info->comp_version_string_type = 602 data_header->comp_version_string_type; 603 pldm_comp_image_info->comp_version_string_length = 604 data_header->comp_version_string_length; 605 606 if ((pldm_comp_image_info->comp_options.bits.bit1 == false && 607 pldm_comp_image_info->comp_comparison_stamp != 608 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) { 609 return PLDM_ERROR_INVALID_DATA; 610 } 611 612 if (pldm_comp_image_info->comp_location_offset == 0 || 613 pldm_comp_image_info->comp_size == 0) { 614 return PLDM_ERROR_INVALID_DATA; 615 } 616 617 comp_version_str->ptr = 618 data + sizeof(struct pldm_component_image_information); 619 comp_version_str->length = 620 pldm_comp_image_info->comp_version_string_length; 621 622 return PLDM_SUCCESS; 623 } 624 625 LIBPLDM_ABI_STABLE 626 int encode_query_device_identifiers_req(uint8_t instance_id, 627 size_t payload_length, 628 struct pldm_msg *msg) 629 { 630 if (msg == NULL) { 631 return PLDM_ERROR_INVALID_DATA; 632 } 633 634 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) { 635 return PLDM_ERROR_INVALID_LENGTH; 636 } 637 638 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 639 PLDM_QUERY_DEVICE_IDENTIFIERS, msg); 640 } 641 642 LIBPLDM_ABI_STABLE 643 int decode_query_device_identifiers_resp(const struct pldm_msg *msg, 644 size_t payload_length, 645 uint8_t *completion_code, 646 uint32_t *device_identifiers_len, 647 uint8_t *descriptor_count, 648 uint8_t **descriptor_data) 649 { 650 if (msg == NULL || completion_code == NULL || 651 device_identifiers_len == NULL || descriptor_count == NULL || 652 descriptor_data == NULL) { 653 return PLDM_ERROR_INVALID_DATA; 654 } 655 656 *completion_code = msg->payload[0]; 657 if (PLDM_SUCCESS != *completion_code) { 658 return PLDM_SUCCESS; 659 } 660 661 if (payload_length < 662 sizeof(struct pldm_query_device_identifiers_resp)) { 663 return PLDM_ERROR_INVALID_LENGTH; 664 } 665 666 struct pldm_query_device_identifiers_resp *response = 667 (struct pldm_query_device_identifiers_resp *)msg->payload; 668 *device_identifiers_len = le32toh(response->device_identifiers_len); 669 670 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) { 671 return PLDM_ERROR_INVALID_LENGTH; 672 } 673 674 if (payload_length != 675 sizeof(struct pldm_query_device_identifiers_resp) + 676 *device_identifiers_len) { 677 return PLDM_ERROR_INVALID_LENGTH; 678 } 679 *descriptor_count = response->descriptor_count; 680 681 if (*descriptor_count == 0) { 682 return PLDM_ERROR_INVALID_DATA; 683 } 684 *descriptor_data = 685 (uint8_t *)(msg->payload + 686 sizeof(struct pldm_query_device_identifiers_resp)); 687 return PLDM_SUCCESS; 688 } 689 690 LIBPLDM_ABI_STABLE 691 int encode_get_firmware_parameters_req(uint8_t instance_id, 692 size_t payload_length, 693 struct pldm_msg *msg) 694 { 695 if (msg == NULL) { 696 return PLDM_ERROR_INVALID_DATA; 697 } 698 699 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) { 700 return PLDM_ERROR_INVALID_LENGTH; 701 } 702 703 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 704 PLDM_GET_FIRMWARE_PARAMETERS, msg); 705 } 706 707 LIBPLDM_ABI_STABLE 708 int decode_get_firmware_parameters_resp( 709 const struct pldm_msg *msg, size_t payload_length, 710 struct pldm_get_firmware_parameters_resp *resp_data, 711 struct variable_field *active_comp_image_set_ver_str, 712 struct variable_field *pending_comp_image_set_ver_str, 713 struct variable_field *comp_parameter_table) 714 { 715 if (msg == NULL || resp_data == NULL || 716 active_comp_image_set_ver_str == NULL || 717 pending_comp_image_set_ver_str == NULL || 718 comp_parameter_table == NULL || !payload_length) { 719 return PLDM_ERROR_INVALID_DATA; 720 } 721 722 resp_data->completion_code = msg->payload[0]; 723 if (PLDM_SUCCESS != resp_data->completion_code) { 724 return PLDM_SUCCESS; 725 } 726 727 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) { 728 return PLDM_ERROR_INVALID_LENGTH; 729 } 730 731 struct pldm_get_firmware_parameters_resp *response = 732 (struct pldm_get_firmware_parameters_resp *)msg->payload; 733 734 if (!is_string_type_valid( 735 response->active_comp_image_set_ver_str_type) || 736 (response->active_comp_image_set_ver_str_len == 0)) { 737 return PLDM_ERROR_INVALID_DATA; 738 } 739 740 if (response->pending_comp_image_set_ver_str_len == 0) { 741 if (response->pending_comp_image_set_ver_str_type != 742 PLDM_STR_TYPE_UNKNOWN) { 743 return PLDM_ERROR_INVALID_DATA; 744 } 745 } else { 746 if (!is_string_type_valid( 747 response->pending_comp_image_set_ver_str_type)) { 748 return PLDM_ERROR_INVALID_DATA; 749 } 750 } 751 752 size_t partial_response_length = 753 sizeof(struct pldm_get_firmware_parameters_resp) + 754 response->active_comp_image_set_ver_str_len + 755 response->pending_comp_image_set_ver_str_len; 756 757 if (payload_length < partial_response_length) { 758 return PLDM_ERROR_INVALID_LENGTH; 759 } 760 761 resp_data->capabilities_during_update.value = 762 le32toh(response->capabilities_during_update.value); 763 resp_data->comp_count = le16toh(response->comp_count); 764 resp_data->active_comp_image_set_ver_str_type = 765 response->active_comp_image_set_ver_str_type; 766 resp_data->active_comp_image_set_ver_str_len = 767 response->active_comp_image_set_ver_str_len; 768 resp_data->pending_comp_image_set_ver_str_type = 769 response->pending_comp_image_set_ver_str_type; 770 resp_data->pending_comp_image_set_ver_str_len = 771 response->pending_comp_image_set_ver_str_len; 772 773 active_comp_image_set_ver_str->ptr = 774 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp); 775 active_comp_image_set_ver_str->length = 776 resp_data->active_comp_image_set_ver_str_len; 777 778 if (resp_data->pending_comp_image_set_ver_str_len != 0) { 779 pending_comp_image_set_ver_str->ptr = 780 msg->payload + 781 sizeof(struct pldm_get_firmware_parameters_resp) + 782 resp_data->active_comp_image_set_ver_str_len; 783 pending_comp_image_set_ver_str->length = 784 resp_data->pending_comp_image_set_ver_str_len; 785 } else { 786 pending_comp_image_set_ver_str->ptr = NULL; 787 pending_comp_image_set_ver_str->length = 0; 788 } 789 790 if (payload_length > partial_response_length && resp_data->comp_count) { 791 comp_parameter_table->ptr = 792 msg->payload + 793 sizeof(struct pldm_get_firmware_parameters_resp) + 794 resp_data->active_comp_image_set_ver_str_len + 795 resp_data->pending_comp_image_set_ver_str_len; 796 comp_parameter_table->length = 797 payload_length - partial_response_length; 798 } else { 799 comp_parameter_table->ptr = NULL; 800 comp_parameter_table->length = 0; 801 } 802 803 return PLDM_SUCCESS; 804 } 805 806 LIBPLDM_ABI_STABLE 807 int decode_get_firmware_parameters_resp_comp_entry( 808 const uint8_t *data, size_t length, 809 struct pldm_component_parameter_entry *component_data, 810 struct variable_field *active_comp_ver_str, 811 struct variable_field *pending_comp_ver_str) 812 { 813 if (data == NULL || component_data == NULL || 814 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) { 815 return PLDM_ERROR_INVALID_DATA; 816 } 817 818 if (length < sizeof(struct pldm_component_parameter_entry)) { 819 return PLDM_ERROR_INVALID_LENGTH; 820 } 821 822 struct pldm_component_parameter_entry *entry = 823 (struct pldm_component_parameter_entry *)(data); 824 825 size_t entry_length = sizeof(struct pldm_component_parameter_entry) + 826 entry->active_comp_ver_str_len + 827 entry->pending_comp_ver_str_len; 828 829 if (length < entry_length) { 830 return PLDM_ERROR_INVALID_LENGTH; 831 } 832 833 component_data->comp_classification = 834 le16toh(entry->comp_classification); 835 component_data->comp_identifier = le16toh(entry->comp_identifier); 836 component_data->comp_classification_index = 837 entry->comp_classification_index; 838 component_data->active_comp_comparison_stamp = 839 le32toh(entry->active_comp_comparison_stamp); 840 component_data->active_comp_ver_str_type = 841 entry->active_comp_ver_str_type; 842 component_data->active_comp_ver_str_len = 843 entry->active_comp_ver_str_len; 844 memcpy(component_data->active_comp_release_date, 845 entry->active_comp_release_date, 846 sizeof(entry->active_comp_release_date)); 847 component_data->pending_comp_comparison_stamp = 848 le32toh(entry->pending_comp_comparison_stamp); 849 component_data->pending_comp_ver_str_type = 850 entry->pending_comp_ver_str_type; 851 component_data->pending_comp_ver_str_len = 852 entry->pending_comp_ver_str_len; 853 memcpy(component_data->pending_comp_release_date, 854 entry->pending_comp_release_date, 855 sizeof(entry->pending_comp_release_date)); 856 component_data->comp_activation_methods.value = 857 le16toh(entry->comp_activation_methods.value); 858 component_data->capabilities_during_update.value = 859 le32toh(entry->capabilities_during_update.value); 860 861 if (entry->active_comp_ver_str_len != 0) { 862 active_comp_ver_str->ptr = 863 data + sizeof(struct pldm_component_parameter_entry); 864 active_comp_ver_str->length = entry->active_comp_ver_str_len; 865 } else { 866 active_comp_ver_str->ptr = NULL; 867 active_comp_ver_str->length = 0; 868 } 869 870 if (entry->pending_comp_ver_str_len != 0) { 871 pending_comp_ver_str->ptr = 872 data + sizeof(struct pldm_component_parameter_entry) + 873 entry->active_comp_ver_str_len; 874 pending_comp_ver_str->length = entry->pending_comp_ver_str_len; 875 } else { 876 pending_comp_ver_str->ptr = NULL; 877 pending_comp_ver_str->length = 0; 878 } 879 return PLDM_SUCCESS; 880 } 881 882 LIBPLDM_ABI_TESTING 883 int encode_query_downstream_devices_req(uint8_t instance_id, 884 struct pldm_msg *msg) 885 { 886 if (msg == NULL) { 887 return PLDM_ERROR_INVALID_DATA; 888 } 889 890 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 891 PLDM_QUERY_DOWNSTREAM_DEVICES, msg); 892 } 893 894 LIBPLDM_ABI_TESTING 895 int decode_query_downstream_devices_resp( 896 const struct pldm_msg *msg, size_t payload_length, 897 struct pldm_query_downstream_devices_resp *resp_data) 898 { 899 struct pldm_msgbuf _buf; 900 struct pldm_msgbuf *buf = &_buf; 901 int rc; 902 903 if (msg == NULL || resp_data == NULL || !payload_length) { 904 return PLDM_ERROR_INVALID_DATA; 905 } 906 907 rc = pldm_msgbuf_init_cc(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 908 msg->payload, payload_length); 909 if (rc) { 910 return rc; 911 } 912 913 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 914 if (rc) { 915 return rc; 916 } 917 if (PLDM_SUCCESS != resp_data->completion_code) { 918 // Return the CC directly without decoding the rest of the payload 919 return PLDM_SUCCESS; 920 } 921 922 if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) { 923 return PLDM_ERROR_INVALID_LENGTH; 924 } 925 926 rc = pldm_msgbuf_extract(buf, 927 resp_data->downstream_device_update_supported); 928 if (rc) { 929 return rc; 930 } 931 932 if (!is_downstream_device_update_support_valid( 933 resp_data->downstream_device_update_supported)) { 934 return PLDM_ERROR_INVALID_DATA; 935 } 936 937 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices); 938 pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices); 939 pldm_msgbuf_extract(buf, resp_data->capabilities.value); 940 941 return pldm_msgbuf_destroy_consumed(buf); 942 } 943 944 LIBPLDM_ABI_TESTING 945 int encode_query_downstream_identifiers_req( 946 uint8_t instance_id, uint32_t data_transfer_handle, 947 enum transfer_op_flag transfer_operation_flag, struct pldm_msg *msg, 948 size_t payload_length) 949 { 950 struct pldm_msgbuf _buf; 951 struct pldm_msgbuf *buf = &_buf; 952 int rc; 953 954 if (msg == NULL) { 955 return PLDM_ERROR_INVALID_DATA; 956 } 957 958 if (!is_transfer_operation_flag_valid(transfer_operation_flag)) { 959 return PLDM_INVALID_TRANSFER_OPERATION_FLAG; 960 } 961 962 struct pldm_header_info header = { 0 }; 963 header.instance = instance_id; 964 header.msg_type = PLDM_REQUEST; 965 header.pldm_type = PLDM_FWUP; 966 header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS; 967 rc = pack_pldm_header(&header, &(msg->hdr)); 968 if (rc) { 969 return rc; 970 } 971 972 rc = pldm_msgbuf_init_cc(buf, 973 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES, 974 msg->payload, payload_length); 975 if (rc) { 976 return rc; 977 } 978 979 pldm_msgbuf_insert(buf, data_transfer_handle); 980 // Data correctness has been verified, cast it to 1-byte data directly. 981 pldm_msgbuf_insert(buf, (uint8_t)transfer_operation_flag); 982 983 return pldm_msgbuf_destroy(buf); 984 } 985 986 LIBPLDM_ABI_TESTING 987 int decode_query_downstream_identifiers_resp( 988 const struct pldm_msg *msg, size_t payload_length, 989 struct pldm_query_downstream_identifiers_resp *resp_data, 990 struct variable_field *downstream_devices) 991 { 992 struct pldm_msgbuf _buf; 993 struct pldm_msgbuf *buf = &_buf; 994 int rc = PLDM_ERROR; 995 996 if (msg == NULL || resp_data == NULL || downstream_devices == NULL || 997 !payload_length) { 998 return PLDM_ERROR_INVALID_DATA; 999 } 1000 1001 rc = pldm_msgbuf_init_cc(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 1002 msg->payload, payload_length); 1003 if (rc) { 1004 return rc; 1005 } 1006 1007 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 1008 if (rc) { 1009 return rc; 1010 } 1011 if (PLDM_SUCCESS != resp_data->completion_code) { 1012 return PLDM_SUCCESS; 1013 } 1014 1015 if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) { 1016 return PLDM_ERROR_INVALID_LENGTH; 1017 } 1018 1019 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle); 1020 pldm_msgbuf_extract(buf, resp_data->transfer_flag); 1021 1022 rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length); 1023 if (rc) { 1024 return rc; 1025 } 1026 1027 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices); 1028 rc = pldm_msgbuf_span_required(buf, 1029 resp_data->downstream_devices_length, 1030 (void **)&downstream_devices->ptr); 1031 if (rc) { 1032 return rc; 1033 } 1034 downstream_devices->length = resp_data->downstream_devices_length; 1035 1036 return pldm_msgbuf_destroy(buf); 1037 } 1038 1039 LIBPLDM_ABI_TESTING 1040 int encode_get_downstream_firmware_params_req( 1041 uint8_t instance_id, uint32_t data_transfer_handle, 1042 enum transfer_op_flag transfer_operation_flag, struct pldm_msg *msg, 1043 size_t payload_length) 1044 { 1045 struct pldm_msgbuf _buf; 1046 struct pldm_msgbuf *buf = &_buf; 1047 int rc; 1048 1049 if (msg == NULL) { 1050 return -EINVAL; 1051 } 1052 1053 rc = pldm_msgbuf_init_errno( 1054 buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_REQ_BYTES, 1055 msg->payload, payload_length); 1056 if (rc < 0) { 1057 return rc; 1058 } 1059 1060 if (!is_transfer_operation_flag_valid(transfer_operation_flag)) { 1061 return -EBADMSG; 1062 } 1063 1064 struct pldm_header_info header = { 0 }; 1065 header.instance = instance_id; 1066 header.msg_type = PLDM_REQUEST; 1067 header.pldm_type = PLDM_FWUP; 1068 header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS; 1069 rc = pack_pldm_header_errno(&header, &msg->hdr); 1070 if (rc < 0) { 1071 return rc; 1072 } 1073 1074 pldm_msgbuf_insert(buf, data_transfer_handle); 1075 // Data correctness has been verified, cast it to 1-byte data directly. 1076 pldm_msgbuf_insert(buf, (uint8_t)transfer_operation_flag); 1077 1078 return pldm_msgbuf_destroy(buf); 1079 } 1080 1081 LIBPLDM_ABI_TESTING 1082 int decode_get_downstream_firmware_params_resp( 1083 const struct pldm_msg *msg, size_t payload_length, 1084 struct pldm_get_downstream_firmware_params_resp *resp_data, 1085 struct variable_field *downstream_device_param_table) 1086 { 1087 struct pldm_msgbuf _buf; 1088 struct pldm_msgbuf *buf = &_buf; 1089 int rc; 1090 1091 if (msg == NULL || resp_data == NULL || 1092 downstream_device_param_table == NULL) { 1093 return -EINVAL; 1094 } 1095 1096 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 1097 msg->payload, payload_length); 1098 if (rc < 0) { 1099 return rc; 1100 } 1101 1102 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 1103 if (rc < 0) { 1104 return rc; 1105 } 1106 if (PLDM_SUCCESS != resp_data->completion_code) { 1107 return 0; 1108 } 1109 1110 if (payload_length < PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_RESP_MIN_LEN) { 1111 return -EBADMSG; 1112 } 1113 1114 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle); 1115 pldm_msgbuf_extract(buf, resp_data->transfer_flag); 1116 pldm_msgbuf_extract(buf, 1117 resp_data->fdp_capabilities_during_update.value); 1118 pldm_msgbuf_extract(buf, resp_data->downstream_device_count); 1119 1120 return pldm_msgbuf_span_remaining( 1121 buf, (void **)&downstream_device_param_table->ptr, 1122 &downstream_device_param_table->length); 1123 } 1124 1125 LIBPLDM_ABI_TESTING 1126 int decode_downstream_device_parameter_table_entry( 1127 struct variable_field *data, 1128 struct pldm_downstream_device_parameter_entry *entry, 1129 struct variable_field *versions) 1130 { 1131 struct pldm_msgbuf _buf; 1132 struct pldm_msgbuf *buf = &_buf; 1133 void *cursor = NULL; 1134 size_t remaining; 1135 int rc; 1136 1137 if (data == NULL || entry == NULL || versions == NULL) { 1138 return -EINVAL; 1139 } 1140 1141 rc = pldm_msgbuf_init_errno( 1142 buf, PLDM_DOWNSTREAM_DEVICE_PARAMETER_ENTRY_MIN_LEN, data->ptr, 1143 data->length); 1144 if (rc < 0) { 1145 return rc; 1146 } 1147 1148 pldm_msgbuf_extract(buf, entry->downstream_device_index); 1149 pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp); 1150 pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type); 1151 rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len); 1152 if (rc < 0) { 1153 return rc; 1154 } 1155 pldm_msgbuf_extract_array(buf, entry->active_comp_release_date, 1156 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN); 1157 // Fill the last byte with NULL character 1158 entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] = 1159 '\0'; 1160 1161 pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp); 1162 pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type); 1163 rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len); 1164 if (rc < 0) { 1165 return rc; 1166 } 1167 pldm_msgbuf_extract_array(buf, entry->pending_comp_release_date, 1168 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN); 1169 // Fill the last byte with NULL character 1170 entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] = 1171 '\0'; 1172 1173 pldm_msgbuf_extract(buf, entry->comp_activation_methods.value); 1174 pldm_msgbuf_extract(buf, entry->capabilities_during_update.value); 1175 const size_t versions_len = entry->active_comp_ver_str_len + 1176 entry->pending_comp_ver_str_len; 1177 rc = pldm_msgbuf_span_required(buf, versions_len, 1178 (void **)&versions->ptr); 1179 if (rc < 0) { 1180 return rc; 1181 } 1182 versions->length = versions_len; 1183 1184 rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining); 1185 if (rc < 0) { 1186 return rc; 1187 } 1188 1189 data->ptr = cursor; 1190 data->length = remaining; 1191 1192 return 0; 1193 } 1194 1195 LIBPLDM_ABI_TESTING 1196 int decode_downstream_device_parameter_table_entry_versions( 1197 const struct variable_field *versions, 1198 struct pldm_downstream_device_parameter_entry *entry, char *active, 1199 char *pending) 1200 { 1201 struct pldm_msgbuf _buf; 1202 struct pldm_msgbuf *buf = &_buf; 1203 int rc; 1204 1205 if (versions == NULL || versions->ptr == NULL || !versions->length || 1206 entry == NULL || active == NULL || pending == NULL) { 1207 return -EINVAL; 1208 } 1209 1210 /* This API should be called after decode_downstream_device_parameter_table_entry 1211 * has successfully decoded the entry, assume the entry data is valid here. 1212 */ 1213 const size_t versions_len = entry->active_comp_ver_str_len + 1214 entry->pending_comp_ver_str_len; 1215 rc = pldm_msgbuf_init_errno(buf, versions_len, versions->ptr, 1216 versions->length); 1217 if (rc < 0) { 1218 return rc; 1219 } 1220 1221 pldm_msgbuf_extract_array(buf, active, entry->active_comp_ver_str_len); 1222 active[entry->active_comp_ver_str_len] = '\0'; 1223 pldm_msgbuf_extract_array(buf, pending, 1224 entry->pending_comp_ver_str_len); 1225 pending[entry->pending_comp_ver_str_len] = '\0'; 1226 1227 entry->active_comp_ver_str = active; 1228 entry->pending_comp_ver_str = pending; 1229 1230 return pldm_msgbuf_destroy_consumed(buf); 1231 } 1232 1233 LIBPLDM_ABI_STABLE 1234 int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size, 1235 uint16_t num_of_comp, 1236 uint8_t max_outstanding_transfer_req, 1237 uint16_t pkg_data_len, 1238 uint8_t comp_image_set_ver_str_type, 1239 uint8_t comp_image_set_ver_str_len, 1240 const struct variable_field *comp_img_set_ver_str, 1241 struct pldm_msg *msg, size_t payload_length) 1242 { 1243 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL || 1244 msg == NULL) { 1245 return PLDM_ERROR_INVALID_DATA; 1246 } 1247 1248 if (payload_length != sizeof(struct pldm_request_update_req) + 1249 comp_img_set_ver_str->length) { 1250 return PLDM_ERROR_INVALID_LENGTH; 1251 } 1252 1253 if ((comp_image_set_ver_str_len == 0) || 1254 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) { 1255 return PLDM_ERROR_INVALID_DATA; 1256 } 1257 1258 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) || 1259 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) { 1260 return PLDM_ERROR_INVALID_DATA; 1261 } 1262 1263 if (!is_string_type_valid(comp_image_set_ver_str_type)) { 1264 return PLDM_ERROR_INVALID_DATA; 1265 } 1266 1267 struct pldm_header_info header = { 0 }; 1268 header.instance = instance_id; 1269 header.msg_type = PLDM_REQUEST; 1270 header.pldm_type = PLDM_FWUP; 1271 header.command = PLDM_REQUEST_UPDATE; 1272 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1273 if (rc) { 1274 return rc; 1275 } 1276 1277 struct pldm_request_update_req *request = 1278 (struct pldm_request_update_req *)msg->payload; 1279 1280 request->max_transfer_size = htole32(max_transfer_size); 1281 request->num_of_comp = htole16(num_of_comp); 1282 request->max_outstanding_transfer_req = max_outstanding_transfer_req; 1283 request->pkg_data_len = htole16(pkg_data_len); 1284 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type; 1285 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len; 1286 1287 memcpy(msg->payload + sizeof(struct pldm_request_update_req), 1288 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length); 1289 1290 return PLDM_SUCCESS; 1291 } 1292 1293 LIBPLDM_ABI_STABLE 1294 int decode_request_update_resp(const struct pldm_msg *msg, 1295 size_t payload_length, uint8_t *completion_code, 1296 uint16_t *fd_meta_data_len, 1297 uint8_t *fd_will_send_pkg_data) 1298 { 1299 if (msg == NULL || completion_code == NULL || 1300 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL || 1301 !payload_length) { 1302 return PLDM_ERROR_INVALID_DATA; 1303 } 1304 1305 *completion_code = msg->payload[0]; 1306 if (*completion_code != PLDM_SUCCESS) { 1307 return PLDM_SUCCESS; 1308 } 1309 1310 if (payload_length != sizeof(struct pldm_request_update_resp)) { 1311 return PLDM_ERROR_INVALID_LENGTH; 1312 } 1313 1314 struct pldm_request_update_resp *response = 1315 (struct pldm_request_update_resp *)msg->payload; 1316 1317 *fd_meta_data_len = le16toh(response->fd_meta_data_len); 1318 *fd_will_send_pkg_data = response->fd_will_send_pkg_data; 1319 1320 return PLDM_SUCCESS; 1321 } 1322 1323 LIBPLDM_ABI_STABLE 1324 int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag, 1325 uint16_t comp_classification, 1326 uint16_t comp_identifier, 1327 uint8_t comp_classification_index, 1328 uint32_t comp_comparison_stamp, 1329 uint8_t comp_ver_str_type, 1330 uint8_t comp_ver_str_len, 1331 const struct variable_field *comp_ver_str, 1332 struct pldm_msg *msg, size_t payload_length) 1333 { 1334 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) { 1335 return PLDM_ERROR_INVALID_DATA; 1336 } 1337 1338 if (payload_length != sizeof(struct pldm_pass_component_table_req) + 1339 comp_ver_str->length) { 1340 return PLDM_ERROR_INVALID_LENGTH; 1341 } 1342 1343 if ((comp_ver_str_len == 0) || 1344 (comp_ver_str_len != comp_ver_str->length)) { 1345 return PLDM_ERROR_INVALID_DATA; 1346 } 1347 1348 if (!is_transfer_flag_valid(transfer_flag)) { 1349 return PLDM_INVALID_TRANSFER_OPERATION_FLAG; 1350 } 1351 1352 if (!is_string_type_valid(comp_ver_str_type)) { 1353 return PLDM_ERROR_INVALID_DATA; 1354 } 1355 1356 struct pldm_header_info header = { 0 }; 1357 header.instance = instance_id; 1358 header.msg_type = PLDM_REQUEST; 1359 header.pldm_type = PLDM_FWUP; 1360 header.command = PLDM_PASS_COMPONENT_TABLE; 1361 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1362 if (rc) { 1363 return rc; 1364 } 1365 1366 struct pldm_pass_component_table_req *request = 1367 (struct pldm_pass_component_table_req *)msg->payload; 1368 1369 request->transfer_flag = transfer_flag; 1370 request->comp_classification = htole16(comp_classification); 1371 request->comp_identifier = htole16(comp_identifier); 1372 request->comp_classification_index = comp_classification_index; 1373 request->comp_comparison_stamp = htole32(comp_comparison_stamp); 1374 request->comp_ver_str_type = comp_ver_str_type; 1375 request->comp_ver_str_len = comp_ver_str_len; 1376 1377 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req), 1378 comp_ver_str->ptr, comp_ver_str->length); 1379 1380 return PLDM_SUCCESS; 1381 } 1382 1383 LIBPLDM_ABI_STABLE 1384 int decode_pass_component_table_resp(const struct pldm_msg *msg, 1385 const size_t payload_length, 1386 uint8_t *completion_code, 1387 uint8_t *comp_resp, 1388 uint8_t *comp_resp_code) 1389 { 1390 if (msg == NULL || completion_code == NULL || comp_resp == NULL || 1391 comp_resp_code == NULL || !payload_length) { 1392 return PLDM_ERROR_INVALID_DATA; 1393 } 1394 1395 *completion_code = msg->payload[0]; 1396 if (*completion_code != PLDM_SUCCESS) { 1397 return PLDM_SUCCESS; 1398 } 1399 1400 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) { 1401 return PLDM_ERROR_INVALID_LENGTH; 1402 } 1403 1404 struct pldm_pass_component_table_resp *response = 1405 (struct pldm_pass_component_table_resp *)msg->payload; 1406 1407 if (!is_comp_resp_valid(response->comp_resp)) { 1408 return PLDM_ERROR_INVALID_DATA; 1409 } 1410 1411 if (!is_comp_resp_code_valid(response->comp_resp_code)) { 1412 return PLDM_ERROR_INVALID_DATA; 1413 } 1414 1415 *comp_resp = response->comp_resp; 1416 *comp_resp_code = response->comp_resp_code; 1417 1418 return PLDM_SUCCESS; 1419 } 1420 1421 LIBPLDM_ABI_STABLE 1422 int encode_update_component_req( 1423 uint8_t instance_id, uint16_t comp_classification, 1424 uint16_t comp_identifier, uint8_t comp_classification_index, 1425 uint32_t comp_comparison_stamp, uint32_t comp_image_size, 1426 bitfield32_t update_option_flags, uint8_t comp_ver_str_type, 1427 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str, 1428 struct pldm_msg *msg, size_t payload_length) 1429 { 1430 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) { 1431 return PLDM_ERROR_INVALID_DATA; 1432 } 1433 1434 if (payload_length != 1435 sizeof(struct pldm_update_component_req) + comp_ver_str->length) { 1436 return PLDM_ERROR_INVALID_LENGTH; 1437 } 1438 1439 if (!comp_image_size) { 1440 return PLDM_ERROR_INVALID_DATA; 1441 } 1442 1443 if ((comp_ver_str_len == 0) || 1444 (comp_ver_str_len != comp_ver_str->length)) { 1445 return PLDM_ERROR_INVALID_DATA; 1446 } 1447 1448 if (!is_string_type_valid(comp_ver_str_type)) { 1449 return PLDM_ERROR_INVALID_DATA; 1450 } 1451 1452 struct pldm_header_info header = { 0 }; 1453 header.instance = instance_id; 1454 header.msg_type = PLDM_REQUEST; 1455 header.pldm_type = PLDM_FWUP; 1456 header.command = PLDM_UPDATE_COMPONENT; 1457 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1458 if (rc) { 1459 return rc; 1460 } 1461 1462 struct pldm_update_component_req *request = 1463 (struct pldm_update_component_req *)msg->payload; 1464 1465 request->comp_classification = htole16(comp_classification); 1466 request->comp_identifier = htole16(comp_identifier); 1467 request->comp_classification_index = comp_classification_index; 1468 request->comp_comparison_stamp = htole32(comp_comparison_stamp); 1469 request->comp_image_size = htole32(comp_image_size); 1470 request->update_option_flags.value = htole32(update_option_flags.value); 1471 request->comp_ver_str_type = comp_ver_str_type; 1472 request->comp_ver_str_len = comp_ver_str_len; 1473 1474 memcpy(msg->payload + sizeof(struct pldm_update_component_req), 1475 comp_ver_str->ptr, comp_ver_str->length); 1476 1477 return PLDM_SUCCESS; 1478 } 1479 1480 LIBPLDM_ABI_STABLE 1481 int decode_update_component_resp(const struct pldm_msg *msg, 1482 size_t payload_length, 1483 uint8_t *completion_code, 1484 uint8_t *comp_compatibility_resp, 1485 uint8_t *comp_compatibility_resp_code, 1486 bitfield32_t *update_option_flags_enabled, 1487 uint16_t *time_before_req_fw_data) 1488 { 1489 if (msg == NULL || completion_code == NULL || 1490 comp_compatibility_resp == NULL || 1491 comp_compatibility_resp_code == NULL || 1492 update_option_flags_enabled == NULL || 1493 time_before_req_fw_data == NULL || !payload_length) { 1494 return PLDM_ERROR_INVALID_DATA; 1495 } 1496 1497 *completion_code = msg->payload[0]; 1498 if (*completion_code != PLDM_SUCCESS) { 1499 return PLDM_SUCCESS; 1500 } 1501 1502 if (payload_length != sizeof(struct pldm_update_component_resp)) { 1503 return PLDM_ERROR_INVALID_LENGTH; 1504 } 1505 1506 struct pldm_update_component_resp *response = 1507 (struct pldm_update_component_resp *)msg->payload; 1508 1509 if (!is_comp_compatibility_resp_valid( 1510 response->comp_compatibility_resp)) { 1511 return PLDM_ERROR_INVALID_DATA; 1512 } 1513 1514 if (!is_comp_compatibility_resp_code_valid( 1515 response->comp_compatibility_resp_code)) { 1516 return PLDM_ERROR_INVALID_DATA; 1517 } 1518 1519 *comp_compatibility_resp = response->comp_compatibility_resp; 1520 *comp_compatibility_resp_code = response->comp_compatibility_resp_code; 1521 update_option_flags_enabled->value = 1522 le32toh(response->update_option_flags_enabled.value); 1523 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data); 1524 1525 return PLDM_SUCCESS; 1526 } 1527 1528 LIBPLDM_ABI_STABLE 1529 int decode_request_firmware_data_req(const struct pldm_msg *msg, 1530 size_t payload_length, uint32_t *offset, 1531 uint32_t *length) 1532 { 1533 if (msg == NULL || offset == NULL || length == NULL) { 1534 return PLDM_ERROR_INVALID_DATA; 1535 } 1536 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) { 1537 return PLDM_ERROR_INVALID_LENGTH; 1538 } 1539 struct pldm_request_firmware_data_req *request = 1540 (struct pldm_request_firmware_data_req *)msg->payload; 1541 *offset = le32toh(request->offset); 1542 *length = le32toh(request->length); 1543 1544 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) { 1545 return PLDM_FWUP_INVALID_TRANSFER_LENGTH; 1546 } 1547 1548 return PLDM_SUCCESS; 1549 } 1550 1551 LIBPLDM_ABI_STABLE 1552 int encode_request_firmware_data_resp(uint8_t instance_id, 1553 uint8_t completion_code, 1554 struct pldm_msg *msg, 1555 size_t payload_length) 1556 { 1557 if (msg == NULL || !payload_length) { 1558 return PLDM_ERROR_INVALID_DATA; 1559 } 1560 1561 struct pldm_header_info header = { 0 }; 1562 header.instance = instance_id; 1563 header.msg_type = PLDM_RESPONSE; 1564 header.pldm_type = PLDM_FWUP; 1565 header.command = PLDM_REQUEST_FIRMWARE_DATA; 1566 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1567 if (rc) { 1568 return rc; 1569 } 1570 1571 msg->payload[0] = completion_code; 1572 1573 return PLDM_SUCCESS; 1574 } 1575 1576 LIBPLDM_ABI_STABLE 1577 int decode_transfer_complete_req(const struct pldm_msg *msg, 1578 size_t payload_length, 1579 uint8_t *transfer_result) 1580 { 1581 if (msg == NULL || transfer_result == NULL) { 1582 return PLDM_ERROR_INVALID_DATA; 1583 } 1584 1585 if (payload_length != sizeof(*transfer_result)) { 1586 return PLDM_ERROR_INVALID_LENGTH; 1587 } 1588 1589 *transfer_result = msg->payload[0]; 1590 return PLDM_SUCCESS; 1591 } 1592 1593 LIBPLDM_ABI_STABLE 1594 int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code, 1595 struct pldm_msg *msg, size_t payload_length) 1596 { 1597 if (msg == NULL) { 1598 return PLDM_ERROR_INVALID_DATA; 1599 } 1600 1601 if (payload_length != sizeof(completion_code)) { 1602 return PLDM_ERROR_INVALID_LENGTH; 1603 } 1604 1605 struct pldm_header_info header = { 0 }; 1606 header.instance = instance_id; 1607 header.msg_type = PLDM_RESPONSE; 1608 header.pldm_type = PLDM_FWUP; 1609 header.command = PLDM_TRANSFER_COMPLETE; 1610 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1611 if (rc) { 1612 return rc; 1613 } 1614 1615 msg->payload[0] = completion_code; 1616 1617 return PLDM_SUCCESS; 1618 } 1619 1620 LIBPLDM_ABI_STABLE 1621 int decode_verify_complete_req(const struct pldm_msg *msg, 1622 size_t payload_length, uint8_t *verify_result) 1623 { 1624 if (msg == NULL || verify_result == NULL) { 1625 return PLDM_ERROR_INVALID_DATA; 1626 } 1627 1628 if (payload_length != sizeof(*verify_result)) { 1629 return PLDM_ERROR_INVALID_LENGTH; 1630 } 1631 1632 *verify_result = msg->payload[0]; 1633 return PLDM_SUCCESS; 1634 } 1635 1636 LIBPLDM_ABI_STABLE 1637 int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code, 1638 struct pldm_msg *msg, size_t payload_length) 1639 { 1640 if (msg == NULL) { 1641 return PLDM_ERROR_INVALID_DATA; 1642 } 1643 1644 if (payload_length != sizeof(completion_code)) { 1645 return PLDM_ERROR_INVALID_LENGTH; 1646 } 1647 1648 struct pldm_header_info header = { 0 }; 1649 header.instance = instance_id; 1650 header.msg_type = PLDM_RESPONSE; 1651 header.pldm_type = PLDM_FWUP; 1652 header.command = PLDM_VERIFY_COMPLETE; 1653 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1654 if (rc) { 1655 return rc; 1656 } 1657 1658 msg->payload[0] = completion_code; 1659 1660 return PLDM_SUCCESS; 1661 } 1662 1663 LIBPLDM_ABI_STABLE 1664 int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length, 1665 uint8_t *apply_result, 1666 bitfield16_t *comp_activation_methods_modification) 1667 { 1668 if (msg == NULL || apply_result == NULL || 1669 comp_activation_methods_modification == NULL) { 1670 return PLDM_ERROR_INVALID_DATA; 1671 } 1672 1673 if (payload_length != sizeof(struct pldm_apply_complete_req)) { 1674 return PLDM_ERROR_INVALID_LENGTH; 1675 } 1676 1677 struct pldm_apply_complete_req *request = 1678 (struct pldm_apply_complete_req *)msg->payload; 1679 1680 *apply_result = request->apply_result; 1681 comp_activation_methods_modification->value = 1682 le16toh(request->comp_activation_methods_modification.value); 1683 1684 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) && 1685 comp_activation_methods_modification->value) { 1686 return PLDM_ERROR_INVALID_DATA; 1687 } 1688 1689 return PLDM_SUCCESS; 1690 } 1691 1692 LIBPLDM_ABI_STABLE 1693 int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code, 1694 struct pldm_msg *msg, size_t payload_length) 1695 { 1696 if (msg == NULL) { 1697 return PLDM_ERROR_INVALID_DATA; 1698 } 1699 1700 if (payload_length != sizeof(completion_code)) { 1701 return PLDM_ERROR_INVALID_LENGTH; 1702 } 1703 1704 struct pldm_header_info header = { 0 }; 1705 header.instance = instance_id; 1706 header.msg_type = PLDM_RESPONSE; 1707 header.pldm_type = PLDM_FWUP; 1708 header.command = PLDM_APPLY_COMPLETE; 1709 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1710 if (rc) { 1711 return rc; 1712 } 1713 1714 msg->payload[0] = completion_code; 1715 1716 return PLDM_SUCCESS; 1717 } 1718 1719 LIBPLDM_ABI_STABLE 1720 int encode_activate_firmware_req(uint8_t instance_id, 1721 bool8_t self_contained_activation_req, 1722 struct pldm_msg *msg, size_t payload_length) 1723 { 1724 if (msg == NULL) { 1725 return PLDM_ERROR_INVALID_DATA; 1726 } 1727 1728 if (payload_length != sizeof(struct pldm_activate_firmware_req)) { 1729 return PLDM_ERROR_INVALID_LENGTH; 1730 } 1731 1732 if (!is_self_contained_activation_req_valid( 1733 self_contained_activation_req)) { 1734 return PLDM_ERROR_INVALID_DATA; 1735 } 1736 1737 struct pldm_header_info header = { 0 }; 1738 header.instance = instance_id; 1739 header.msg_type = PLDM_REQUEST; 1740 header.pldm_type = PLDM_FWUP; 1741 header.command = PLDM_ACTIVATE_FIRMWARE; 1742 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1743 if (rc) { 1744 return rc; 1745 } 1746 1747 struct pldm_activate_firmware_req *request = 1748 (struct pldm_activate_firmware_req *)msg->payload; 1749 1750 request->self_contained_activation_req = self_contained_activation_req; 1751 1752 return PLDM_SUCCESS; 1753 } 1754 1755 LIBPLDM_ABI_STABLE 1756 int decode_activate_firmware_resp(const struct pldm_msg *msg, 1757 size_t payload_length, 1758 uint8_t *completion_code, 1759 uint16_t *estimated_time_activation) 1760 { 1761 if (msg == NULL || completion_code == NULL || 1762 estimated_time_activation == NULL || !payload_length) { 1763 return PLDM_ERROR_INVALID_DATA; 1764 } 1765 1766 *completion_code = msg->payload[0]; 1767 if (*completion_code != PLDM_SUCCESS) { 1768 return PLDM_SUCCESS; 1769 } 1770 1771 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) { 1772 return PLDM_ERROR_INVALID_LENGTH; 1773 } 1774 1775 struct pldm_activate_firmware_resp *response = 1776 (struct pldm_activate_firmware_resp *)msg->payload; 1777 1778 *estimated_time_activation = 1779 le16toh(response->estimated_time_activation); 1780 1781 return PLDM_SUCCESS; 1782 } 1783 1784 LIBPLDM_ABI_STABLE 1785 int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg, 1786 size_t payload_length) 1787 { 1788 if (msg == NULL) { 1789 return PLDM_ERROR_INVALID_DATA; 1790 } 1791 1792 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) { 1793 return PLDM_ERROR_INVALID_LENGTH; 1794 } 1795 1796 struct pldm_header_info header = { 0 }; 1797 header.instance = instance_id; 1798 header.msg_type = PLDM_REQUEST; 1799 header.pldm_type = PLDM_FWUP; 1800 header.command = PLDM_GET_STATUS; 1801 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1802 if (rc) { 1803 return rc; 1804 } 1805 1806 return PLDM_SUCCESS; 1807 } 1808 1809 LIBPLDM_ABI_STABLE 1810 int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length, 1811 uint8_t *completion_code, uint8_t *current_state, 1812 uint8_t *previous_state, uint8_t *aux_state, 1813 uint8_t *aux_state_status, uint8_t *progress_percent, 1814 uint8_t *reason_code, 1815 bitfield32_t *update_option_flags_enabled) 1816 { 1817 if (msg == NULL || completion_code == NULL || current_state == NULL || 1818 previous_state == NULL || aux_state == NULL || 1819 aux_state_status == NULL || progress_percent == NULL || 1820 reason_code == NULL || update_option_flags_enabled == NULL || 1821 !payload_length) { 1822 return PLDM_ERROR_INVALID_DATA; 1823 } 1824 1825 *completion_code = msg->payload[0]; 1826 if (*completion_code != PLDM_SUCCESS) { 1827 return PLDM_SUCCESS; 1828 } 1829 1830 if (payload_length != sizeof(struct pldm_get_status_resp)) { 1831 return PLDM_ERROR_INVALID_LENGTH; 1832 } 1833 struct pldm_get_status_resp *response = 1834 (struct pldm_get_status_resp *)msg->payload; 1835 1836 if (!is_state_valid(response->current_state)) { 1837 return PLDM_ERROR_INVALID_DATA; 1838 } 1839 if (!is_state_valid(response->previous_state)) { 1840 return PLDM_ERROR_INVALID_DATA; 1841 } 1842 if (!is_aux_state_valid(response->aux_state)) { 1843 return PLDM_ERROR_INVALID_DATA; 1844 } 1845 if (!is_aux_state_status_valid(response->aux_state_status)) { 1846 return PLDM_ERROR_INVALID_DATA; 1847 } 1848 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) { 1849 return PLDM_ERROR_INVALID_DATA; 1850 } 1851 if (!is_reason_code_valid(response->reason_code)) { 1852 return PLDM_ERROR_INVALID_DATA; 1853 } 1854 1855 if ((response->current_state == PLDM_FD_STATE_IDLE) || 1856 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) || 1857 (response->current_state == PLDM_FD_STATE_READY_XFER)) { 1858 if (response->aux_state != 1859 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) { 1860 return PLDM_ERROR_INVALID_DATA; 1861 } 1862 } 1863 1864 *current_state = response->current_state; 1865 *previous_state = response->previous_state; 1866 *aux_state = response->aux_state; 1867 *aux_state_status = response->aux_state_status; 1868 *progress_percent = response->progress_percent; 1869 *reason_code = response->reason_code; 1870 update_option_flags_enabled->value = 1871 le32toh(response->update_option_flags_enabled.value); 1872 1873 return PLDM_SUCCESS; 1874 } 1875 1876 LIBPLDM_ABI_STABLE 1877 int encode_cancel_update_component_req(uint8_t instance_id, 1878 struct pldm_msg *msg, 1879 size_t payload_length) 1880 { 1881 if (msg == NULL) { 1882 return PLDM_ERROR_INVALID_DATA; 1883 } 1884 1885 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) { 1886 return PLDM_ERROR_INVALID_LENGTH; 1887 } 1888 1889 struct pldm_header_info header = { 0 }; 1890 header.instance = instance_id; 1891 header.msg_type = PLDM_REQUEST; 1892 header.pldm_type = PLDM_FWUP; 1893 header.command = PLDM_CANCEL_UPDATE_COMPONENT; 1894 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1895 if (rc) { 1896 return rc; 1897 } 1898 1899 return PLDM_SUCCESS; 1900 } 1901 1902 LIBPLDM_ABI_STABLE 1903 int decode_cancel_update_component_resp(const struct pldm_msg *msg, 1904 size_t payload_length, 1905 uint8_t *completion_code) 1906 { 1907 if (msg == NULL || completion_code == NULL) { 1908 return PLDM_ERROR_INVALID_DATA; 1909 } 1910 1911 if (payload_length != sizeof(*completion_code)) { 1912 return PLDM_ERROR_INVALID_LENGTH; 1913 } 1914 1915 *completion_code = msg->payload[0]; 1916 return PLDM_SUCCESS; 1917 } 1918 1919 LIBPLDM_ABI_STABLE 1920 int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg, 1921 size_t payload_length) 1922 { 1923 if (msg == NULL) { 1924 return PLDM_ERROR_INVALID_DATA; 1925 } 1926 1927 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) { 1928 return PLDM_ERROR_INVALID_LENGTH; 1929 } 1930 1931 struct pldm_header_info header = { 0 }; 1932 header.instance = instance_id; 1933 header.msg_type = PLDM_REQUEST; 1934 header.pldm_type = PLDM_FWUP; 1935 header.command = PLDM_CANCEL_UPDATE; 1936 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1937 if (rc) { 1938 return rc; 1939 } 1940 1941 return PLDM_SUCCESS; 1942 } 1943 1944 LIBPLDM_ABI_STABLE 1945 int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length, 1946 uint8_t *completion_code, 1947 bool8_t *non_functioning_component_indication, 1948 bitfield64_t *non_functioning_component_bitmap) 1949 { 1950 if (msg == NULL || completion_code == NULL || 1951 non_functioning_component_indication == NULL || 1952 non_functioning_component_bitmap == NULL || !payload_length) { 1953 return PLDM_ERROR_INVALID_DATA; 1954 } 1955 1956 *completion_code = msg->payload[0]; 1957 if (*completion_code != PLDM_SUCCESS) { 1958 return PLDM_SUCCESS; 1959 } 1960 1961 if (payload_length != sizeof(struct pldm_cancel_update_resp)) { 1962 return PLDM_ERROR_INVALID_LENGTH; 1963 } 1964 struct pldm_cancel_update_resp *response = 1965 (struct pldm_cancel_update_resp *)msg->payload; 1966 1967 if (!is_non_functioning_component_indication_valid( 1968 response->non_functioning_component_indication)) { 1969 return PLDM_ERROR_INVALID_DATA; 1970 } 1971 1972 *non_functioning_component_indication = 1973 response->non_functioning_component_indication; 1974 1975 if (*non_functioning_component_indication) { 1976 non_functioning_component_bitmap->value = 1977 le64toh(response->non_functioning_component_bitmap); 1978 } 1979 1980 return PLDM_SUCCESS; 1981 } 1982