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 rc = pldm_msgbuf_extract_array(buf, 1156 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 1157 entry->active_comp_release_date, 1158 sizeof(entry->active_comp_release_date)); 1159 if (rc < 0) { 1160 return rc; 1161 } 1162 1163 // Fill the last byte with NULL character 1164 entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] = 1165 '\0'; 1166 1167 pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp); 1168 pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type); 1169 rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len); 1170 if (rc < 0) { 1171 return rc; 1172 } 1173 1174 rc = pldm_msgbuf_extract_array( 1175 buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 1176 entry->pending_comp_release_date, 1177 sizeof(entry->pending_comp_release_date)); 1178 if (rc < 0) { 1179 return rc; 1180 } 1181 1182 // Fill the last byte with NULL character 1183 entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] = 1184 '\0'; 1185 1186 pldm_msgbuf_extract(buf, entry->comp_activation_methods.value); 1187 pldm_msgbuf_extract(buf, entry->capabilities_during_update.value); 1188 const size_t versions_len = entry->active_comp_ver_str_len + 1189 entry->pending_comp_ver_str_len; 1190 rc = pldm_msgbuf_span_required(buf, versions_len, 1191 (void **)&versions->ptr); 1192 if (rc < 0) { 1193 return rc; 1194 } 1195 versions->length = versions_len; 1196 1197 rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining); 1198 if (rc < 0) { 1199 return rc; 1200 } 1201 1202 data->ptr = cursor; 1203 data->length = remaining; 1204 1205 return 0; 1206 } 1207 1208 LIBPLDM_ABI_TESTING 1209 int decode_downstream_device_parameter_table_entry_versions( 1210 const struct variable_field *versions, 1211 struct pldm_downstream_device_parameter_entry *entry, char *active, 1212 char *pending) 1213 { 1214 struct pldm_msgbuf _buf; 1215 struct pldm_msgbuf *buf = &_buf; 1216 int rc; 1217 1218 if (versions == NULL || versions->ptr == NULL || !versions->length || 1219 entry == NULL || active == NULL || pending == NULL) { 1220 return -EINVAL; 1221 } 1222 1223 /* This API should be called after decode_downstream_device_parameter_table_entry 1224 * has successfully decoded the entry, assume the entry data is valid here. 1225 */ 1226 const size_t versions_len = entry->active_comp_ver_str_len + 1227 entry->pending_comp_ver_str_len; 1228 rc = pldm_msgbuf_init_errno(buf, versions_len, versions->ptr, 1229 versions->length); 1230 if (rc < 0) { 1231 return rc; 1232 } 1233 1234 rc = pldm_msgbuf_extract_array(buf, entry->active_comp_ver_str_len, 1235 active, entry->active_comp_ver_str_len); 1236 if (rc < 0) { 1237 return rc; 1238 } 1239 1240 active[entry->active_comp_ver_str_len] = '\0'; 1241 rc = pldm_msgbuf_extract_array(buf, entry->pending_comp_ver_str_len, 1242 pending, 1243 entry->pending_comp_ver_str_len); 1244 if (rc < 0) { 1245 return rc; 1246 } 1247 1248 pending[entry->pending_comp_ver_str_len] = '\0'; 1249 1250 entry->active_comp_ver_str = active; 1251 entry->pending_comp_ver_str = pending; 1252 1253 return pldm_msgbuf_destroy_consumed(buf); 1254 } 1255 1256 LIBPLDM_ABI_STABLE 1257 int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size, 1258 uint16_t num_of_comp, 1259 uint8_t max_outstanding_transfer_req, 1260 uint16_t pkg_data_len, 1261 uint8_t comp_image_set_ver_str_type, 1262 uint8_t comp_image_set_ver_str_len, 1263 const struct variable_field *comp_img_set_ver_str, 1264 struct pldm_msg *msg, size_t payload_length) 1265 { 1266 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL || 1267 msg == NULL) { 1268 return PLDM_ERROR_INVALID_DATA; 1269 } 1270 1271 if (payload_length != sizeof(struct pldm_request_update_req) + 1272 comp_img_set_ver_str->length) { 1273 return PLDM_ERROR_INVALID_LENGTH; 1274 } 1275 1276 if ((comp_image_set_ver_str_len == 0) || 1277 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) { 1278 return PLDM_ERROR_INVALID_DATA; 1279 } 1280 1281 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) || 1282 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) { 1283 return PLDM_ERROR_INVALID_DATA; 1284 } 1285 1286 if (!is_string_type_valid(comp_image_set_ver_str_type)) { 1287 return PLDM_ERROR_INVALID_DATA; 1288 } 1289 1290 struct pldm_header_info header = { 0 }; 1291 header.instance = instance_id; 1292 header.msg_type = PLDM_REQUEST; 1293 header.pldm_type = PLDM_FWUP; 1294 header.command = PLDM_REQUEST_UPDATE; 1295 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1296 if (rc) { 1297 return rc; 1298 } 1299 1300 struct pldm_request_update_req *request = 1301 (struct pldm_request_update_req *)msg->payload; 1302 1303 request->max_transfer_size = htole32(max_transfer_size); 1304 request->num_of_comp = htole16(num_of_comp); 1305 request->max_outstanding_transfer_req = max_outstanding_transfer_req; 1306 request->pkg_data_len = htole16(pkg_data_len); 1307 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type; 1308 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len; 1309 1310 memcpy(msg->payload + sizeof(struct pldm_request_update_req), 1311 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length); 1312 1313 return PLDM_SUCCESS; 1314 } 1315 1316 LIBPLDM_ABI_STABLE 1317 int decode_request_update_resp(const struct pldm_msg *msg, 1318 size_t payload_length, uint8_t *completion_code, 1319 uint16_t *fd_meta_data_len, 1320 uint8_t *fd_will_send_pkg_data) 1321 { 1322 if (msg == NULL || completion_code == NULL || 1323 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL || 1324 !payload_length) { 1325 return PLDM_ERROR_INVALID_DATA; 1326 } 1327 1328 *completion_code = msg->payload[0]; 1329 if (*completion_code != PLDM_SUCCESS) { 1330 return PLDM_SUCCESS; 1331 } 1332 1333 if (payload_length != sizeof(struct pldm_request_update_resp)) { 1334 return PLDM_ERROR_INVALID_LENGTH; 1335 } 1336 1337 struct pldm_request_update_resp *response = 1338 (struct pldm_request_update_resp *)msg->payload; 1339 1340 *fd_meta_data_len = le16toh(response->fd_meta_data_len); 1341 *fd_will_send_pkg_data = response->fd_will_send_pkg_data; 1342 1343 return PLDM_SUCCESS; 1344 } 1345 1346 LIBPLDM_ABI_STABLE 1347 int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag, 1348 uint16_t comp_classification, 1349 uint16_t comp_identifier, 1350 uint8_t comp_classification_index, 1351 uint32_t comp_comparison_stamp, 1352 uint8_t comp_ver_str_type, 1353 uint8_t comp_ver_str_len, 1354 const struct variable_field *comp_ver_str, 1355 struct pldm_msg *msg, size_t payload_length) 1356 { 1357 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) { 1358 return PLDM_ERROR_INVALID_DATA; 1359 } 1360 1361 if (payload_length != sizeof(struct pldm_pass_component_table_req) + 1362 comp_ver_str->length) { 1363 return PLDM_ERROR_INVALID_LENGTH; 1364 } 1365 1366 if ((comp_ver_str_len == 0) || 1367 (comp_ver_str_len != comp_ver_str->length)) { 1368 return PLDM_ERROR_INVALID_DATA; 1369 } 1370 1371 if (!is_transfer_flag_valid(transfer_flag)) { 1372 return PLDM_INVALID_TRANSFER_OPERATION_FLAG; 1373 } 1374 1375 if (!is_string_type_valid(comp_ver_str_type)) { 1376 return PLDM_ERROR_INVALID_DATA; 1377 } 1378 1379 struct pldm_header_info header = { 0 }; 1380 header.instance = instance_id; 1381 header.msg_type = PLDM_REQUEST; 1382 header.pldm_type = PLDM_FWUP; 1383 header.command = PLDM_PASS_COMPONENT_TABLE; 1384 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1385 if (rc) { 1386 return rc; 1387 } 1388 1389 struct pldm_pass_component_table_req *request = 1390 (struct pldm_pass_component_table_req *)msg->payload; 1391 1392 request->transfer_flag = transfer_flag; 1393 request->comp_classification = htole16(comp_classification); 1394 request->comp_identifier = htole16(comp_identifier); 1395 request->comp_classification_index = comp_classification_index; 1396 request->comp_comparison_stamp = htole32(comp_comparison_stamp); 1397 request->comp_ver_str_type = comp_ver_str_type; 1398 request->comp_ver_str_len = comp_ver_str_len; 1399 1400 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req), 1401 comp_ver_str->ptr, comp_ver_str->length); 1402 1403 return PLDM_SUCCESS; 1404 } 1405 1406 LIBPLDM_ABI_STABLE 1407 int decode_pass_component_table_resp(const struct pldm_msg *msg, 1408 const size_t payload_length, 1409 uint8_t *completion_code, 1410 uint8_t *comp_resp, 1411 uint8_t *comp_resp_code) 1412 { 1413 if (msg == NULL || completion_code == NULL || comp_resp == NULL || 1414 comp_resp_code == NULL || !payload_length) { 1415 return PLDM_ERROR_INVALID_DATA; 1416 } 1417 1418 *completion_code = msg->payload[0]; 1419 if (*completion_code != PLDM_SUCCESS) { 1420 return PLDM_SUCCESS; 1421 } 1422 1423 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) { 1424 return PLDM_ERROR_INVALID_LENGTH; 1425 } 1426 1427 struct pldm_pass_component_table_resp *response = 1428 (struct pldm_pass_component_table_resp *)msg->payload; 1429 1430 if (!is_comp_resp_valid(response->comp_resp)) { 1431 return PLDM_ERROR_INVALID_DATA; 1432 } 1433 1434 if (!is_comp_resp_code_valid(response->comp_resp_code)) { 1435 return PLDM_ERROR_INVALID_DATA; 1436 } 1437 1438 *comp_resp = response->comp_resp; 1439 *comp_resp_code = response->comp_resp_code; 1440 1441 return PLDM_SUCCESS; 1442 } 1443 1444 LIBPLDM_ABI_STABLE 1445 int encode_update_component_req( 1446 uint8_t instance_id, uint16_t comp_classification, 1447 uint16_t comp_identifier, uint8_t comp_classification_index, 1448 uint32_t comp_comparison_stamp, uint32_t comp_image_size, 1449 bitfield32_t update_option_flags, uint8_t comp_ver_str_type, 1450 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str, 1451 struct pldm_msg *msg, size_t payload_length) 1452 { 1453 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) { 1454 return PLDM_ERROR_INVALID_DATA; 1455 } 1456 1457 if (payload_length != 1458 sizeof(struct pldm_update_component_req) + comp_ver_str->length) { 1459 return PLDM_ERROR_INVALID_LENGTH; 1460 } 1461 1462 if (!comp_image_size) { 1463 return PLDM_ERROR_INVALID_DATA; 1464 } 1465 1466 if ((comp_ver_str_len == 0) || 1467 (comp_ver_str_len != comp_ver_str->length)) { 1468 return PLDM_ERROR_INVALID_DATA; 1469 } 1470 1471 if (!is_string_type_valid(comp_ver_str_type)) { 1472 return PLDM_ERROR_INVALID_DATA; 1473 } 1474 1475 struct pldm_header_info header = { 0 }; 1476 header.instance = instance_id; 1477 header.msg_type = PLDM_REQUEST; 1478 header.pldm_type = PLDM_FWUP; 1479 header.command = PLDM_UPDATE_COMPONENT; 1480 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1481 if (rc) { 1482 return rc; 1483 } 1484 1485 struct pldm_update_component_req *request = 1486 (struct pldm_update_component_req *)msg->payload; 1487 1488 request->comp_classification = htole16(comp_classification); 1489 request->comp_identifier = htole16(comp_identifier); 1490 request->comp_classification_index = comp_classification_index; 1491 request->comp_comparison_stamp = htole32(comp_comparison_stamp); 1492 request->comp_image_size = htole32(comp_image_size); 1493 request->update_option_flags.value = htole32(update_option_flags.value); 1494 request->comp_ver_str_type = comp_ver_str_type; 1495 request->comp_ver_str_len = comp_ver_str_len; 1496 1497 memcpy(msg->payload + sizeof(struct pldm_update_component_req), 1498 comp_ver_str->ptr, comp_ver_str->length); 1499 1500 return PLDM_SUCCESS; 1501 } 1502 1503 LIBPLDM_ABI_STABLE 1504 int decode_update_component_resp(const struct pldm_msg *msg, 1505 size_t payload_length, 1506 uint8_t *completion_code, 1507 uint8_t *comp_compatibility_resp, 1508 uint8_t *comp_compatibility_resp_code, 1509 bitfield32_t *update_option_flags_enabled, 1510 uint16_t *time_before_req_fw_data) 1511 { 1512 if (msg == NULL || completion_code == NULL || 1513 comp_compatibility_resp == NULL || 1514 comp_compatibility_resp_code == NULL || 1515 update_option_flags_enabled == NULL || 1516 time_before_req_fw_data == NULL || !payload_length) { 1517 return PLDM_ERROR_INVALID_DATA; 1518 } 1519 1520 *completion_code = msg->payload[0]; 1521 if (*completion_code != PLDM_SUCCESS) { 1522 return PLDM_SUCCESS; 1523 } 1524 1525 if (payload_length != sizeof(struct pldm_update_component_resp)) { 1526 return PLDM_ERROR_INVALID_LENGTH; 1527 } 1528 1529 struct pldm_update_component_resp *response = 1530 (struct pldm_update_component_resp *)msg->payload; 1531 1532 if (!is_comp_compatibility_resp_valid( 1533 response->comp_compatibility_resp)) { 1534 return PLDM_ERROR_INVALID_DATA; 1535 } 1536 1537 if (!is_comp_compatibility_resp_code_valid( 1538 response->comp_compatibility_resp_code)) { 1539 return PLDM_ERROR_INVALID_DATA; 1540 } 1541 1542 *comp_compatibility_resp = response->comp_compatibility_resp; 1543 *comp_compatibility_resp_code = response->comp_compatibility_resp_code; 1544 update_option_flags_enabled->value = 1545 le32toh(response->update_option_flags_enabled.value); 1546 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data); 1547 1548 return PLDM_SUCCESS; 1549 } 1550 1551 LIBPLDM_ABI_STABLE 1552 int decode_request_firmware_data_req(const struct pldm_msg *msg, 1553 size_t payload_length, uint32_t *offset, 1554 uint32_t *length) 1555 { 1556 if (msg == NULL || offset == NULL || length == NULL) { 1557 return PLDM_ERROR_INVALID_DATA; 1558 } 1559 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) { 1560 return PLDM_ERROR_INVALID_LENGTH; 1561 } 1562 struct pldm_request_firmware_data_req *request = 1563 (struct pldm_request_firmware_data_req *)msg->payload; 1564 *offset = le32toh(request->offset); 1565 *length = le32toh(request->length); 1566 1567 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) { 1568 return PLDM_FWUP_INVALID_TRANSFER_LENGTH; 1569 } 1570 1571 return PLDM_SUCCESS; 1572 } 1573 1574 LIBPLDM_ABI_STABLE 1575 int encode_request_firmware_data_resp(uint8_t instance_id, 1576 uint8_t completion_code, 1577 struct pldm_msg *msg, 1578 size_t payload_length) 1579 { 1580 if (msg == NULL || !payload_length) { 1581 return PLDM_ERROR_INVALID_DATA; 1582 } 1583 1584 struct pldm_header_info header = { 0 }; 1585 header.instance = instance_id; 1586 header.msg_type = PLDM_RESPONSE; 1587 header.pldm_type = PLDM_FWUP; 1588 header.command = PLDM_REQUEST_FIRMWARE_DATA; 1589 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1590 if (rc) { 1591 return rc; 1592 } 1593 1594 msg->payload[0] = completion_code; 1595 1596 return PLDM_SUCCESS; 1597 } 1598 1599 LIBPLDM_ABI_STABLE 1600 int decode_transfer_complete_req(const struct pldm_msg *msg, 1601 size_t payload_length, 1602 uint8_t *transfer_result) 1603 { 1604 if (msg == NULL || transfer_result == NULL) { 1605 return PLDM_ERROR_INVALID_DATA; 1606 } 1607 1608 if (payload_length != sizeof(*transfer_result)) { 1609 return PLDM_ERROR_INVALID_LENGTH; 1610 } 1611 1612 *transfer_result = msg->payload[0]; 1613 return PLDM_SUCCESS; 1614 } 1615 1616 LIBPLDM_ABI_STABLE 1617 int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code, 1618 struct pldm_msg *msg, size_t payload_length) 1619 { 1620 if (msg == NULL) { 1621 return PLDM_ERROR_INVALID_DATA; 1622 } 1623 1624 if (payload_length != sizeof(completion_code)) { 1625 return PLDM_ERROR_INVALID_LENGTH; 1626 } 1627 1628 struct pldm_header_info header = { 0 }; 1629 header.instance = instance_id; 1630 header.msg_type = PLDM_RESPONSE; 1631 header.pldm_type = PLDM_FWUP; 1632 header.command = PLDM_TRANSFER_COMPLETE; 1633 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1634 if (rc) { 1635 return rc; 1636 } 1637 1638 msg->payload[0] = completion_code; 1639 1640 return PLDM_SUCCESS; 1641 } 1642 1643 LIBPLDM_ABI_STABLE 1644 int decode_verify_complete_req(const struct pldm_msg *msg, 1645 size_t payload_length, uint8_t *verify_result) 1646 { 1647 if (msg == NULL || verify_result == NULL) { 1648 return PLDM_ERROR_INVALID_DATA; 1649 } 1650 1651 if (payload_length != sizeof(*verify_result)) { 1652 return PLDM_ERROR_INVALID_LENGTH; 1653 } 1654 1655 *verify_result = msg->payload[0]; 1656 return PLDM_SUCCESS; 1657 } 1658 1659 LIBPLDM_ABI_STABLE 1660 int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code, 1661 struct pldm_msg *msg, size_t payload_length) 1662 { 1663 if (msg == NULL) { 1664 return PLDM_ERROR_INVALID_DATA; 1665 } 1666 1667 if (payload_length != sizeof(completion_code)) { 1668 return PLDM_ERROR_INVALID_LENGTH; 1669 } 1670 1671 struct pldm_header_info header = { 0 }; 1672 header.instance = instance_id; 1673 header.msg_type = PLDM_RESPONSE; 1674 header.pldm_type = PLDM_FWUP; 1675 header.command = PLDM_VERIFY_COMPLETE; 1676 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1677 if (rc) { 1678 return rc; 1679 } 1680 1681 msg->payload[0] = completion_code; 1682 1683 return PLDM_SUCCESS; 1684 } 1685 1686 LIBPLDM_ABI_STABLE 1687 int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length, 1688 uint8_t *apply_result, 1689 bitfield16_t *comp_activation_methods_modification) 1690 { 1691 if (msg == NULL || apply_result == NULL || 1692 comp_activation_methods_modification == NULL) { 1693 return PLDM_ERROR_INVALID_DATA; 1694 } 1695 1696 if (payload_length != sizeof(struct pldm_apply_complete_req)) { 1697 return PLDM_ERROR_INVALID_LENGTH; 1698 } 1699 1700 struct pldm_apply_complete_req *request = 1701 (struct pldm_apply_complete_req *)msg->payload; 1702 1703 *apply_result = request->apply_result; 1704 comp_activation_methods_modification->value = 1705 le16toh(request->comp_activation_methods_modification.value); 1706 1707 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) && 1708 comp_activation_methods_modification->value) { 1709 return PLDM_ERROR_INVALID_DATA; 1710 } 1711 1712 return PLDM_SUCCESS; 1713 } 1714 1715 LIBPLDM_ABI_STABLE 1716 int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code, 1717 struct pldm_msg *msg, size_t payload_length) 1718 { 1719 if (msg == NULL) { 1720 return PLDM_ERROR_INVALID_DATA; 1721 } 1722 1723 if (payload_length != sizeof(completion_code)) { 1724 return PLDM_ERROR_INVALID_LENGTH; 1725 } 1726 1727 struct pldm_header_info header = { 0 }; 1728 header.instance = instance_id; 1729 header.msg_type = PLDM_RESPONSE; 1730 header.pldm_type = PLDM_FWUP; 1731 header.command = PLDM_APPLY_COMPLETE; 1732 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1733 if (rc) { 1734 return rc; 1735 } 1736 1737 msg->payload[0] = completion_code; 1738 1739 return PLDM_SUCCESS; 1740 } 1741 1742 LIBPLDM_ABI_STABLE 1743 int encode_activate_firmware_req(uint8_t instance_id, 1744 bool8_t self_contained_activation_req, 1745 struct pldm_msg *msg, size_t payload_length) 1746 { 1747 if (msg == NULL) { 1748 return PLDM_ERROR_INVALID_DATA; 1749 } 1750 1751 if (payload_length != sizeof(struct pldm_activate_firmware_req)) { 1752 return PLDM_ERROR_INVALID_LENGTH; 1753 } 1754 1755 if (!is_self_contained_activation_req_valid( 1756 self_contained_activation_req)) { 1757 return PLDM_ERROR_INVALID_DATA; 1758 } 1759 1760 struct pldm_header_info header = { 0 }; 1761 header.instance = instance_id; 1762 header.msg_type = PLDM_REQUEST; 1763 header.pldm_type = PLDM_FWUP; 1764 header.command = PLDM_ACTIVATE_FIRMWARE; 1765 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1766 if (rc) { 1767 return rc; 1768 } 1769 1770 struct pldm_activate_firmware_req *request = 1771 (struct pldm_activate_firmware_req *)msg->payload; 1772 1773 request->self_contained_activation_req = self_contained_activation_req; 1774 1775 return PLDM_SUCCESS; 1776 } 1777 1778 LIBPLDM_ABI_STABLE 1779 int decode_activate_firmware_resp(const struct pldm_msg *msg, 1780 size_t payload_length, 1781 uint8_t *completion_code, 1782 uint16_t *estimated_time_activation) 1783 { 1784 if (msg == NULL || completion_code == NULL || 1785 estimated_time_activation == NULL || !payload_length) { 1786 return PLDM_ERROR_INVALID_DATA; 1787 } 1788 1789 *completion_code = msg->payload[0]; 1790 if (*completion_code != PLDM_SUCCESS) { 1791 return PLDM_SUCCESS; 1792 } 1793 1794 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) { 1795 return PLDM_ERROR_INVALID_LENGTH; 1796 } 1797 1798 struct pldm_activate_firmware_resp *response = 1799 (struct pldm_activate_firmware_resp *)msg->payload; 1800 1801 *estimated_time_activation = 1802 le16toh(response->estimated_time_activation); 1803 1804 return PLDM_SUCCESS; 1805 } 1806 1807 LIBPLDM_ABI_STABLE 1808 int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg, 1809 size_t payload_length) 1810 { 1811 if (msg == NULL) { 1812 return PLDM_ERROR_INVALID_DATA; 1813 } 1814 1815 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) { 1816 return PLDM_ERROR_INVALID_LENGTH; 1817 } 1818 1819 struct pldm_header_info header = { 0 }; 1820 header.instance = instance_id; 1821 header.msg_type = PLDM_REQUEST; 1822 header.pldm_type = PLDM_FWUP; 1823 header.command = PLDM_GET_STATUS; 1824 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1825 if (rc) { 1826 return rc; 1827 } 1828 1829 return PLDM_SUCCESS; 1830 } 1831 1832 LIBPLDM_ABI_STABLE 1833 int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length, 1834 uint8_t *completion_code, uint8_t *current_state, 1835 uint8_t *previous_state, uint8_t *aux_state, 1836 uint8_t *aux_state_status, uint8_t *progress_percent, 1837 uint8_t *reason_code, 1838 bitfield32_t *update_option_flags_enabled) 1839 { 1840 if (msg == NULL || completion_code == NULL || current_state == NULL || 1841 previous_state == NULL || aux_state == NULL || 1842 aux_state_status == NULL || progress_percent == NULL || 1843 reason_code == NULL || update_option_flags_enabled == NULL || 1844 !payload_length) { 1845 return PLDM_ERROR_INVALID_DATA; 1846 } 1847 1848 *completion_code = msg->payload[0]; 1849 if (*completion_code != PLDM_SUCCESS) { 1850 return PLDM_SUCCESS; 1851 } 1852 1853 if (payload_length != sizeof(struct pldm_get_status_resp)) { 1854 return PLDM_ERROR_INVALID_LENGTH; 1855 } 1856 struct pldm_get_status_resp *response = 1857 (struct pldm_get_status_resp *)msg->payload; 1858 1859 if (!is_state_valid(response->current_state)) { 1860 return PLDM_ERROR_INVALID_DATA; 1861 } 1862 if (!is_state_valid(response->previous_state)) { 1863 return PLDM_ERROR_INVALID_DATA; 1864 } 1865 if (!is_aux_state_valid(response->aux_state)) { 1866 return PLDM_ERROR_INVALID_DATA; 1867 } 1868 if (!is_aux_state_status_valid(response->aux_state_status)) { 1869 return PLDM_ERROR_INVALID_DATA; 1870 } 1871 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) { 1872 return PLDM_ERROR_INVALID_DATA; 1873 } 1874 if (!is_reason_code_valid(response->reason_code)) { 1875 return PLDM_ERROR_INVALID_DATA; 1876 } 1877 1878 if ((response->current_state == PLDM_FD_STATE_IDLE) || 1879 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) || 1880 (response->current_state == PLDM_FD_STATE_READY_XFER)) { 1881 if (response->aux_state != 1882 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) { 1883 return PLDM_ERROR_INVALID_DATA; 1884 } 1885 } 1886 1887 *current_state = response->current_state; 1888 *previous_state = response->previous_state; 1889 *aux_state = response->aux_state; 1890 *aux_state_status = response->aux_state_status; 1891 *progress_percent = response->progress_percent; 1892 *reason_code = response->reason_code; 1893 update_option_flags_enabled->value = 1894 le32toh(response->update_option_flags_enabled.value); 1895 1896 return PLDM_SUCCESS; 1897 } 1898 1899 LIBPLDM_ABI_STABLE 1900 int encode_cancel_update_component_req(uint8_t instance_id, 1901 struct pldm_msg *msg, 1902 size_t payload_length) 1903 { 1904 if (msg == NULL) { 1905 return PLDM_ERROR_INVALID_DATA; 1906 } 1907 1908 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) { 1909 return PLDM_ERROR_INVALID_LENGTH; 1910 } 1911 1912 struct pldm_header_info header = { 0 }; 1913 header.instance = instance_id; 1914 header.msg_type = PLDM_REQUEST; 1915 header.pldm_type = PLDM_FWUP; 1916 header.command = PLDM_CANCEL_UPDATE_COMPONENT; 1917 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1918 if (rc) { 1919 return rc; 1920 } 1921 1922 return PLDM_SUCCESS; 1923 } 1924 1925 LIBPLDM_ABI_STABLE 1926 int decode_cancel_update_component_resp(const struct pldm_msg *msg, 1927 size_t payload_length, 1928 uint8_t *completion_code) 1929 { 1930 if (msg == NULL || completion_code == NULL) { 1931 return PLDM_ERROR_INVALID_DATA; 1932 } 1933 1934 if (payload_length != sizeof(*completion_code)) { 1935 return PLDM_ERROR_INVALID_LENGTH; 1936 } 1937 1938 *completion_code = msg->payload[0]; 1939 return PLDM_SUCCESS; 1940 } 1941 1942 LIBPLDM_ABI_STABLE 1943 int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg, 1944 size_t payload_length) 1945 { 1946 if (msg == NULL) { 1947 return PLDM_ERROR_INVALID_DATA; 1948 } 1949 1950 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) { 1951 return PLDM_ERROR_INVALID_LENGTH; 1952 } 1953 1954 struct pldm_header_info header = { 0 }; 1955 header.instance = instance_id; 1956 header.msg_type = PLDM_REQUEST; 1957 header.pldm_type = PLDM_FWUP; 1958 header.command = PLDM_CANCEL_UPDATE; 1959 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1960 if (rc) { 1961 return rc; 1962 } 1963 1964 return PLDM_SUCCESS; 1965 } 1966 1967 LIBPLDM_ABI_STABLE 1968 int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length, 1969 uint8_t *completion_code, 1970 bool8_t *non_functioning_component_indication, 1971 bitfield64_t *non_functioning_component_bitmap) 1972 { 1973 if (msg == NULL || completion_code == NULL || 1974 non_functioning_component_indication == NULL || 1975 non_functioning_component_bitmap == NULL || !payload_length) { 1976 return PLDM_ERROR_INVALID_DATA; 1977 } 1978 1979 *completion_code = msg->payload[0]; 1980 if (*completion_code != PLDM_SUCCESS) { 1981 return PLDM_SUCCESS; 1982 } 1983 1984 if (payload_length != sizeof(struct pldm_cancel_update_resp)) { 1985 return PLDM_ERROR_INVALID_LENGTH; 1986 } 1987 struct pldm_cancel_update_resp *response = 1988 (struct pldm_cancel_update_resp *)msg->payload; 1989 1990 if (!is_non_functioning_component_indication_valid( 1991 response->non_functioning_component_indication)) { 1992 return PLDM_ERROR_INVALID_DATA; 1993 } 1994 1995 *non_functioning_component_indication = 1996 response->non_functioning_component_indication; 1997 1998 if (*non_functioning_component_indication) { 1999 non_functioning_component_bitmap->value = 2000 le64toh(response->non_functioning_component_bitmap); 2001 } 2002 2003 return PLDM_SUCCESS; 2004 } 2005