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_TESTING 477 int decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter *iter, 478 struct pldm_descriptor *desc) 479 { 480 struct pldm_msgbuf _buf; 481 struct pldm_msgbuf *buf = &_buf; 482 int rc; 483 484 if (!iter || !iter->field || !desc) { 485 return -EINVAL; 486 } 487 488 rc = pldm_msgbuf_init_errno(buf, PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN, 489 iter->field->ptr, iter->field->length); 490 if (rc) { 491 return rc; 492 } 493 494 pldm_msgbuf_extract(buf, desc->descriptor_type); 495 rc = pldm_msgbuf_extract(buf, desc->descriptor_length); 496 if (rc) { 497 return rc; 498 } 499 500 desc->descriptor_data = NULL; 501 pldm_msgbuf_span_required(buf, desc->descriptor_length, 502 (void **)&desc->descriptor_data); 503 iter->field->ptr = NULL; 504 pldm_msgbuf_span_remaining(buf, (void **)&iter->field->ptr, 505 &iter->field->length); 506 507 return pldm_msgbuf_destroy(buf); 508 } 509 510 LIBPLDM_ABI_STABLE 511 int decode_descriptor_type_length_value(const uint8_t *data, size_t length, 512 uint16_t *descriptor_type, 513 struct variable_field *descriptor_data) 514 { 515 uint16_t descriptor_length = 0; 516 517 if (data == NULL || descriptor_type == NULL || 518 descriptor_data == NULL) { 519 return PLDM_ERROR_INVALID_DATA; 520 } 521 522 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) { 523 return PLDM_ERROR_INVALID_LENGTH; 524 } 525 526 struct pldm_descriptor_tlv *entry = 527 (struct pldm_descriptor_tlv *)(data); 528 529 *descriptor_type = le16toh(entry->descriptor_type); 530 descriptor_length = le16toh(entry->descriptor_length); 531 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) { 532 if (descriptor_length != 533 get_descriptor_type_length(*descriptor_type)) { 534 return PLDM_ERROR_INVALID_LENGTH; 535 } 536 } 537 538 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) + 539 descriptor_length)) { 540 return PLDM_ERROR_INVALID_LENGTH; 541 } 542 543 descriptor_data->ptr = entry->descriptor_data; 544 descriptor_data->length = descriptor_length; 545 546 return PLDM_SUCCESS; 547 } 548 549 LIBPLDM_ABI_STABLE 550 int decode_vendor_defined_descriptor_value( 551 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type, 552 struct variable_field *descriptor_title_str, 553 struct variable_field *descriptor_data) 554 { 555 if (data == NULL || descriptor_title_str_type == NULL || 556 descriptor_title_str == NULL || descriptor_data == NULL) { 557 return PLDM_ERROR_INVALID_DATA; 558 } 559 560 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) { 561 return PLDM_ERROR_INVALID_LENGTH; 562 } 563 564 struct pldm_vendor_defined_descriptor_title_data *entry = 565 (struct pldm_vendor_defined_descriptor_title_data *)(data); 566 if (!is_string_type_valid( 567 entry->vendor_defined_descriptor_title_str_type) || 568 (entry->vendor_defined_descriptor_title_str_len == 0)) { 569 return PLDM_ERROR_INVALID_DATA; 570 } 571 572 // Assuming at least 1 byte of VendorDefinedDescriptorData 573 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) + 574 entry->vendor_defined_descriptor_title_str_len)) { 575 return PLDM_ERROR_INVALID_LENGTH; 576 } 577 578 *descriptor_title_str_type = 579 entry->vendor_defined_descriptor_title_str_type; 580 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str; 581 descriptor_title_str->length = 582 entry->vendor_defined_descriptor_title_str_len; 583 584 descriptor_data->ptr = 585 descriptor_title_str->ptr + descriptor_title_str->length; 586 descriptor_data->length = 587 length - 588 sizeof(entry->vendor_defined_descriptor_title_str_type) - 589 sizeof(entry->vendor_defined_descriptor_title_str_len) - 590 descriptor_title_str->length; 591 592 return PLDM_SUCCESS; 593 } 594 595 LIBPLDM_ABI_STABLE 596 int decode_pldm_comp_image_info( 597 const uint8_t *data, size_t length, 598 struct pldm_component_image_information *pldm_comp_image_info, 599 struct variable_field *comp_version_str) 600 { 601 if (data == NULL || pldm_comp_image_info == NULL || 602 comp_version_str == NULL) { 603 return PLDM_ERROR_INVALID_DATA; 604 } 605 606 if (length < sizeof(struct pldm_component_image_information)) { 607 return PLDM_ERROR_INVALID_LENGTH; 608 } 609 610 struct pldm_component_image_information *data_header = 611 (struct pldm_component_image_information *)(data); 612 613 if (!is_string_type_valid(data_header->comp_version_string_type) || 614 (data_header->comp_version_string_length == 0)) { 615 return PLDM_ERROR_INVALID_DATA; 616 } 617 618 if (length < sizeof(struct pldm_component_image_information) + 619 data_header->comp_version_string_length) { 620 return PLDM_ERROR_INVALID_LENGTH; 621 } 622 623 pldm_comp_image_info->comp_classification = 624 le16toh(data_header->comp_classification); 625 pldm_comp_image_info->comp_identifier = 626 le16toh(data_header->comp_identifier); 627 pldm_comp_image_info->comp_comparison_stamp = 628 le32toh(data_header->comp_comparison_stamp); 629 pldm_comp_image_info->comp_options.value = 630 le16toh(data_header->comp_options.value); 631 pldm_comp_image_info->requested_comp_activation_method.value = 632 le16toh(data_header->requested_comp_activation_method.value); 633 pldm_comp_image_info->comp_location_offset = 634 le32toh(data_header->comp_location_offset); 635 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size); 636 pldm_comp_image_info->comp_version_string_type = 637 data_header->comp_version_string_type; 638 pldm_comp_image_info->comp_version_string_length = 639 data_header->comp_version_string_length; 640 641 if ((pldm_comp_image_info->comp_options.bits.bit1 == false && 642 pldm_comp_image_info->comp_comparison_stamp != 643 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) { 644 return PLDM_ERROR_INVALID_DATA; 645 } 646 647 if (pldm_comp_image_info->comp_location_offset == 0 || 648 pldm_comp_image_info->comp_size == 0) { 649 return PLDM_ERROR_INVALID_DATA; 650 } 651 652 comp_version_str->ptr = 653 data + sizeof(struct pldm_component_image_information); 654 comp_version_str->length = 655 pldm_comp_image_info->comp_version_string_length; 656 657 return PLDM_SUCCESS; 658 } 659 660 LIBPLDM_ABI_STABLE 661 int encode_query_device_identifiers_req(uint8_t instance_id, 662 size_t payload_length, 663 struct pldm_msg *msg) 664 { 665 if (msg == NULL) { 666 return PLDM_ERROR_INVALID_DATA; 667 } 668 669 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) { 670 return PLDM_ERROR_INVALID_LENGTH; 671 } 672 673 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 674 PLDM_QUERY_DEVICE_IDENTIFIERS, msg); 675 } 676 677 LIBPLDM_ABI_STABLE 678 int decode_query_device_identifiers_resp(const struct pldm_msg *msg, 679 size_t payload_length, 680 uint8_t *completion_code, 681 uint32_t *device_identifiers_len, 682 uint8_t *descriptor_count, 683 uint8_t **descriptor_data) 684 { 685 if (msg == NULL || completion_code == NULL || 686 device_identifiers_len == NULL || descriptor_count == NULL || 687 descriptor_data == NULL) { 688 return PLDM_ERROR_INVALID_DATA; 689 } 690 691 *completion_code = msg->payload[0]; 692 if (PLDM_SUCCESS != *completion_code) { 693 return PLDM_SUCCESS; 694 } 695 696 if (payload_length < 697 sizeof(struct pldm_query_device_identifiers_resp)) { 698 return PLDM_ERROR_INVALID_LENGTH; 699 } 700 701 struct pldm_query_device_identifiers_resp *response = 702 (struct pldm_query_device_identifiers_resp *)msg->payload; 703 *device_identifiers_len = le32toh(response->device_identifiers_len); 704 705 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) { 706 return PLDM_ERROR_INVALID_LENGTH; 707 } 708 709 if (payload_length != 710 sizeof(struct pldm_query_device_identifiers_resp) + 711 *device_identifiers_len) { 712 return PLDM_ERROR_INVALID_LENGTH; 713 } 714 *descriptor_count = response->descriptor_count; 715 716 if (*descriptor_count == 0) { 717 return PLDM_ERROR_INVALID_DATA; 718 } 719 *descriptor_data = 720 (uint8_t *)(msg->payload + 721 sizeof(struct pldm_query_device_identifiers_resp)); 722 return PLDM_SUCCESS; 723 } 724 725 LIBPLDM_ABI_STABLE 726 int encode_get_firmware_parameters_req(uint8_t instance_id, 727 size_t payload_length, 728 struct pldm_msg *msg) 729 { 730 if (msg == NULL) { 731 return PLDM_ERROR_INVALID_DATA; 732 } 733 734 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) { 735 return PLDM_ERROR_INVALID_LENGTH; 736 } 737 738 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 739 PLDM_GET_FIRMWARE_PARAMETERS, msg); 740 } 741 742 LIBPLDM_ABI_STABLE 743 int decode_get_firmware_parameters_resp( 744 const struct pldm_msg *msg, size_t payload_length, 745 struct pldm_get_firmware_parameters_resp *resp_data, 746 struct variable_field *active_comp_image_set_ver_str, 747 struct variable_field *pending_comp_image_set_ver_str, 748 struct variable_field *comp_parameter_table) 749 { 750 if (msg == NULL || resp_data == NULL || 751 active_comp_image_set_ver_str == NULL || 752 pending_comp_image_set_ver_str == NULL || 753 comp_parameter_table == NULL || !payload_length) { 754 return PLDM_ERROR_INVALID_DATA; 755 } 756 757 resp_data->completion_code = msg->payload[0]; 758 if (PLDM_SUCCESS != resp_data->completion_code) { 759 return PLDM_SUCCESS; 760 } 761 762 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) { 763 return PLDM_ERROR_INVALID_LENGTH; 764 } 765 766 struct pldm_get_firmware_parameters_resp *response = 767 (struct pldm_get_firmware_parameters_resp *)msg->payload; 768 769 if (!is_string_type_valid( 770 response->active_comp_image_set_ver_str_type) || 771 (response->active_comp_image_set_ver_str_len == 0)) { 772 return PLDM_ERROR_INVALID_DATA; 773 } 774 775 if (response->pending_comp_image_set_ver_str_len == 0) { 776 if (response->pending_comp_image_set_ver_str_type != 777 PLDM_STR_TYPE_UNKNOWN) { 778 return PLDM_ERROR_INVALID_DATA; 779 } 780 } else { 781 if (!is_string_type_valid( 782 response->pending_comp_image_set_ver_str_type)) { 783 return PLDM_ERROR_INVALID_DATA; 784 } 785 } 786 787 size_t partial_response_length = 788 sizeof(struct pldm_get_firmware_parameters_resp) + 789 response->active_comp_image_set_ver_str_len + 790 response->pending_comp_image_set_ver_str_len; 791 792 if (payload_length < partial_response_length) { 793 return PLDM_ERROR_INVALID_LENGTH; 794 } 795 796 resp_data->capabilities_during_update.value = 797 le32toh(response->capabilities_during_update.value); 798 resp_data->comp_count = le16toh(response->comp_count); 799 resp_data->active_comp_image_set_ver_str_type = 800 response->active_comp_image_set_ver_str_type; 801 resp_data->active_comp_image_set_ver_str_len = 802 response->active_comp_image_set_ver_str_len; 803 resp_data->pending_comp_image_set_ver_str_type = 804 response->pending_comp_image_set_ver_str_type; 805 resp_data->pending_comp_image_set_ver_str_len = 806 response->pending_comp_image_set_ver_str_len; 807 808 active_comp_image_set_ver_str->ptr = 809 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp); 810 active_comp_image_set_ver_str->length = 811 resp_data->active_comp_image_set_ver_str_len; 812 813 if (resp_data->pending_comp_image_set_ver_str_len != 0) { 814 pending_comp_image_set_ver_str->ptr = 815 msg->payload + 816 sizeof(struct pldm_get_firmware_parameters_resp) + 817 resp_data->active_comp_image_set_ver_str_len; 818 pending_comp_image_set_ver_str->length = 819 resp_data->pending_comp_image_set_ver_str_len; 820 } else { 821 pending_comp_image_set_ver_str->ptr = NULL; 822 pending_comp_image_set_ver_str->length = 0; 823 } 824 825 if (payload_length > partial_response_length && resp_data->comp_count) { 826 comp_parameter_table->ptr = 827 msg->payload + 828 sizeof(struct pldm_get_firmware_parameters_resp) + 829 resp_data->active_comp_image_set_ver_str_len + 830 resp_data->pending_comp_image_set_ver_str_len; 831 comp_parameter_table->length = 832 payload_length - partial_response_length; 833 } else { 834 comp_parameter_table->ptr = NULL; 835 comp_parameter_table->length = 0; 836 } 837 838 return PLDM_SUCCESS; 839 } 840 841 LIBPLDM_ABI_STABLE 842 int decode_get_firmware_parameters_resp_comp_entry( 843 const uint8_t *data, size_t length, 844 struct pldm_component_parameter_entry *component_data, 845 struct variable_field *active_comp_ver_str, 846 struct variable_field *pending_comp_ver_str) 847 { 848 if (data == NULL || component_data == NULL || 849 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) { 850 return PLDM_ERROR_INVALID_DATA; 851 } 852 853 if (length < sizeof(struct pldm_component_parameter_entry)) { 854 return PLDM_ERROR_INVALID_LENGTH; 855 } 856 857 struct pldm_component_parameter_entry *entry = 858 (struct pldm_component_parameter_entry *)(data); 859 860 size_t entry_length = sizeof(struct pldm_component_parameter_entry) + 861 entry->active_comp_ver_str_len + 862 entry->pending_comp_ver_str_len; 863 864 if (length < entry_length) { 865 return PLDM_ERROR_INVALID_LENGTH; 866 } 867 868 component_data->comp_classification = 869 le16toh(entry->comp_classification); 870 component_data->comp_identifier = le16toh(entry->comp_identifier); 871 component_data->comp_classification_index = 872 entry->comp_classification_index; 873 component_data->active_comp_comparison_stamp = 874 le32toh(entry->active_comp_comparison_stamp); 875 component_data->active_comp_ver_str_type = 876 entry->active_comp_ver_str_type; 877 component_data->active_comp_ver_str_len = 878 entry->active_comp_ver_str_len; 879 memcpy(component_data->active_comp_release_date, 880 entry->active_comp_release_date, 881 sizeof(entry->active_comp_release_date)); 882 component_data->pending_comp_comparison_stamp = 883 le32toh(entry->pending_comp_comparison_stamp); 884 component_data->pending_comp_ver_str_type = 885 entry->pending_comp_ver_str_type; 886 component_data->pending_comp_ver_str_len = 887 entry->pending_comp_ver_str_len; 888 memcpy(component_data->pending_comp_release_date, 889 entry->pending_comp_release_date, 890 sizeof(entry->pending_comp_release_date)); 891 component_data->comp_activation_methods.value = 892 le16toh(entry->comp_activation_methods.value); 893 component_data->capabilities_during_update.value = 894 le32toh(entry->capabilities_during_update.value); 895 896 if (entry->active_comp_ver_str_len != 0) { 897 active_comp_ver_str->ptr = 898 data + sizeof(struct pldm_component_parameter_entry); 899 active_comp_ver_str->length = entry->active_comp_ver_str_len; 900 } else { 901 active_comp_ver_str->ptr = NULL; 902 active_comp_ver_str->length = 0; 903 } 904 905 if (entry->pending_comp_ver_str_len != 0) { 906 pending_comp_ver_str->ptr = 907 data + sizeof(struct pldm_component_parameter_entry) + 908 entry->active_comp_ver_str_len; 909 pending_comp_ver_str->length = entry->pending_comp_ver_str_len; 910 } else { 911 pending_comp_ver_str->ptr = NULL; 912 pending_comp_ver_str->length = 0; 913 } 914 return PLDM_SUCCESS; 915 } 916 917 LIBPLDM_ABI_TESTING 918 int encode_query_downstream_devices_req(uint8_t instance_id, 919 struct pldm_msg *msg) 920 { 921 if (msg == NULL) { 922 return -EINVAL; 923 } 924 925 return encode_pldm_header_only_errno(PLDM_REQUEST, instance_id, 926 PLDM_FWUP, 927 PLDM_QUERY_DOWNSTREAM_DEVICES, 928 msg); 929 } 930 931 LIBPLDM_ABI_TESTING 932 int decode_query_downstream_devices_resp( 933 const struct pldm_msg *msg, size_t payload_length, 934 struct pldm_query_downstream_devices_resp *resp_data) 935 { 936 struct pldm_msgbuf _buf; 937 struct pldm_msgbuf *buf = &_buf; 938 int rc; 939 940 if (msg == NULL || resp_data == NULL || !payload_length) { 941 return -EINVAL; 942 } 943 944 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 945 msg->payload, payload_length); 946 if (rc) { 947 return rc; 948 } 949 950 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 951 if (rc) { 952 return rc; 953 } 954 if (PLDM_SUCCESS != resp_data->completion_code) { 955 // Return the CC directly without decoding the rest of the payload 956 return 0; 957 } 958 959 if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) { 960 return -EBADMSG; 961 } 962 963 rc = pldm_msgbuf_extract(buf, 964 resp_data->downstream_device_update_supported); 965 if (rc) { 966 return rc; 967 } 968 969 if (!is_downstream_device_update_support_valid( 970 resp_data->downstream_device_update_supported)) { 971 return -EINVAL; 972 } 973 974 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices); 975 pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices); 976 pldm_msgbuf_extract(buf, resp_data->capabilities.value); 977 978 return pldm_msgbuf_destroy_consumed(buf); 979 } 980 981 LIBPLDM_ABI_TESTING 982 int encode_query_downstream_identifiers_req( 983 uint8_t instance_id, 984 const struct pldm_query_downstream_identifiers_req *params_req, 985 struct pldm_msg *msg, size_t payload_length) 986 { 987 struct pldm_msgbuf _buf; 988 struct pldm_msgbuf *buf = &_buf; 989 int rc; 990 991 if (!msg || !params_req) { 992 return -EINVAL; 993 } 994 995 if (!is_transfer_operation_flag_valid( 996 (enum transfer_op_flag) 997 params_req->transfer_operation_flag)) { 998 return -EINVAL; 999 } 1000 1001 struct pldm_header_info header = { 0 }; 1002 header.instance = instance_id; 1003 header.msg_type = PLDM_REQUEST; 1004 header.pldm_type = PLDM_FWUP; 1005 header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS; 1006 rc = pack_pldm_header_errno(&header, &(msg->hdr)); 1007 if (rc) { 1008 return rc; 1009 } 1010 1011 rc = pldm_msgbuf_init_errno(buf, 1012 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES, 1013 msg->payload, payload_length); 1014 if (rc) { 1015 return rc; 1016 } 1017 1018 pldm_msgbuf_insert(buf, params_req->data_transfer_handle); 1019 // Data correctness has been verified, cast it to 1-byte data directly. 1020 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag); 1021 1022 return pldm_msgbuf_destroy(buf); 1023 } 1024 1025 LIBPLDM_ABI_TESTING 1026 int decode_query_downstream_identifiers_resp( 1027 const struct pldm_msg *msg, size_t payload_length, 1028 struct pldm_query_downstream_identifiers_resp *resp_data, 1029 struct pldm_downstream_device_iter *iter) 1030 { 1031 struct pldm_msgbuf _buf; 1032 struct pldm_msgbuf *buf = &_buf; 1033 void *remaining = NULL; 1034 int rc = 0; 1035 1036 if (msg == NULL || resp_data == NULL || iter == NULL || 1037 !payload_length) { 1038 return -EINVAL; 1039 } 1040 1041 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 1042 msg->payload, payload_length); 1043 if (rc) { 1044 return rc; 1045 } 1046 1047 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 1048 if (rc) { 1049 return rc; 1050 } 1051 if (PLDM_SUCCESS != resp_data->completion_code) { 1052 return 0; 1053 } 1054 1055 if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) { 1056 return -EBADMSG; 1057 } 1058 1059 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle); 1060 pldm_msgbuf_extract(buf, resp_data->transfer_flag); 1061 1062 rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length); 1063 if (rc) { 1064 return rc; 1065 } 1066 1067 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices); 1068 rc = pldm_msgbuf_span_required( 1069 buf, resp_data->downstream_devices_length, &remaining); 1070 if (rc) { 1071 return rc; 1072 } 1073 1074 rc = pldm_msgbuf_destroy(buf); 1075 if (rc) { 1076 return rc; 1077 } 1078 1079 iter->field.ptr = remaining; 1080 iter->field.length = resp_data->downstream_devices_length; 1081 iter->devs = resp_data->number_of_downstream_devices; 1082 1083 return 0; 1084 } 1085 1086 LIBPLDM_ABI_TESTING 1087 int decode_pldm_downstream_device_from_iter( 1088 struct pldm_downstream_device_iter *iter, 1089 struct pldm_downstream_device *dev) 1090 { 1091 struct pldm_msgbuf _buf; 1092 struct pldm_msgbuf *buf = &_buf; 1093 int rc; 1094 1095 if (!iter || !dev) { 1096 return -EINVAL; 1097 } 1098 1099 rc = pldm_msgbuf_init_errno(buf, 3, iter->field.ptr, 1100 iter->field.length); 1101 if (rc) { 1102 return rc; 1103 } 1104 1105 pldm_msgbuf_extract(buf, dev->downstream_device_index); 1106 pldm_msgbuf_extract(buf, dev->downstream_descriptor_count); 1107 iter->field.ptr = NULL; 1108 pldm_msgbuf_span_remaining(buf, (void **)&iter->field.ptr, 1109 &iter->field.length); 1110 1111 return pldm_msgbuf_destroy(buf); 1112 } 1113 1114 LIBPLDM_ABI_TESTING 1115 int encode_get_downstream_firmware_parameters_req( 1116 uint8_t instance_id, 1117 const struct pldm_get_downstream_firmware_parameters_req *params_req, 1118 struct pldm_msg *msg, size_t payload_length) 1119 { 1120 struct pldm_msgbuf _buf; 1121 struct pldm_msgbuf *buf = &_buf; 1122 int rc; 1123 1124 if (!msg || !params_req) { 1125 return -EINVAL; 1126 } 1127 1128 rc = pldm_msgbuf_init_errno( 1129 buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES, 1130 msg->payload, payload_length); 1131 if (rc < 0) { 1132 return rc; 1133 } 1134 1135 if (!is_transfer_operation_flag_valid( 1136 (enum transfer_op_flag) 1137 params_req->transfer_operation_flag)) { 1138 return -EBADMSG; 1139 } 1140 1141 struct pldm_header_info header = { 0 }; 1142 header.instance = instance_id; 1143 header.msg_type = PLDM_REQUEST; 1144 header.pldm_type = PLDM_FWUP; 1145 header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS; 1146 rc = pack_pldm_header_errno(&header, &msg->hdr); 1147 if (rc < 0) { 1148 return rc; 1149 } 1150 1151 pldm_msgbuf_insert(buf, params_req->data_transfer_handle); 1152 // Data correctness has been verified, cast it to 1-byte data directly. 1153 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag); 1154 1155 return pldm_msgbuf_destroy(buf); 1156 } 1157 1158 LIBPLDM_ABI_TESTING 1159 int decode_get_downstream_firmware_parameters_resp( 1160 const struct pldm_msg *msg, size_t payload_length, 1161 struct pldm_get_downstream_firmware_parameters_resp *resp_data, 1162 struct pldm_downstream_device_parameters_iter *iter) 1163 { 1164 struct pldm_msgbuf _buf; 1165 struct pldm_msgbuf *buf = &_buf; 1166 void *remaining = NULL; 1167 size_t length; 1168 int rc; 1169 1170 if (msg == NULL || resp_data == NULL || iter == NULL) { 1171 return -EINVAL; 1172 } 1173 1174 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 1175 msg->payload, payload_length); 1176 if (rc < 0) { 1177 return rc; 1178 } 1179 1180 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 1181 if (rc < 0) { 1182 return rc; 1183 } 1184 if (PLDM_SUCCESS != resp_data->completion_code) { 1185 return 0; 1186 } 1187 1188 if (payload_length < 1189 PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN) { 1190 return -EBADMSG; 1191 } 1192 1193 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle); 1194 pldm_msgbuf_extract(buf, resp_data->transfer_flag); 1195 pldm_msgbuf_extract(buf, 1196 resp_data->fdp_capabilities_during_update.value); 1197 pldm_msgbuf_extract(buf, resp_data->downstream_device_count); 1198 1199 rc = pldm_msgbuf_span_remaining(buf, &remaining, &length); 1200 if (rc) { 1201 return rc; 1202 } 1203 1204 rc = pldm_msgbuf_destroy(buf); 1205 if (rc) { 1206 return rc; 1207 } 1208 1209 iter->field.ptr = remaining; 1210 iter->field.length = length; 1211 iter->entries = resp_data->downstream_device_count; 1212 1213 return 0; 1214 } 1215 1216 LIBPLDM_ABI_TESTING 1217 int decode_pldm_downstream_device_parameters_entry_from_iter( 1218 struct pldm_downstream_device_parameters_iter *iter, 1219 struct pldm_downstream_device_parameters_entry *entry) 1220 { 1221 struct pldm_msgbuf _buf; 1222 struct pldm_msgbuf *buf = &_buf; 1223 void *comp_ver_str; 1224 size_t remaining; 1225 void *cursor; 1226 int rc; 1227 1228 if (iter == NULL || entry == NULL) { 1229 return -EINVAL; 1230 } 1231 1232 rc = pldm_msgbuf_init_errno( 1233 buf, PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN, 1234 iter->field.ptr, iter->field.length); 1235 if (rc < 0) { 1236 return rc; 1237 } 1238 1239 pldm_msgbuf_extract(buf, entry->downstream_device_index); 1240 pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp); 1241 pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type); 1242 rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len); 1243 if (rc < 0) { 1244 return rc; 1245 } 1246 rc = pldm_msgbuf_extract_array(buf, 1247 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 1248 entry->active_comp_release_date, 1249 sizeof(entry->active_comp_release_date)); 1250 if (rc < 0) { 1251 return rc; 1252 } 1253 1254 // Fill the last byte with NULL character 1255 entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] = 1256 '\0'; 1257 1258 pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp); 1259 pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type); 1260 rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len); 1261 if (rc < 0) { 1262 return rc; 1263 } 1264 1265 rc = pldm_msgbuf_extract_array( 1266 buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 1267 entry->pending_comp_release_date, 1268 sizeof(entry->pending_comp_release_date)); 1269 if (rc < 0) { 1270 return rc; 1271 } 1272 1273 // Fill the last byte with NULL character 1274 entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] = 1275 '\0'; 1276 1277 pldm_msgbuf_extract(buf, entry->comp_activation_methods.value); 1278 pldm_msgbuf_extract(buf, entry->capabilities_during_update.value); 1279 1280 comp_ver_str = NULL; 1281 pldm_msgbuf_span_required(buf, entry->active_comp_ver_str_len, 1282 &comp_ver_str); 1283 entry->active_comp_ver_str = comp_ver_str; 1284 1285 comp_ver_str = NULL; 1286 pldm_msgbuf_span_required(buf, entry->pending_comp_ver_str_len, 1287 &comp_ver_str); 1288 entry->pending_comp_ver_str = comp_ver_str; 1289 1290 cursor = NULL; 1291 rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining); 1292 if (rc < 0) { 1293 return rc; 1294 } 1295 1296 iter->field.ptr = cursor; 1297 iter->field.length = remaining; 1298 1299 return 0; 1300 } 1301 1302 LIBPLDM_ABI_STABLE 1303 int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size, 1304 uint16_t num_of_comp, 1305 uint8_t max_outstanding_transfer_req, 1306 uint16_t pkg_data_len, 1307 uint8_t comp_image_set_ver_str_type, 1308 uint8_t comp_image_set_ver_str_len, 1309 const struct variable_field *comp_img_set_ver_str, 1310 struct pldm_msg *msg, size_t payload_length) 1311 { 1312 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL || 1313 msg == NULL) { 1314 return PLDM_ERROR_INVALID_DATA; 1315 } 1316 1317 if (payload_length != sizeof(struct pldm_request_update_req) + 1318 comp_img_set_ver_str->length) { 1319 return PLDM_ERROR_INVALID_LENGTH; 1320 } 1321 1322 if ((comp_image_set_ver_str_len == 0) || 1323 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) { 1324 return PLDM_ERROR_INVALID_DATA; 1325 } 1326 1327 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) || 1328 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) { 1329 return PLDM_ERROR_INVALID_DATA; 1330 } 1331 1332 if (!is_string_type_valid(comp_image_set_ver_str_type)) { 1333 return PLDM_ERROR_INVALID_DATA; 1334 } 1335 1336 struct pldm_header_info header = { 0 }; 1337 header.instance = instance_id; 1338 header.msg_type = PLDM_REQUEST; 1339 header.pldm_type = PLDM_FWUP; 1340 header.command = PLDM_REQUEST_UPDATE; 1341 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1342 if (rc) { 1343 return rc; 1344 } 1345 1346 struct pldm_request_update_req *request = 1347 (struct pldm_request_update_req *)msg->payload; 1348 1349 request->max_transfer_size = htole32(max_transfer_size); 1350 request->num_of_comp = htole16(num_of_comp); 1351 request->max_outstanding_transfer_req = max_outstanding_transfer_req; 1352 request->pkg_data_len = htole16(pkg_data_len); 1353 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type; 1354 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len; 1355 1356 memcpy(msg->payload + sizeof(struct pldm_request_update_req), 1357 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length); 1358 1359 return PLDM_SUCCESS; 1360 } 1361 1362 LIBPLDM_ABI_STABLE 1363 int decode_request_update_resp(const struct pldm_msg *msg, 1364 size_t payload_length, uint8_t *completion_code, 1365 uint16_t *fd_meta_data_len, 1366 uint8_t *fd_will_send_pkg_data) 1367 { 1368 if (msg == NULL || completion_code == NULL || 1369 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL || 1370 !payload_length) { 1371 return PLDM_ERROR_INVALID_DATA; 1372 } 1373 1374 *completion_code = msg->payload[0]; 1375 if (*completion_code != PLDM_SUCCESS) { 1376 return PLDM_SUCCESS; 1377 } 1378 1379 if (payload_length != sizeof(struct pldm_request_update_resp)) { 1380 return PLDM_ERROR_INVALID_LENGTH; 1381 } 1382 1383 struct pldm_request_update_resp *response = 1384 (struct pldm_request_update_resp *)msg->payload; 1385 1386 *fd_meta_data_len = le16toh(response->fd_meta_data_len); 1387 *fd_will_send_pkg_data = response->fd_will_send_pkg_data; 1388 1389 return PLDM_SUCCESS; 1390 } 1391 1392 LIBPLDM_ABI_STABLE 1393 int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag, 1394 uint16_t comp_classification, 1395 uint16_t comp_identifier, 1396 uint8_t comp_classification_index, 1397 uint32_t comp_comparison_stamp, 1398 uint8_t comp_ver_str_type, 1399 uint8_t comp_ver_str_len, 1400 const struct variable_field *comp_ver_str, 1401 struct pldm_msg *msg, size_t payload_length) 1402 { 1403 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) { 1404 return PLDM_ERROR_INVALID_DATA; 1405 } 1406 1407 if (payload_length != sizeof(struct pldm_pass_component_table_req) + 1408 comp_ver_str->length) { 1409 return PLDM_ERROR_INVALID_LENGTH; 1410 } 1411 1412 if ((comp_ver_str_len == 0) || 1413 (comp_ver_str_len != comp_ver_str->length)) { 1414 return PLDM_ERROR_INVALID_DATA; 1415 } 1416 1417 if (!is_transfer_flag_valid(transfer_flag)) { 1418 return PLDM_INVALID_TRANSFER_OPERATION_FLAG; 1419 } 1420 1421 if (!is_string_type_valid(comp_ver_str_type)) { 1422 return PLDM_ERROR_INVALID_DATA; 1423 } 1424 1425 struct pldm_header_info header = { 0 }; 1426 header.instance = instance_id; 1427 header.msg_type = PLDM_REQUEST; 1428 header.pldm_type = PLDM_FWUP; 1429 header.command = PLDM_PASS_COMPONENT_TABLE; 1430 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1431 if (rc) { 1432 return rc; 1433 } 1434 1435 struct pldm_pass_component_table_req *request = 1436 (struct pldm_pass_component_table_req *)msg->payload; 1437 1438 request->transfer_flag = transfer_flag; 1439 request->comp_classification = htole16(comp_classification); 1440 request->comp_identifier = htole16(comp_identifier); 1441 request->comp_classification_index = comp_classification_index; 1442 request->comp_comparison_stamp = htole32(comp_comparison_stamp); 1443 request->comp_ver_str_type = comp_ver_str_type; 1444 request->comp_ver_str_len = comp_ver_str_len; 1445 1446 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req), 1447 comp_ver_str->ptr, comp_ver_str->length); 1448 1449 return PLDM_SUCCESS; 1450 } 1451 1452 LIBPLDM_ABI_STABLE 1453 int decode_pass_component_table_resp(const struct pldm_msg *msg, 1454 const size_t payload_length, 1455 uint8_t *completion_code, 1456 uint8_t *comp_resp, 1457 uint8_t *comp_resp_code) 1458 { 1459 if (msg == NULL || completion_code == NULL || comp_resp == NULL || 1460 comp_resp_code == NULL || !payload_length) { 1461 return PLDM_ERROR_INVALID_DATA; 1462 } 1463 1464 *completion_code = msg->payload[0]; 1465 if (*completion_code != PLDM_SUCCESS) { 1466 return PLDM_SUCCESS; 1467 } 1468 1469 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) { 1470 return PLDM_ERROR_INVALID_LENGTH; 1471 } 1472 1473 struct pldm_pass_component_table_resp *response = 1474 (struct pldm_pass_component_table_resp *)msg->payload; 1475 1476 if (!is_comp_resp_valid(response->comp_resp)) { 1477 return PLDM_ERROR_INVALID_DATA; 1478 } 1479 1480 if (!is_comp_resp_code_valid(response->comp_resp_code)) { 1481 return PLDM_ERROR_INVALID_DATA; 1482 } 1483 1484 *comp_resp = response->comp_resp; 1485 *comp_resp_code = response->comp_resp_code; 1486 1487 return PLDM_SUCCESS; 1488 } 1489 1490 LIBPLDM_ABI_STABLE 1491 int encode_update_component_req( 1492 uint8_t instance_id, uint16_t comp_classification, 1493 uint16_t comp_identifier, uint8_t comp_classification_index, 1494 uint32_t comp_comparison_stamp, uint32_t comp_image_size, 1495 bitfield32_t update_option_flags, uint8_t comp_ver_str_type, 1496 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str, 1497 struct pldm_msg *msg, size_t payload_length) 1498 { 1499 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) { 1500 return PLDM_ERROR_INVALID_DATA; 1501 } 1502 1503 if (payload_length != 1504 sizeof(struct pldm_update_component_req) + comp_ver_str->length) { 1505 return PLDM_ERROR_INVALID_LENGTH; 1506 } 1507 1508 if (!comp_image_size) { 1509 return PLDM_ERROR_INVALID_DATA; 1510 } 1511 1512 if ((comp_ver_str_len == 0) || 1513 (comp_ver_str_len != comp_ver_str->length)) { 1514 return PLDM_ERROR_INVALID_DATA; 1515 } 1516 1517 if (!is_string_type_valid(comp_ver_str_type)) { 1518 return PLDM_ERROR_INVALID_DATA; 1519 } 1520 1521 struct pldm_header_info header = { 0 }; 1522 header.instance = instance_id; 1523 header.msg_type = PLDM_REQUEST; 1524 header.pldm_type = PLDM_FWUP; 1525 header.command = PLDM_UPDATE_COMPONENT; 1526 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1527 if (rc) { 1528 return rc; 1529 } 1530 1531 struct pldm_update_component_req *request = 1532 (struct pldm_update_component_req *)msg->payload; 1533 1534 request->comp_classification = htole16(comp_classification); 1535 request->comp_identifier = htole16(comp_identifier); 1536 request->comp_classification_index = comp_classification_index; 1537 request->comp_comparison_stamp = htole32(comp_comparison_stamp); 1538 request->comp_image_size = htole32(comp_image_size); 1539 request->update_option_flags.value = htole32(update_option_flags.value); 1540 request->comp_ver_str_type = comp_ver_str_type; 1541 request->comp_ver_str_len = comp_ver_str_len; 1542 1543 memcpy(msg->payload + sizeof(struct pldm_update_component_req), 1544 comp_ver_str->ptr, comp_ver_str->length); 1545 1546 return PLDM_SUCCESS; 1547 } 1548 1549 LIBPLDM_ABI_STABLE 1550 int decode_update_component_resp(const struct pldm_msg *msg, 1551 size_t payload_length, 1552 uint8_t *completion_code, 1553 uint8_t *comp_compatibility_resp, 1554 uint8_t *comp_compatibility_resp_code, 1555 bitfield32_t *update_option_flags_enabled, 1556 uint16_t *time_before_req_fw_data) 1557 { 1558 if (msg == NULL || completion_code == NULL || 1559 comp_compatibility_resp == NULL || 1560 comp_compatibility_resp_code == NULL || 1561 update_option_flags_enabled == NULL || 1562 time_before_req_fw_data == NULL || !payload_length) { 1563 return PLDM_ERROR_INVALID_DATA; 1564 } 1565 1566 *completion_code = msg->payload[0]; 1567 if (*completion_code != PLDM_SUCCESS) { 1568 return PLDM_SUCCESS; 1569 } 1570 1571 if (payload_length != sizeof(struct pldm_update_component_resp)) { 1572 return PLDM_ERROR_INVALID_LENGTH; 1573 } 1574 1575 struct pldm_update_component_resp *response = 1576 (struct pldm_update_component_resp *)msg->payload; 1577 1578 if (!is_comp_compatibility_resp_valid( 1579 response->comp_compatibility_resp)) { 1580 return PLDM_ERROR_INVALID_DATA; 1581 } 1582 1583 if (!is_comp_compatibility_resp_code_valid( 1584 response->comp_compatibility_resp_code)) { 1585 return PLDM_ERROR_INVALID_DATA; 1586 } 1587 1588 *comp_compatibility_resp = response->comp_compatibility_resp; 1589 *comp_compatibility_resp_code = response->comp_compatibility_resp_code; 1590 update_option_flags_enabled->value = 1591 le32toh(response->update_option_flags_enabled.value); 1592 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data); 1593 1594 return PLDM_SUCCESS; 1595 } 1596 1597 LIBPLDM_ABI_STABLE 1598 int decode_request_firmware_data_req(const struct pldm_msg *msg, 1599 size_t payload_length, uint32_t *offset, 1600 uint32_t *length) 1601 { 1602 if (msg == NULL || offset == NULL || length == NULL) { 1603 return PLDM_ERROR_INVALID_DATA; 1604 } 1605 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) { 1606 return PLDM_ERROR_INVALID_LENGTH; 1607 } 1608 struct pldm_request_firmware_data_req *request = 1609 (struct pldm_request_firmware_data_req *)msg->payload; 1610 *offset = le32toh(request->offset); 1611 *length = le32toh(request->length); 1612 1613 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) { 1614 return PLDM_FWUP_INVALID_TRANSFER_LENGTH; 1615 } 1616 1617 return PLDM_SUCCESS; 1618 } 1619 1620 LIBPLDM_ABI_STABLE 1621 int encode_request_firmware_data_resp(uint8_t instance_id, 1622 uint8_t completion_code, 1623 struct pldm_msg *msg, 1624 size_t payload_length) 1625 { 1626 if (msg == NULL || !payload_length) { 1627 return PLDM_ERROR_INVALID_DATA; 1628 } 1629 1630 struct pldm_header_info header = { 0 }; 1631 header.instance = instance_id; 1632 header.msg_type = PLDM_RESPONSE; 1633 header.pldm_type = PLDM_FWUP; 1634 header.command = PLDM_REQUEST_FIRMWARE_DATA; 1635 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1636 if (rc) { 1637 return rc; 1638 } 1639 1640 msg->payload[0] = completion_code; 1641 1642 return PLDM_SUCCESS; 1643 } 1644 1645 LIBPLDM_ABI_STABLE 1646 int decode_transfer_complete_req(const struct pldm_msg *msg, 1647 size_t payload_length, 1648 uint8_t *transfer_result) 1649 { 1650 if (msg == NULL || transfer_result == NULL) { 1651 return PLDM_ERROR_INVALID_DATA; 1652 } 1653 1654 if (payload_length != sizeof(*transfer_result)) { 1655 return PLDM_ERROR_INVALID_LENGTH; 1656 } 1657 1658 *transfer_result = msg->payload[0]; 1659 return PLDM_SUCCESS; 1660 } 1661 1662 LIBPLDM_ABI_STABLE 1663 int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code, 1664 struct pldm_msg *msg, size_t payload_length) 1665 { 1666 if (msg == NULL) { 1667 return PLDM_ERROR_INVALID_DATA; 1668 } 1669 1670 if (payload_length != sizeof(completion_code)) { 1671 return PLDM_ERROR_INVALID_LENGTH; 1672 } 1673 1674 struct pldm_header_info header = { 0 }; 1675 header.instance = instance_id; 1676 header.msg_type = PLDM_RESPONSE; 1677 header.pldm_type = PLDM_FWUP; 1678 header.command = PLDM_TRANSFER_COMPLETE; 1679 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1680 if (rc) { 1681 return rc; 1682 } 1683 1684 msg->payload[0] = completion_code; 1685 1686 return PLDM_SUCCESS; 1687 } 1688 1689 LIBPLDM_ABI_STABLE 1690 int decode_verify_complete_req(const struct pldm_msg *msg, 1691 size_t payload_length, uint8_t *verify_result) 1692 { 1693 if (msg == NULL || verify_result == NULL) { 1694 return PLDM_ERROR_INVALID_DATA; 1695 } 1696 1697 if (payload_length != sizeof(*verify_result)) { 1698 return PLDM_ERROR_INVALID_LENGTH; 1699 } 1700 1701 *verify_result = msg->payload[0]; 1702 return PLDM_SUCCESS; 1703 } 1704 1705 LIBPLDM_ABI_STABLE 1706 int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code, 1707 struct pldm_msg *msg, size_t payload_length) 1708 { 1709 if (msg == NULL) { 1710 return PLDM_ERROR_INVALID_DATA; 1711 } 1712 1713 if (payload_length != sizeof(completion_code)) { 1714 return PLDM_ERROR_INVALID_LENGTH; 1715 } 1716 1717 struct pldm_header_info header = { 0 }; 1718 header.instance = instance_id; 1719 header.msg_type = PLDM_RESPONSE; 1720 header.pldm_type = PLDM_FWUP; 1721 header.command = PLDM_VERIFY_COMPLETE; 1722 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1723 if (rc) { 1724 return rc; 1725 } 1726 1727 msg->payload[0] = completion_code; 1728 1729 return PLDM_SUCCESS; 1730 } 1731 1732 LIBPLDM_ABI_STABLE 1733 int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length, 1734 uint8_t *apply_result, 1735 bitfield16_t *comp_activation_methods_modification) 1736 { 1737 if (msg == NULL || apply_result == NULL || 1738 comp_activation_methods_modification == NULL) { 1739 return PLDM_ERROR_INVALID_DATA; 1740 } 1741 1742 if (payload_length != sizeof(struct pldm_apply_complete_req)) { 1743 return PLDM_ERROR_INVALID_LENGTH; 1744 } 1745 1746 struct pldm_apply_complete_req *request = 1747 (struct pldm_apply_complete_req *)msg->payload; 1748 1749 *apply_result = request->apply_result; 1750 comp_activation_methods_modification->value = 1751 le16toh(request->comp_activation_methods_modification.value); 1752 1753 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) && 1754 comp_activation_methods_modification->value) { 1755 return PLDM_ERROR_INVALID_DATA; 1756 } 1757 1758 return PLDM_SUCCESS; 1759 } 1760 1761 LIBPLDM_ABI_STABLE 1762 int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code, 1763 struct pldm_msg *msg, size_t payload_length) 1764 { 1765 if (msg == NULL) { 1766 return PLDM_ERROR_INVALID_DATA; 1767 } 1768 1769 if (payload_length != sizeof(completion_code)) { 1770 return PLDM_ERROR_INVALID_LENGTH; 1771 } 1772 1773 struct pldm_header_info header = { 0 }; 1774 header.instance = instance_id; 1775 header.msg_type = PLDM_RESPONSE; 1776 header.pldm_type = PLDM_FWUP; 1777 header.command = PLDM_APPLY_COMPLETE; 1778 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1779 if (rc) { 1780 return rc; 1781 } 1782 1783 msg->payload[0] = completion_code; 1784 1785 return PLDM_SUCCESS; 1786 } 1787 1788 LIBPLDM_ABI_STABLE 1789 int encode_activate_firmware_req(uint8_t instance_id, 1790 bool8_t self_contained_activation_req, 1791 struct pldm_msg *msg, size_t payload_length) 1792 { 1793 if (msg == NULL) { 1794 return PLDM_ERROR_INVALID_DATA; 1795 } 1796 1797 if (payload_length != sizeof(struct pldm_activate_firmware_req)) { 1798 return PLDM_ERROR_INVALID_LENGTH; 1799 } 1800 1801 if (!is_self_contained_activation_req_valid( 1802 self_contained_activation_req)) { 1803 return PLDM_ERROR_INVALID_DATA; 1804 } 1805 1806 struct pldm_header_info header = { 0 }; 1807 header.instance = instance_id; 1808 header.msg_type = PLDM_REQUEST; 1809 header.pldm_type = PLDM_FWUP; 1810 header.command = PLDM_ACTIVATE_FIRMWARE; 1811 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1812 if (rc) { 1813 return rc; 1814 } 1815 1816 struct pldm_activate_firmware_req *request = 1817 (struct pldm_activate_firmware_req *)msg->payload; 1818 1819 request->self_contained_activation_req = self_contained_activation_req; 1820 1821 return PLDM_SUCCESS; 1822 } 1823 1824 LIBPLDM_ABI_STABLE 1825 int decode_activate_firmware_resp(const struct pldm_msg *msg, 1826 size_t payload_length, 1827 uint8_t *completion_code, 1828 uint16_t *estimated_time_activation) 1829 { 1830 if (msg == NULL || completion_code == NULL || 1831 estimated_time_activation == NULL || !payload_length) { 1832 return PLDM_ERROR_INVALID_DATA; 1833 } 1834 1835 *completion_code = msg->payload[0]; 1836 if (*completion_code != PLDM_SUCCESS) { 1837 return PLDM_SUCCESS; 1838 } 1839 1840 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) { 1841 return PLDM_ERROR_INVALID_LENGTH; 1842 } 1843 1844 struct pldm_activate_firmware_resp *response = 1845 (struct pldm_activate_firmware_resp *)msg->payload; 1846 1847 *estimated_time_activation = 1848 le16toh(response->estimated_time_activation); 1849 1850 return PLDM_SUCCESS; 1851 } 1852 1853 LIBPLDM_ABI_STABLE 1854 int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg, 1855 size_t payload_length) 1856 { 1857 if (msg == NULL) { 1858 return PLDM_ERROR_INVALID_DATA; 1859 } 1860 1861 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) { 1862 return PLDM_ERROR_INVALID_LENGTH; 1863 } 1864 1865 struct pldm_header_info header = { 0 }; 1866 header.instance = instance_id; 1867 header.msg_type = PLDM_REQUEST; 1868 header.pldm_type = PLDM_FWUP; 1869 header.command = PLDM_GET_STATUS; 1870 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1871 if (rc) { 1872 return rc; 1873 } 1874 1875 return PLDM_SUCCESS; 1876 } 1877 1878 LIBPLDM_ABI_STABLE 1879 int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length, 1880 uint8_t *completion_code, uint8_t *current_state, 1881 uint8_t *previous_state, uint8_t *aux_state, 1882 uint8_t *aux_state_status, uint8_t *progress_percent, 1883 uint8_t *reason_code, 1884 bitfield32_t *update_option_flags_enabled) 1885 { 1886 if (msg == NULL || completion_code == NULL || current_state == NULL || 1887 previous_state == NULL || aux_state == NULL || 1888 aux_state_status == NULL || progress_percent == NULL || 1889 reason_code == NULL || update_option_flags_enabled == NULL || 1890 !payload_length) { 1891 return PLDM_ERROR_INVALID_DATA; 1892 } 1893 1894 *completion_code = msg->payload[0]; 1895 if (*completion_code != PLDM_SUCCESS) { 1896 return PLDM_SUCCESS; 1897 } 1898 1899 if (payload_length != sizeof(struct pldm_get_status_resp)) { 1900 return PLDM_ERROR_INVALID_LENGTH; 1901 } 1902 struct pldm_get_status_resp *response = 1903 (struct pldm_get_status_resp *)msg->payload; 1904 1905 if (!is_state_valid(response->current_state)) { 1906 return PLDM_ERROR_INVALID_DATA; 1907 } 1908 if (!is_state_valid(response->previous_state)) { 1909 return PLDM_ERROR_INVALID_DATA; 1910 } 1911 if (!is_aux_state_valid(response->aux_state)) { 1912 return PLDM_ERROR_INVALID_DATA; 1913 } 1914 if (!is_aux_state_status_valid(response->aux_state_status)) { 1915 return PLDM_ERROR_INVALID_DATA; 1916 } 1917 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) { 1918 return PLDM_ERROR_INVALID_DATA; 1919 } 1920 if (!is_reason_code_valid(response->reason_code)) { 1921 return PLDM_ERROR_INVALID_DATA; 1922 } 1923 1924 if ((response->current_state == PLDM_FD_STATE_IDLE) || 1925 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) || 1926 (response->current_state == PLDM_FD_STATE_READY_XFER)) { 1927 if (response->aux_state != 1928 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) { 1929 return PLDM_ERROR_INVALID_DATA; 1930 } 1931 } 1932 1933 *current_state = response->current_state; 1934 *previous_state = response->previous_state; 1935 *aux_state = response->aux_state; 1936 *aux_state_status = response->aux_state_status; 1937 *progress_percent = response->progress_percent; 1938 *reason_code = response->reason_code; 1939 update_option_flags_enabled->value = 1940 le32toh(response->update_option_flags_enabled.value); 1941 1942 return PLDM_SUCCESS; 1943 } 1944 1945 LIBPLDM_ABI_STABLE 1946 int encode_cancel_update_component_req(uint8_t instance_id, 1947 struct pldm_msg *msg, 1948 size_t payload_length) 1949 { 1950 if (msg == NULL) { 1951 return PLDM_ERROR_INVALID_DATA; 1952 } 1953 1954 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) { 1955 return PLDM_ERROR_INVALID_LENGTH; 1956 } 1957 1958 struct pldm_header_info header = { 0 }; 1959 header.instance = instance_id; 1960 header.msg_type = PLDM_REQUEST; 1961 header.pldm_type = PLDM_FWUP; 1962 header.command = PLDM_CANCEL_UPDATE_COMPONENT; 1963 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1964 if (rc) { 1965 return rc; 1966 } 1967 1968 return PLDM_SUCCESS; 1969 } 1970 1971 LIBPLDM_ABI_STABLE 1972 int decode_cancel_update_component_resp(const struct pldm_msg *msg, 1973 size_t payload_length, 1974 uint8_t *completion_code) 1975 { 1976 if (msg == NULL || completion_code == NULL) { 1977 return PLDM_ERROR_INVALID_DATA; 1978 } 1979 1980 if (payload_length != sizeof(*completion_code)) { 1981 return PLDM_ERROR_INVALID_LENGTH; 1982 } 1983 1984 *completion_code = msg->payload[0]; 1985 return PLDM_SUCCESS; 1986 } 1987 1988 LIBPLDM_ABI_STABLE 1989 int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg, 1990 size_t payload_length) 1991 { 1992 if (msg == NULL) { 1993 return PLDM_ERROR_INVALID_DATA; 1994 } 1995 1996 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) { 1997 return PLDM_ERROR_INVALID_LENGTH; 1998 } 1999 2000 struct pldm_header_info header = { 0 }; 2001 header.instance = instance_id; 2002 header.msg_type = PLDM_REQUEST; 2003 header.pldm_type = PLDM_FWUP; 2004 header.command = PLDM_CANCEL_UPDATE; 2005 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2006 if (rc) { 2007 return rc; 2008 } 2009 2010 return PLDM_SUCCESS; 2011 } 2012 2013 LIBPLDM_ABI_STABLE 2014 int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length, 2015 uint8_t *completion_code, 2016 bool8_t *non_functioning_component_indication, 2017 bitfield64_t *non_functioning_component_bitmap) 2018 { 2019 if (msg == NULL || completion_code == NULL || 2020 non_functioning_component_indication == NULL || 2021 non_functioning_component_bitmap == NULL || !payload_length) { 2022 return PLDM_ERROR_INVALID_DATA; 2023 } 2024 2025 *completion_code = msg->payload[0]; 2026 if (*completion_code != PLDM_SUCCESS) { 2027 return PLDM_SUCCESS; 2028 } 2029 2030 if (payload_length != sizeof(struct pldm_cancel_update_resp)) { 2031 return PLDM_ERROR_INVALID_LENGTH; 2032 } 2033 struct pldm_cancel_update_resp *response = 2034 (struct pldm_cancel_update_resp *)msg->payload; 2035 2036 if (!is_non_functioning_component_indication_valid( 2037 response->non_functioning_component_indication)) { 2038 return PLDM_ERROR_INVALID_DATA; 2039 } 2040 2041 *non_functioning_component_indication = 2042 response->non_functioning_component_indication; 2043 2044 if (*non_functioning_component_indication) { 2045 non_functioning_component_bitmap->value = 2046 le64toh(response->non_functioning_component_bitmap); 2047 } 2048 2049 return PLDM_SUCCESS; 2050 } 2051