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