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 PLDM_ERROR_INVALID_DATA; 923 } 924 925 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 926 PLDM_QUERY_DOWNSTREAM_DEVICES, msg); 927 } 928 929 LIBPLDM_ABI_TESTING 930 int decode_query_downstream_devices_resp( 931 const struct pldm_msg *msg, size_t payload_length, 932 struct pldm_query_downstream_devices_resp *resp_data) 933 { 934 struct pldm_msgbuf _buf; 935 struct pldm_msgbuf *buf = &_buf; 936 int rc; 937 938 if (msg == NULL || resp_data == NULL || !payload_length) { 939 return PLDM_ERROR_INVALID_DATA; 940 } 941 942 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 943 msg->payload, payload_length); 944 if (rc) { 945 return rc; 946 } 947 948 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 949 if (rc) { 950 return pldm_xlate_errno(rc); 951 } 952 if (PLDM_SUCCESS != resp_data->completion_code) { 953 // Return the CC directly without decoding the rest of the payload 954 return PLDM_SUCCESS; 955 } 956 957 if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) { 958 return PLDM_ERROR_INVALID_LENGTH; 959 } 960 961 rc = pldm_msgbuf_extract(buf, 962 resp_data->downstream_device_update_supported); 963 if (rc) { 964 return pldm_xlate_errno(rc); 965 } 966 967 if (!is_downstream_device_update_support_valid( 968 resp_data->downstream_device_update_supported)) { 969 return PLDM_ERROR_INVALID_DATA; 970 } 971 972 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices); 973 pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices); 974 pldm_msgbuf_extract(buf, resp_data->capabilities.value); 975 976 rc = pldm_msgbuf_destroy_consumed(buf); 977 if (rc) { 978 pldm_xlate_errno(rc); 979 } 980 981 return PLDM_SUCCESS; 982 } 983 984 LIBPLDM_ABI_TESTING 985 int encode_query_downstream_identifiers_req( 986 uint8_t instance_id, uint32_t data_transfer_handle, 987 enum transfer_op_flag transfer_operation_flag, struct pldm_msg *msg, 988 size_t payload_length) 989 { 990 struct pldm_msgbuf _buf; 991 struct pldm_msgbuf *buf = &_buf; 992 int rc; 993 994 if (msg == NULL) { 995 return PLDM_ERROR_INVALID_DATA; 996 } 997 998 if (!is_transfer_operation_flag_valid(transfer_operation_flag)) { 999 return PLDM_INVALID_TRANSFER_OPERATION_FLAG; 1000 } 1001 1002 struct pldm_header_info header = { 0 }; 1003 header.instance = instance_id; 1004 header.msg_type = PLDM_REQUEST; 1005 header.pldm_type = PLDM_FWUP; 1006 header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS; 1007 rc = pack_pldm_header(&header, &(msg->hdr)); 1008 if (rc) { 1009 return rc; 1010 } 1011 1012 rc = pldm_msgbuf_init_errno(buf, 1013 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES, 1014 msg->payload, payload_length); 1015 if (rc) { 1016 return pldm_xlate_errno(rc); 1017 } 1018 1019 pldm_msgbuf_insert(buf, data_transfer_handle); 1020 // Data correctness has been verified, cast it to 1-byte data directly. 1021 pldm_msgbuf_insert(buf, (uint8_t)transfer_operation_flag); 1022 1023 rc = pldm_msgbuf_destroy(buf); 1024 if (rc) { 1025 return pldm_xlate_errno(rc); 1026 } 1027 1028 return PLDM_SUCCESS; 1029 } 1030 1031 LIBPLDM_ABI_TESTING 1032 int decode_query_downstream_identifiers_resp( 1033 const struct pldm_msg *msg, size_t payload_length, 1034 struct pldm_query_downstream_identifiers_resp *resp_data, 1035 struct pldm_downstream_device_iter *iter) 1036 { 1037 struct pldm_msgbuf _buf; 1038 struct pldm_msgbuf *buf = &_buf; 1039 void *remaining = NULL; 1040 int rc = PLDM_ERROR; 1041 1042 if (msg == NULL || resp_data == NULL || iter == NULL || 1043 !payload_length) { 1044 return PLDM_ERROR_INVALID_DATA; 1045 } 1046 1047 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 1048 msg->payload, payload_length); 1049 if (rc) { 1050 return pldm_xlate_errno(rc); 1051 } 1052 1053 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 1054 if (rc) { 1055 return pldm_xlate_errno(rc); 1056 } 1057 if (PLDM_SUCCESS != resp_data->completion_code) { 1058 return PLDM_SUCCESS; 1059 } 1060 1061 if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) { 1062 return PLDM_ERROR_INVALID_LENGTH; 1063 } 1064 1065 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle); 1066 pldm_msgbuf_extract(buf, resp_data->transfer_flag); 1067 1068 rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length); 1069 if (rc) { 1070 return pldm_xlate_errno(rc); 1071 } 1072 1073 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices); 1074 rc = pldm_msgbuf_span_required( 1075 buf, resp_data->downstream_devices_length, &remaining); 1076 if (rc) { 1077 return pldm_xlate_errno(rc); 1078 } 1079 1080 rc = pldm_msgbuf_destroy(buf); 1081 if (rc) { 1082 return pldm_xlate_errno(rc); 1083 } 1084 1085 iter->field.ptr = remaining; 1086 iter->field.length = resp_data->downstream_devices_length; 1087 iter->devs = resp_data->number_of_downstream_devices; 1088 1089 return PLDM_SUCCESS; 1090 } 1091 1092 LIBPLDM_ABI_TESTING 1093 int decode_pldm_downstream_device_from_iter( 1094 struct pldm_downstream_device_iter *iter, 1095 struct pldm_downstream_device *dev) 1096 { 1097 struct pldm_msgbuf _buf; 1098 struct pldm_msgbuf *buf = &_buf; 1099 int rc; 1100 1101 if (!iter || !dev) { 1102 return -EINVAL; 1103 } 1104 1105 rc = pldm_msgbuf_init_errno(buf, 3, iter->field.ptr, 1106 iter->field.length); 1107 if (rc) { 1108 return rc; 1109 } 1110 1111 pldm_msgbuf_extract(buf, dev->downstream_device_index); 1112 pldm_msgbuf_extract(buf, dev->downstream_descriptor_count); 1113 iter->field.ptr = NULL; 1114 pldm_msgbuf_span_remaining(buf, (void **)&iter->field.ptr, 1115 &iter->field.length); 1116 1117 return pldm_msgbuf_destroy(buf); 1118 } 1119 1120 LIBPLDM_ABI_TESTING 1121 int encode_get_downstream_firmware_params_req( 1122 uint8_t instance_id, uint32_t data_transfer_handle, 1123 enum transfer_op_flag transfer_operation_flag, struct pldm_msg *msg, 1124 size_t payload_length) 1125 { 1126 struct pldm_msgbuf _buf; 1127 struct pldm_msgbuf *buf = &_buf; 1128 int rc; 1129 1130 if (msg == NULL) { 1131 return -EINVAL; 1132 } 1133 1134 rc = pldm_msgbuf_init_errno( 1135 buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_REQ_BYTES, 1136 msg->payload, payload_length); 1137 if (rc < 0) { 1138 return rc; 1139 } 1140 1141 if (!is_transfer_operation_flag_valid(transfer_operation_flag)) { 1142 return -EBADMSG; 1143 } 1144 1145 struct pldm_header_info header = { 0 }; 1146 header.instance = instance_id; 1147 header.msg_type = PLDM_REQUEST; 1148 header.pldm_type = PLDM_FWUP; 1149 header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS; 1150 rc = pack_pldm_header_errno(&header, &msg->hdr); 1151 if (rc < 0) { 1152 return rc; 1153 } 1154 1155 pldm_msgbuf_insert(buf, data_transfer_handle); 1156 // Data correctness has been verified, cast it to 1-byte data directly. 1157 pldm_msgbuf_insert(buf, (uint8_t)transfer_operation_flag); 1158 1159 return pldm_msgbuf_destroy(buf); 1160 } 1161 1162 LIBPLDM_ABI_TESTING 1163 int decode_get_downstream_firmware_params_resp( 1164 const struct pldm_msg *msg, size_t payload_length, 1165 struct pldm_get_downstream_firmware_params_resp *resp_data, 1166 struct variable_field *downstream_device_param_table) 1167 { 1168 struct pldm_msgbuf _buf; 1169 struct pldm_msgbuf *buf = &_buf; 1170 int rc; 1171 1172 if (msg == NULL || resp_data == NULL || 1173 downstream_device_param_table == NULL) { 1174 return -EINVAL; 1175 } 1176 1177 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 1178 msg->payload, payload_length); 1179 if (rc < 0) { 1180 return rc; 1181 } 1182 1183 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 1184 if (rc < 0) { 1185 return rc; 1186 } 1187 if (PLDM_SUCCESS != resp_data->completion_code) { 1188 return 0; 1189 } 1190 1191 if (payload_length < PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMS_RESP_MIN_LEN) { 1192 return -EBADMSG; 1193 } 1194 1195 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle); 1196 pldm_msgbuf_extract(buf, resp_data->transfer_flag); 1197 pldm_msgbuf_extract(buf, 1198 resp_data->fdp_capabilities_during_update.value); 1199 pldm_msgbuf_extract(buf, resp_data->downstream_device_count); 1200 1201 return pldm_msgbuf_span_remaining( 1202 buf, (void **)&downstream_device_param_table->ptr, 1203 &downstream_device_param_table->length); 1204 } 1205 1206 LIBPLDM_ABI_TESTING 1207 int decode_downstream_device_parameter_table_entry( 1208 struct variable_field *data, 1209 struct pldm_downstream_device_parameter_entry *entry, 1210 struct variable_field *versions) 1211 { 1212 struct pldm_msgbuf _buf; 1213 struct pldm_msgbuf *buf = &_buf; 1214 void *cursor = NULL; 1215 size_t remaining; 1216 int rc; 1217 1218 if (data == NULL || entry == NULL || versions == NULL) { 1219 return -EINVAL; 1220 } 1221 1222 rc = pldm_msgbuf_init_errno( 1223 buf, PLDM_DOWNSTREAM_DEVICE_PARAMETER_ENTRY_MIN_LEN, data->ptr, 1224 data->length); 1225 if (rc < 0) { 1226 return rc; 1227 } 1228 1229 pldm_msgbuf_extract(buf, entry->downstream_device_index); 1230 pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp); 1231 pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type); 1232 rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len); 1233 if (rc < 0) { 1234 return rc; 1235 } 1236 rc = pldm_msgbuf_extract_array(buf, 1237 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 1238 entry->active_comp_release_date, 1239 sizeof(entry->active_comp_release_date)); 1240 if (rc < 0) { 1241 return rc; 1242 } 1243 1244 // Fill the last byte with NULL character 1245 entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] = 1246 '\0'; 1247 1248 pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp); 1249 pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type); 1250 rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len); 1251 if (rc < 0) { 1252 return rc; 1253 } 1254 1255 rc = pldm_msgbuf_extract_array( 1256 buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 1257 entry->pending_comp_release_date, 1258 sizeof(entry->pending_comp_release_date)); 1259 if (rc < 0) { 1260 return rc; 1261 } 1262 1263 // Fill the last byte with NULL character 1264 entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] = 1265 '\0'; 1266 1267 pldm_msgbuf_extract(buf, entry->comp_activation_methods.value); 1268 pldm_msgbuf_extract(buf, entry->capabilities_during_update.value); 1269 const size_t versions_len = entry->active_comp_ver_str_len + 1270 entry->pending_comp_ver_str_len; 1271 rc = pldm_msgbuf_span_required(buf, versions_len, 1272 (void **)&versions->ptr); 1273 if (rc < 0) { 1274 return rc; 1275 } 1276 versions->length = versions_len; 1277 1278 rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining); 1279 if (rc < 0) { 1280 return rc; 1281 } 1282 1283 data->ptr = cursor; 1284 data->length = remaining; 1285 1286 return 0; 1287 } 1288 1289 LIBPLDM_ABI_TESTING 1290 int decode_downstream_device_parameter_table_entry_versions( 1291 const struct variable_field *versions, 1292 struct pldm_downstream_device_parameter_entry *entry, char *active, 1293 size_t active_len, char *pending, size_t pending_len) 1294 { 1295 struct pldm_msgbuf _buf; 1296 struct pldm_msgbuf *buf = &_buf; 1297 int rc; 1298 1299 if (versions == NULL || versions->ptr == NULL || !versions->length || 1300 entry == NULL || active == NULL || pending == NULL) { 1301 return -EINVAL; 1302 } 1303 1304 if (!active_len || active_len - 1 < entry->active_comp_ver_str_len) { 1305 return -EOVERFLOW; 1306 } 1307 1308 if (!pending_len || pending_len - 1 < entry->pending_comp_ver_str_len) { 1309 return -EOVERFLOW; 1310 } 1311 1312 /* This API should be called after decode_downstream_device_parameter_table_entry 1313 * has successfully decoded the entry, assume the entry data is valid here. 1314 */ 1315 const size_t versions_len = entry->active_comp_ver_str_len + 1316 entry->pending_comp_ver_str_len; 1317 rc = pldm_msgbuf_init_errno(buf, versions_len, versions->ptr, 1318 versions->length); 1319 if (rc < 0) { 1320 return rc; 1321 } 1322 1323 rc = pldm_msgbuf_extract_array(buf, entry->active_comp_ver_str_len, 1324 active, active_len); 1325 if (rc < 0) { 1326 return rc; 1327 } 1328 1329 active[entry->active_comp_ver_str_len] = '\0'; 1330 rc = pldm_msgbuf_extract_array(buf, entry->pending_comp_ver_str_len, 1331 pending, pending_len); 1332 if (rc < 0) { 1333 return rc; 1334 } 1335 1336 pending[entry->pending_comp_ver_str_len] = '\0'; 1337 1338 entry->active_comp_ver_str = active; 1339 entry->pending_comp_ver_str = pending; 1340 1341 return pldm_msgbuf_destroy_consumed(buf); 1342 } 1343 1344 LIBPLDM_ABI_STABLE 1345 int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size, 1346 uint16_t num_of_comp, 1347 uint8_t max_outstanding_transfer_req, 1348 uint16_t pkg_data_len, 1349 uint8_t comp_image_set_ver_str_type, 1350 uint8_t comp_image_set_ver_str_len, 1351 const struct variable_field *comp_img_set_ver_str, 1352 struct pldm_msg *msg, size_t payload_length) 1353 { 1354 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL || 1355 msg == NULL) { 1356 return PLDM_ERROR_INVALID_DATA; 1357 } 1358 1359 if (payload_length != sizeof(struct pldm_request_update_req) + 1360 comp_img_set_ver_str->length) { 1361 return PLDM_ERROR_INVALID_LENGTH; 1362 } 1363 1364 if ((comp_image_set_ver_str_len == 0) || 1365 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) { 1366 return PLDM_ERROR_INVALID_DATA; 1367 } 1368 1369 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) || 1370 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) { 1371 return PLDM_ERROR_INVALID_DATA; 1372 } 1373 1374 if (!is_string_type_valid(comp_image_set_ver_str_type)) { 1375 return PLDM_ERROR_INVALID_DATA; 1376 } 1377 1378 struct pldm_header_info header = { 0 }; 1379 header.instance = instance_id; 1380 header.msg_type = PLDM_REQUEST; 1381 header.pldm_type = PLDM_FWUP; 1382 header.command = PLDM_REQUEST_UPDATE; 1383 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1384 if (rc) { 1385 return rc; 1386 } 1387 1388 struct pldm_request_update_req *request = 1389 (struct pldm_request_update_req *)msg->payload; 1390 1391 request->max_transfer_size = htole32(max_transfer_size); 1392 request->num_of_comp = htole16(num_of_comp); 1393 request->max_outstanding_transfer_req = max_outstanding_transfer_req; 1394 request->pkg_data_len = htole16(pkg_data_len); 1395 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type; 1396 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len; 1397 1398 memcpy(msg->payload + sizeof(struct pldm_request_update_req), 1399 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length); 1400 1401 return PLDM_SUCCESS; 1402 } 1403 1404 LIBPLDM_ABI_STABLE 1405 int decode_request_update_resp(const struct pldm_msg *msg, 1406 size_t payload_length, uint8_t *completion_code, 1407 uint16_t *fd_meta_data_len, 1408 uint8_t *fd_will_send_pkg_data) 1409 { 1410 if (msg == NULL || completion_code == NULL || 1411 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL || 1412 !payload_length) { 1413 return PLDM_ERROR_INVALID_DATA; 1414 } 1415 1416 *completion_code = msg->payload[0]; 1417 if (*completion_code != PLDM_SUCCESS) { 1418 return PLDM_SUCCESS; 1419 } 1420 1421 if (payload_length != sizeof(struct pldm_request_update_resp)) { 1422 return PLDM_ERROR_INVALID_LENGTH; 1423 } 1424 1425 struct pldm_request_update_resp *response = 1426 (struct pldm_request_update_resp *)msg->payload; 1427 1428 *fd_meta_data_len = le16toh(response->fd_meta_data_len); 1429 *fd_will_send_pkg_data = response->fd_will_send_pkg_data; 1430 1431 return PLDM_SUCCESS; 1432 } 1433 1434 LIBPLDM_ABI_STABLE 1435 int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag, 1436 uint16_t comp_classification, 1437 uint16_t comp_identifier, 1438 uint8_t comp_classification_index, 1439 uint32_t comp_comparison_stamp, 1440 uint8_t comp_ver_str_type, 1441 uint8_t comp_ver_str_len, 1442 const struct variable_field *comp_ver_str, 1443 struct pldm_msg *msg, size_t payload_length) 1444 { 1445 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) { 1446 return PLDM_ERROR_INVALID_DATA; 1447 } 1448 1449 if (payload_length != sizeof(struct pldm_pass_component_table_req) + 1450 comp_ver_str->length) { 1451 return PLDM_ERROR_INVALID_LENGTH; 1452 } 1453 1454 if ((comp_ver_str_len == 0) || 1455 (comp_ver_str_len != comp_ver_str->length)) { 1456 return PLDM_ERROR_INVALID_DATA; 1457 } 1458 1459 if (!is_transfer_flag_valid(transfer_flag)) { 1460 return PLDM_INVALID_TRANSFER_OPERATION_FLAG; 1461 } 1462 1463 if (!is_string_type_valid(comp_ver_str_type)) { 1464 return PLDM_ERROR_INVALID_DATA; 1465 } 1466 1467 struct pldm_header_info header = { 0 }; 1468 header.instance = instance_id; 1469 header.msg_type = PLDM_REQUEST; 1470 header.pldm_type = PLDM_FWUP; 1471 header.command = PLDM_PASS_COMPONENT_TABLE; 1472 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1473 if (rc) { 1474 return rc; 1475 } 1476 1477 struct pldm_pass_component_table_req *request = 1478 (struct pldm_pass_component_table_req *)msg->payload; 1479 1480 request->transfer_flag = transfer_flag; 1481 request->comp_classification = htole16(comp_classification); 1482 request->comp_identifier = htole16(comp_identifier); 1483 request->comp_classification_index = comp_classification_index; 1484 request->comp_comparison_stamp = htole32(comp_comparison_stamp); 1485 request->comp_ver_str_type = comp_ver_str_type; 1486 request->comp_ver_str_len = comp_ver_str_len; 1487 1488 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req), 1489 comp_ver_str->ptr, comp_ver_str->length); 1490 1491 return PLDM_SUCCESS; 1492 } 1493 1494 LIBPLDM_ABI_STABLE 1495 int decode_pass_component_table_resp(const struct pldm_msg *msg, 1496 const size_t payload_length, 1497 uint8_t *completion_code, 1498 uint8_t *comp_resp, 1499 uint8_t *comp_resp_code) 1500 { 1501 if (msg == NULL || completion_code == NULL || comp_resp == NULL || 1502 comp_resp_code == NULL || !payload_length) { 1503 return PLDM_ERROR_INVALID_DATA; 1504 } 1505 1506 *completion_code = msg->payload[0]; 1507 if (*completion_code != PLDM_SUCCESS) { 1508 return PLDM_SUCCESS; 1509 } 1510 1511 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) { 1512 return PLDM_ERROR_INVALID_LENGTH; 1513 } 1514 1515 struct pldm_pass_component_table_resp *response = 1516 (struct pldm_pass_component_table_resp *)msg->payload; 1517 1518 if (!is_comp_resp_valid(response->comp_resp)) { 1519 return PLDM_ERROR_INVALID_DATA; 1520 } 1521 1522 if (!is_comp_resp_code_valid(response->comp_resp_code)) { 1523 return PLDM_ERROR_INVALID_DATA; 1524 } 1525 1526 *comp_resp = response->comp_resp; 1527 *comp_resp_code = response->comp_resp_code; 1528 1529 return PLDM_SUCCESS; 1530 } 1531 1532 LIBPLDM_ABI_STABLE 1533 int encode_update_component_req( 1534 uint8_t instance_id, uint16_t comp_classification, 1535 uint16_t comp_identifier, uint8_t comp_classification_index, 1536 uint32_t comp_comparison_stamp, uint32_t comp_image_size, 1537 bitfield32_t update_option_flags, uint8_t comp_ver_str_type, 1538 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str, 1539 struct pldm_msg *msg, size_t payload_length) 1540 { 1541 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) { 1542 return PLDM_ERROR_INVALID_DATA; 1543 } 1544 1545 if (payload_length != 1546 sizeof(struct pldm_update_component_req) + comp_ver_str->length) { 1547 return PLDM_ERROR_INVALID_LENGTH; 1548 } 1549 1550 if (!comp_image_size) { 1551 return PLDM_ERROR_INVALID_DATA; 1552 } 1553 1554 if ((comp_ver_str_len == 0) || 1555 (comp_ver_str_len != comp_ver_str->length)) { 1556 return PLDM_ERROR_INVALID_DATA; 1557 } 1558 1559 if (!is_string_type_valid(comp_ver_str_type)) { 1560 return PLDM_ERROR_INVALID_DATA; 1561 } 1562 1563 struct pldm_header_info header = { 0 }; 1564 header.instance = instance_id; 1565 header.msg_type = PLDM_REQUEST; 1566 header.pldm_type = PLDM_FWUP; 1567 header.command = PLDM_UPDATE_COMPONENT; 1568 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1569 if (rc) { 1570 return rc; 1571 } 1572 1573 struct pldm_update_component_req *request = 1574 (struct pldm_update_component_req *)msg->payload; 1575 1576 request->comp_classification = htole16(comp_classification); 1577 request->comp_identifier = htole16(comp_identifier); 1578 request->comp_classification_index = comp_classification_index; 1579 request->comp_comparison_stamp = htole32(comp_comparison_stamp); 1580 request->comp_image_size = htole32(comp_image_size); 1581 request->update_option_flags.value = htole32(update_option_flags.value); 1582 request->comp_ver_str_type = comp_ver_str_type; 1583 request->comp_ver_str_len = comp_ver_str_len; 1584 1585 memcpy(msg->payload + sizeof(struct pldm_update_component_req), 1586 comp_ver_str->ptr, comp_ver_str->length); 1587 1588 return PLDM_SUCCESS; 1589 } 1590 1591 LIBPLDM_ABI_STABLE 1592 int decode_update_component_resp(const struct pldm_msg *msg, 1593 size_t payload_length, 1594 uint8_t *completion_code, 1595 uint8_t *comp_compatibility_resp, 1596 uint8_t *comp_compatibility_resp_code, 1597 bitfield32_t *update_option_flags_enabled, 1598 uint16_t *time_before_req_fw_data) 1599 { 1600 if (msg == NULL || completion_code == NULL || 1601 comp_compatibility_resp == NULL || 1602 comp_compatibility_resp_code == NULL || 1603 update_option_flags_enabled == NULL || 1604 time_before_req_fw_data == NULL || !payload_length) { 1605 return PLDM_ERROR_INVALID_DATA; 1606 } 1607 1608 *completion_code = msg->payload[0]; 1609 if (*completion_code != PLDM_SUCCESS) { 1610 return PLDM_SUCCESS; 1611 } 1612 1613 if (payload_length != sizeof(struct pldm_update_component_resp)) { 1614 return PLDM_ERROR_INVALID_LENGTH; 1615 } 1616 1617 struct pldm_update_component_resp *response = 1618 (struct pldm_update_component_resp *)msg->payload; 1619 1620 if (!is_comp_compatibility_resp_valid( 1621 response->comp_compatibility_resp)) { 1622 return PLDM_ERROR_INVALID_DATA; 1623 } 1624 1625 if (!is_comp_compatibility_resp_code_valid( 1626 response->comp_compatibility_resp_code)) { 1627 return PLDM_ERROR_INVALID_DATA; 1628 } 1629 1630 *comp_compatibility_resp = response->comp_compatibility_resp; 1631 *comp_compatibility_resp_code = response->comp_compatibility_resp_code; 1632 update_option_flags_enabled->value = 1633 le32toh(response->update_option_flags_enabled.value); 1634 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data); 1635 1636 return PLDM_SUCCESS; 1637 } 1638 1639 LIBPLDM_ABI_STABLE 1640 int decode_request_firmware_data_req(const struct pldm_msg *msg, 1641 size_t payload_length, uint32_t *offset, 1642 uint32_t *length) 1643 { 1644 if (msg == NULL || offset == NULL || length == NULL) { 1645 return PLDM_ERROR_INVALID_DATA; 1646 } 1647 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) { 1648 return PLDM_ERROR_INVALID_LENGTH; 1649 } 1650 struct pldm_request_firmware_data_req *request = 1651 (struct pldm_request_firmware_data_req *)msg->payload; 1652 *offset = le32toh(request->offset); 1653 *length = le32toh(request->length); 1654 1655 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) { 1656 return PLDM_FWUP_INVALID_TRANSFER_LENGTH; 1657 } 1658 1659 return PLDM_SUCCESS; 1660 } 1661 1662 LIBPLDM_ABI_STABLE 1663 int encode_request_firmware_data_resp(uint8_t instance_id, 1664 uint8_t completion_code, 1665 struct pldm_msg *msg, 1666 size_t payload_length) 1667 { 1668 if (msg == NULL || !payload_length) { 1669 return PLDM_ERROR_INVALID_DATA; 1670 } 1671 1672 struct pldm_header_info header = { 0 }; 1673 header.instance = instance_id; 1674 header.msg_type = PLDM_RESPONSE; 1675 header.pldm_type = PLDM_FWUP; 1676 header.command = PLDM_REQUEST_FIRMWARE_DATA; 1677 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1678 if (rc) { 1679 return rc; 1680 } 1681 1682 msg->payload[0] = completion_code; 1683 1684 return PLDM_SUCCESS; 1685 } 1686 1687 LIBPLDM_ABI_STABLE 1688 int decode_transfer_complete_req(const struct pldm_msg *msg, 1689 size_t payload_length, 1690 uint8_t *transfer_result) 1691 { 1692 if (msg == NULL || transfer_result == NULL) { 1693 return PLDM_ERROR_INVALID_DATA; 1694 } 1695 1696 if (payload_length != sizeof(*transfer_result)) { 1697 return PLDM_ERROR_INVALID_LENGTH; 1698 } 1699 1700 *transfer_result = msg->payload[0]; 1701 return PLDM_SUCCESS; 1702 } 1703 1704 LIBPLDM_ABI_STABLE 1705 int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code, 1706 struct pldm_msg *msg, size_t payload_length) 1707 { 1708 if (msg == NULL) { 1709 return PLDM_ERROR_INVALID_DATA; 1710 } 1711 1712 if (payload_length != sizeof(completion_code)) { 1713 return PLDM_ERROR_INVALID_LENGTH; 1714 } 1715 1716 struct pldm_header_info header = { 0 }; 1717 header.instance = instance_id; 1718 header.msg_type = PLDM_RESPONSE; 1719 header.pldm_type = PLDM_FWUP; 1720 header.command = PLDM_TRANSFER_COMPLETE; 1721 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1722 if (rc) { 1723 return rc; 1724 } 1725 1726 msg->payload[0] = completion_code; 1727 1728 return PLDM_SUCCESS; 1729 } 1730 1731 LIBPLDM_ABI_STABLE 1732 int decode_verify_complete_req(const struct pldm_msg *msg, 1733 size_t payload_length, uint8_t *verify_result) 1734 { 1735 if (msg == NULL || verify_result == NULL) { 1736 return PLDM_ERROR_INVALID_DATA; 1737 } 1738 1739 if (payload_length != sizeof(*verify_result)) { 1740 return PLDM_ERROR_INVALID_LENGTH; 1741 } 1742 1743 *verify_result = msg->payload[0]; 1744 return PLDM_SUCCESS; 1745 } 1746 1747 LIBPLDM_ABI_STABLE 1748 int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code, 1749 struct pldm_msg *msg, size_t payload_length) 1750 { 1751 if (msg == NULL) { 1752 return PLDM_ERROR_INVALID_DATA; 1753 } 1754 1755 if (payload_length != sizeof(completion_code)) { 1756 return PLDM_ERROR_INVALID_LENGTH; 1757 } 1758 1759 struct pldm_header_info header = { 0 }; 1760 header.instance = instance_id; 1761 header.msg_type = PLDM_RESPONSE; 1762 header.pldm_type = PLDM_FWUP; 1763 header.command = PLDM_VERIFY_COMPLETE; 1764 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1765 if (rc) { 1766 return rc; 1767 } 1768 1769 msg->payload[0] = completion_code; 1770 1771 return PLDM_SUCCESS; 1772 } 1773 1774 LIBPLDM_ABI_STABLE 1775 int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length, 1776 uint8_t *apply_result, 1777 bitfield16_t *comp_activation_methods_modification) 1778 { 1779 if (msg == NULL || apply_result == NULL || 1780 comp_activation_methods_modification == NULL) { 1781 return PLDM_ERROR_INVALID_DATA; 1782 } 1783 1784 if (payload_length != sizeof(struct pldm_apply_complete_req)) { 1785 return PLDM_ERROR_INVALID_LENGTH; 1786 } 1787 1788 struct pldm_apply_complete_req *request = 1789 (struct pldm_apply_complete_req *)msg->payload; 1790 1791 *apply_result = request->apply_result; 1792 comp_activation_methods_modification->value = 1793 le16toh(request->comp_activation_methods_modification.value); 1794 1795 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) && 1796 comp_activation_methods_modification->value) { 1797 return PLDM_ERROR_INVALID_DATA; 1798 } 1799 1800 return PLDM_SUCCESS; 1801 } 1802 1803 LIBPLDM_ABI_STABLE 1804 int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code, 1805 struct pldm_msg *msg, size_t payload_length) 1806 { 1807 if (msg == NULL) { 1808 return PLDM_ERROR_INVALID_DATA; 1809 } 1810 1811 if (payload_length != sizeof(completion_code)) { 1812 return PLDM_ERROR_INVALID_LENGTH; 1813 } 1814 1815 struct pldm_header_info header = { 0 }; 1816 header.instance = instance_id; 1817 header.msg_type = PLDM_RESPONSE; 1818 header.pldm_type = PLDM_FWUP; 1819 header.command = PLDM_APPLY_COMPLETE; 1820 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1821 if (rc) { 1822 return rc; 1823 } 1824 1825 msg->payload[0] = completion_code; 1826 1827 return PLDM_SUCCESS; 1828 } 1829 1830 LIBPLDM_ABI_STABLE 1831 int encode_activate_firmware_req(uint8_t instance_id, 1832 bool8_t self_contained_activation_req, 1833 struct pldm_msg *msg, size_t payload_length) 1834 { 1835 if (msg == NULL) { 1836 return PLDM_ERROR_INVALID_DATA; 1837 } 1838 1839 if (payload_length != sizeof(struct pldm_activate_firmware_req)) { 1840 return PLDM_ERROR_INVALID_LENGTH; 1841 } 1842 1843 if (!is_self_contained_activation_req_valid( 1844 self_contained_activation_req)) { 1845 return PLDM_ERROR_INVALID_DATA; 1846 } 1847 1848 struct pldm_header_info header = { 0 }; 1849 header.instance = instance_id; 1850 header.msg_type = PLDM_REQUEST; 1851 header.pldm_type = PLDM_FWUP; 1852 header.command = PLDM_ACTIVATE_FIRMWARE; 1853 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1854 if (rc) { 1855 return rc; 1856 } 1857 1858 struct pldm_activate_firmware_req *request = 1859 (struct pldm_activate_firmware_req *)msg->payload; 1860 1861 request->self_contained_activation_req = self_contained_activation_req; 1862 1863 return PLDM_SUCCESS; 1864 } 1865 1866 LIBPLDM_ABI_STABLE 1867 int decode_activate_firmware_resp(const struct pldm_msg *msg, 1868 size_t payload_length, 1869 uint8_t *completion_code, 1870 uint16_t *estimated_time_activation) 1871 { 1872 if (msg == NULL || completion_code == NULL || 1873 estimated_time_activation == NULL || !payload_length) { 1874 return PLDM_ERROR_INVALID_DATA; 1875 } 1876 1877 *completion_code = msg->payload[0]; 1878 if (*completion_code != PLDM_SUCCESS) { 1879 return PLDM_SUCCESS; 1880 } 1881 1882 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) { 1883 return PLDM_ERROR_INVALID_LENGTH; 1884 } 1885 1886 struct pldm_activate_firmware_resp *response = 1887 (struct pldm_activate_firmware_resp *)msg->payload; 1888 1889 *estimated_time_activation = 1890 le16toh(response->estimated_time_activation); 1891 1892 return PLDM_SUCCESS; 1893 } 1894 1895 LIBPLDM_ABI_STABLE 1896 int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg, 1897 size_t payload_length) 1898 { 1899 if (msg == NULL) { 1900 return PLDM_ERROR_INVALID_DATA; 1901 } 1902 1903 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) { 1904 return PLDM_ERROR_INVALID_LENGTH; 1905 } 1906 1907 struct pldm_header_info header = { 0 }; 1908 header.instance = instance_id; 1909 header.msg_type = PLDM_REQUEST; 1910 header.pldm_type = PLDM_FWUP; 1911 header.command = PLDM_GET_STATUS; 1912 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1913 if (rc) { 1914 return rc; 1915 } 1916 1917 return PLDM_SUCCESS; 1918 } 1919 1920 LIBPLDM_ABI_STABLE 1921 int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length, 1922 uint8_t *completion_code, uint8_t *current_state, 1923 uint8_t *previous_state, uint8_t *aux_state, 1924 uint8_t *aux_state_status, uint8_t *progress_percent, 1925 uint8_t *reason_code, 1926 bitfield32_t *update_option_flags_enabled) 1927 { 1928 if (msg == NULL || completion_code == NULL || current_state == NULL || 1929 previous_state == NULL || aux_state == NULL || 1930 aux_state_status == NULL || progress_percent == NULL || 1931 reason_code == NULL || update_option_flags_enabled == NULL || 1932 !payload_length) { 1933 return PLDM_ERROR_INVALID_DATA; 1934 } 1935 1936 *completion_code = msg->payload[0]; 1937 if (*completion_code != PLDM_SUCCESS) { 1938 return PLDM_SUCCESS; 1939 } 1940 1941 if (payload_length != sizeof(struct pldm_get_status_resp)) { 1942 return PLDM_ERROR_INVALID_LENGTH; 1943 } 1944 struct pldm_get_status_resp *response = 1945 (struct pldm_get_status_resp *)msg->payload; 1946 1947 if (!is_state_valid(response->current_state)) { 1948 return PLDM_ERROR_INVALID_DATA; 1949 } 1950 if (!is_state_valid(response->previous_state)) { 1951 return PLDM_ERROR_INVALID_DATA; 1952 } 1953 if (!is_aux_state_valid(response->aux_state)) { 1954 return PLDM_ERROR_INVALID_DATA; 1955 } 1956 if (!is_aux_state_status_valid(response->aux_state_status)) { 1957 return PLDM_ERROR_INVALID_DATA; 1958 } 1959 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) { 1960 return PLDM_ERROR_INVALID_DATA; 1961 } 1962 if (!is_reason_code_valid(response->reason_code)) { 1963 return PLDM_ERROR_INVALID_DATA; 1964 } 1965 1966 if ((response->current_state == PLDM_FD_STATE_IDLE) || 1967 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) || 1968 (response->current_state == PLDM_FD_STATE_READY_XFER)) { 1969 if (response->aux_state != 1970 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) { 1971 return PLDM_ERROR_INVALID_DATA; 1972 } 1973 } 1974 1975 *current_state = response->current_state; 1976 *previous_state = response->previous_state; 1977 *aux_state = response->aux_state; 1978 *aux_state_status = response->aux_state_status; 1979 *progress_percent = response->progress_percent; 1980 *reason_code = response->reason_code; 1981 update_option_flags_enabled->value = 1982 le32toh(response->update_option_flags_enabled.value); 1983 1984 return PLDM_SUCCESS; 1985 } 1986 1987 LIBPLDM_ABI_STABLE 1988 int encode_cancel_update_component_req(uint8_t instance_id, 1989 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_COMPONENT_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_COMPONENT; 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_component_resp(const struct pldm_msg *msg, 2015 size_t payload_length, 2016 uint8_t *completion_code) 2017 { 2018 if (msg == NULL || completion_code == NULL) { 2019 return PLDM_ERROR_INVALID_DATA; 2020 } 2021 2022 if (payload_length != sizeof(*completion_code)) { 2023 return PLDM_ERROR_INVALID_LENGTH; 2024 } 2025 2026 *completion_code = msg->payload[0]; 2027 return PLDM_SUCCESS; 2028 } 2029 2030 LIBPLDM_ABI_STABLE 2031 int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg, 2032 size_t payload_length) 2033 { 2034 if (msg == NULL) { 2035 return PLDM_ERROR_INVALID_DATA; 2036 } 2037 2038 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) { 2039 return PLDM_ERROR_INVALID_LENGTH; 2040 } 2041 2042 struct pldm_header_info header = { 0 }; 2043 header.instance = instance_id; 2044 header.msg_type = PLDM_REQUEST; 2045 header.pldm_type = PLDM_FWUP; 2046 header.command = PLDM_CANCEL_UPDATE; 2047 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2048 if (rc) { 2049 return rc; 2050 } 2051 2052 return PLDM_SUCCESS; 2053 } 2054 2055 LIBPLDM_ABI_STABLE 2056 int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length, 2057 uint8_t *completion_code, 2058 bool8_t *non_functioning_component_indication, 2059 bitfield64_t *non_functioning_component_bitmap) 2060 { 2061 if (msg == NULL || completion_code == NULL || 2062 non_functioning_component_indication == NULL || 2063 non_functioning_component_bitmap == NULL || !payload_length) { 2064 return PLDM_ERROR_INVALID_DATA; 2065 } 2066 2067 *completion_code = msg->payload[0]; 2068 if (*completion_code != PLDM_SUCCESS) { 2069 return PLDM_SUCCESS; 2070 } 2071 2072 if (payload_length != sizeof(struct pldm_cancel_update_resp)) { 2073 return PLDM_ERROR_INVALID_LENGTH; 2074 } 2075 struct pldm_cancel_update_resp *response = 2076 (struct pldm_cancel_update_resp *)msg->payload; 2077 2078 if (!is_non_functioning_component_indication_valid( 2079 response->non_functioning_component_indication)) { 2080 return PLDM_ERROR_INVALID_DATA; 2081 } 2082 2083 *non_functioning_component_indication = 2084 response->non_functioning_component_indication; 2085 2086 if (*non_functioning_component_indication) { 2087 non_functioning_component_bitmap->value = 2088 le64toh(response->non_functioning_component_bitmap); 2089 } 2090 2091 return PLDM_SUCCESS; 2092 } 2093