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 static_assert(PLDM_FIRMWARE_MAX_STRING <= UINT8_MAX, "too large"); 13 14 /** @brief Check whether string type value is valid 15 * 16 * @return true if string type value is valid, false if not 17 */ 18 static bool is_string_type_valid(uint8_t string_type) 19 { 20 switch (string_type) { 21 case PLDM_STR_TYPE_UNKNOWN: 22 return false; 23 case PLDM_STR_TYPE_ASCII: 24 case PLDM_STR_TYPE_UTF_8: 25 case PLDM_STR_TYPE_UTF_16: 26 case PLDM_STR_TYPE_UTF_16LE: 27 case PLDM_STR_TYPE_UTF_16BE: 28 return true; 29 default: 30 return false; 31 } 32 } 33 34 /** @brief Return the length of the descriptor type described in firmware update 35 * specification 36 * 37 * @return length of the descriptor type if descriptor type is valid else 38 * return 0 39 */ 40 static uint16_t get_descriptor_type_length(uint16_t descriptor_type) 41 { 42 switch (descriptor_type) { 43 case PLDM_FWUP_PCI_VENDOR_ID: 44 return PLDM_FWUP_PCI_VENDOR_ID_LENGTH; 45 case PLDM_FWUP_IANA_ENTERPRISE_ID: 46 return PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH; 47 case PLDM_FWUP_UUID: 48 return PLDM_FWUP_UUID_LENGTH; 49 case PLDM_FWUP_PNP_VENDOR_ID: 50 return PLDM_FWUP_PNP_VENDOR_ID_LENGTH; 51 case PLDM_FWUP_ACPI_VENDOR_ID: 52 return PLDM_FWUP_ACPI_VENDOR_ID_LENGTH; 53 case PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID: 54 return PLDM_FWUP_IEEE_ASSIGNED_COMPANY_ID_LENGTH; 55 case PLDM_FWUP_SCSI_VENDOR_ID: 56 return PLDM_FWUP_SCSI_VENDOR_ID_LENGTH; 57 case PLDM_FWUP_PCI_DEVICE_ID: 58 return PLDM_FWUP_PCI_DEVICE_ID_LENGTH; 59 case PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID: 60 return PLDM_FWUP_PCI_SUBSYSTEM_VENDOR_ID_LENGTH; 61 case PLDM_FWUP_PCI_SUBSYSTEM_ID: 62 return PLDM_FWUP_PCI_SUBSYSTEM_ID_LENGTH; 63 case PLDM_FWUP_PCI_REVISION_ID: 64 return PLDM_FWUP_PCI_REVISION_ID_LENGTH; 65 case PLDM_FWUP_PNP_PRODUCT_IDENTIFIER: 66 return PLDM_FWUP_PNP_PRODUCT_IDENTIFIER_LENGTH; 67 case PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER: 68 return PLDM_FWUP_ACPI_PRODUCT_IDENTIFIER_LENGTH; 69 case PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING: 70 return PLDM_FWUP_ASCII_MODEL_NUMBER_LONG_STRING_LENGTH; 71 case PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING: 72 return PLDM_FWUP_ASCII_MODEL_NUMBER_SHORT_STRING_LENGTH; 73 case PLDM_FWUP_SCSI_PRODUCT_ID: 74 return PLDM_FWUP_SCSI_PRODUCT_ID_LENGTH; 75 case PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE: 76 return PLDM_FWUP_UBM_CONTROLLER_DEVICE_CODE_LENGTH; 77 default: 78 return 0; 79 } 80 } 81 82 static bool is_downstream_device_update_support_valid(uint8_t resp) 83 { 84 switch (resp) { 85 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED: 86 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED: 87 return true; 88 default: 89 return false; 90 } 91 } 92 93 static bool 94 is_transfer_operation_flag_valid(enum transfer_op_flag transfer_op_flag) 95 { 96 switch (transfer_op_flag) { 97 case PLDM_GET_NEXTPART: 98 case PLDM_GET_FIRSTPART: 99 return true; 100 default: 101 return false; 102 } 103 } 104 105 /** @brief Check whether ComponentResponse is valid 106 * 107 * @return true if ComponentResponse is valid, false if not 108 */ 109 static bool is_comp_resp_valid(uint8_t comp_resp) 110 { 111 switch (comp_resp) { 112 case PLDM_CR_COMP_CAN_BE_UPDATED: 113 case PLDM_CR_COMP_MAY_BE_UPDATEABLE: 114 return true; 115 116 default: 117 return false; 118 } 119 } 120 121 /** @brief Check whether ComponentResponseCode is valid 122 * 123 * @return true if ComponentResponseCode is valid, false if not 124 */ 125 static bool is_comp_resp_code_valid(uint8_t comp_resp_code) 126 { 127 switch (comp_resp_code) { 128 case PLDM_CRC_COMP_CAN_BE_UPDATED: 129 case PLDM_CRC_COMP_COMPARISON_STAMP_IDENTICAL: 130 case PLDM_CRC_COMP_COMPARISON_STAMP_LOWER: 131 case PLDM_CRC_INVALID_COMP_COMPARISON_STAMP: 132 case PLDM_CRC_COMP_CONFLICT: 133 case PLDM_CRC_COMP_PREREQUISITES_NOT_MET: 134 case PLDM_CRC_COMP_NOT_SUPPORTED: 135 case PLDM_CRC_COMP_SECURITY_RESTRICTIONS: 136 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET: 137 case PLDM_CRC_ACTIVE_IMAGE_NOT_UPDATEABLE_SUBSEQUENTLY: 138 case PLDM_CRC_COMP_VER_STR_IDENTICAL: 139 case PLDM_CRC_COMP_VER_STR_LOWER: 140 return true; 141 142 default: 143 if (comp_resp_code >= 144 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MIN && 145 comp_resp_code <= 146 PLDM_CRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) { 147 return true; 148 } 149 return false; 150 } 151 } 152 153 /** @brief Check whether ComponentCompatibilityResponse is valid 154 * 155 * @return true if ComponentCompatibilityResponse is valid, false if not 156 */ 157 static bool is_comp_compatibility_resp_valid(uint8_t comp_compatibility_resp) 158 { 159 switch (comp_compatibility_resp) { 160 case PLDM_CCR_COMP_CAN_BE_UPDATED: 161 case PLDM_CCR_COMP_CANNOT_BE_UPDATED: 162 return true; 163 164 default: 165 return false; 166 } 167 } 168 169 /** @brief Check whether ComponentCompatibilityResponse Code is valid 170 * 171 * @return true if ComponentCompatibilityResponse Code is valid, false if not 172 */ 173 static bool 174 is_comp_compatibility_resp_code_valid(uint8_t comp_compatibility_resp_code) 175 { 176 switch (comp_compatibility_resp_code) { 177 case PLDM_CCRC_NO_RESPONSE_CODE: 178 case PLDM_CCRC_COMP_COMPARISON_STAMP_IDENTICAL: 179 case PLDM_CCRC_COMP_COMPARISON_STAMP_LOWER: 180 case PLDM_CCRC_INVALID_COMP_COMPARISON_STAMP: 181 case PLDM_CCRC_COMP_CONFLICT: 182 case PLDM_CCRC_COMP_PREREQUISITES_NOT_MET: 183 case PLDM_CCRC_COMP_NOT_SUPPORTED: 184 case PLDM_CCRC_COMP_SECURITY_RESTRICTIONS: 185 case PLDM_CRC_INCOMPLETE_COMP_IMAGE_SET: 186 case PLDM_CCRC_COMP_INFO_NO_MATCH: 187 case PLDM_CCRC_COMP_VER_STR_IDENTICAL: 188 case PLDM_CCRC_COMP_VER_STR_LOWER: 189 return true; 190 191 default: 192 if (comp_compatibility_resp_code >= 193 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MIN && 194 comp_compatibility_resp_code <= 195 PLDM_CCRC_VENDOR_COMP_RESP_CODE_RANGE_MAX) { 196 return true; 197 } 198 return false; 199 } 200 } 201 202 /** @brief Check whether SelfContainedActivationRequest is valid 203 * 204 * @return true if SelfContainedActivationRequest is valid, false if not 205 */ 206 static bool 207 is_self_contained_activation_req_valid(bool8_t self_contained_activation_req) 208 { 209 switch (self_contained_activation_req) { 210 case PLDM_NOT_ACTIVATE_SELF_CONTAINED_COMPONENTS: 211 case PLDM_ACTIVATE_SELF_CONTAINED_COMPONENTS: 212 return true; 213 214 default: 215 return false; 216 } 217 } 218 219 /** @brief Check if current or previous status in GetStatus command response is 220 * valid 221 * 222 * @param[in] state - current or previous different state machine state of 223 * the FD 224 * @return true if state is valid, false if not 225 */ 226 static bool is_state_valid(uint8_t state) 227 { 228 switch (state) { 229 case PLDM_FD_STATE_IDLE: 230 case PLDM_FD_STATE_LEARN_COMPONENTS: 231 case PLDM_FD_STATE_READY_XFER: 232 case PLDM_FD_STATE_DOWNLOAD: 233 case PLDM_FD_STATE_VERIFY: 234 case PLDM_FD_STATE_APPLY: 235 case PLDM_FD_STATE_ACTIVATE: 236 return true; 237 238 default: 239 return false; 240 } 241 } 242 243 /** @brief Check if aux state in GetStatus command response is valid 244 * 245 * @param[in] aux_state - provides additional information to the UA to describe 246 * the current operation state of the FD/FDP 247 * 248 * @return true if aux state is valid, false if not 249 */ 250 static bool is_aux_state_valid(uint8_t aux_state) 251 { 252 switch (aux_state) { 253 case PLDM_FD_OPERATION_IN_PROGRESS: 254 case PLDM_FD_OPERATION_SUCCESSFUL: 255 case PLDM_FD_OPERATION_FAILED: 256 case PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER: 257 return true; 258 259 default: 260 return false; 261 } 262 } 263 264 /** @brief Check if aux state status in GetStatus command response is valid 265 * 266 * @param[in] aux_state_status - aux state status 267 * 268 * @return true if aux state status is valid, false if not 269 */ 270 static bool is_aux_state_status_valid(uint8_t aux_state_status) 271 { 272 if (aux_state_status == PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS || 273 aux_state_status == PLDM_FD_TIMEOUT || 274 aux_state_status == PLDM_FD_GENERIC_ERROR || 275 (aux_state_status >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START && 276 aux_state_status <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)) { 277 return true; 278 } 279 280 return false; 281 } 282 283 /** @brief Check if reason code in GetStatus command response is valid 284 * 285 * @param[in] reason_code - provides the reason for why the current state 286 * entered the IDLE state 287 * 288 * @return true if reason code is valid, false if not 289 */ 290 static bool is_reason_code_valid(uint8_t reason_code) 291 { 292 switch (reason_code) { 293 case PLDM_FD_INITIALIZATION: 294 case PLDM_FD_ACTIVATE_FW: 295 case PLDM_FD_CANCEL_UPDATE: 296 case PLDM_FD_TIMEOUT_LEARN_COMPONENT: 297 case PLDM_FD_TIMEOUT_READY_XFER: 298 case PLDM_FD_TIMEOUT_DOWNLOAD: 299 case PLDM_FD_TIMEOUT_VERIFY: 300 case PLDM_FD_TIMEOUT_APPLY: 301 return true; 302 303 default: 304 if (reason_code >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN) { 305 return true; 306 } 307 return false; 308 } 309 } 310 311 /** @brief Check if non functioning component indication in CancelUpdate 312 * response is valid 313 * 314 * @return true if non functioning component indication is valid, false if not 315 */ 316 static bool is_non_functioning_component_indication_valid( 317 bool8_t non_functioning_component_indication) 318 { 319 switch (non_functioning_component_indication) { 320 case PLDM_FWUP_COMPONENTS_FUNCTIONING: 321 case PLDM_FWUP_COMPONENTS_NOT_FUNCTIONING: 322 return true; 323 324 default: 325 return false; 326 } 327 } 328 329 LIBPLDM_ABI_STABLE 330 int decode_pldm_package_header_info( 331 const uint8_t *data, size_t length, 332 struct pldm_package_header_information *package_header_info, 333 struct variable_field *package_version_str) 334 { 335 if (data == NULL || package_header_info == NULL || 336 package_version_str == NULL) { 337 return PLDM_ERROR_INVALID_DATA; 338 } 339 340 if (length < sizeof(struct pldm_package_header_information)) { 341 return PLDM_ERROR_INVALID_LENGTH; 342 } 343 344 struct pldm_package_header_information *data_header = 345 (struct pldm_package_header_information *)(data); 346 347 if (!is_string_type_valid(data_header->package_version_string_type) || 348 (data_header->package_version_string_length == 0)) { 349 return PLDM_ERROR_INVALID_DATA; 350 } 351 352 if (length < sizeof(struct pldm_package_header_information) + 353 data_header->package_version_string_length) { 354 return PLDM_ERROR_INVALID_LENGTH; 355 } 356 357 if ((data_header->component_bitmap_bit_length % 358 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) { 359 return PLDM_ERROR_INVALID_DATA; 360 } 361 362 memcpy(package_header_info->uuid, data_header->uuid, 363 sizeof(data_header->uuid)); 364 package_header_info->package_header_format_version = 365 data_header->package_header_format_version; 366 package_header_info->package_header_size = 367 le16toh(data_header->package_header_size); 368 memcpy(package_header_info->package_release_date_time, 369 data_header->package_release_date_time, 370 sizeof(data_header->package_release_date_time)); 371 package_header_info->component_bitmap_bit_length = 372 le16toh(data_header->component_bitmap_bit_length); 373 package_header_info->package_version_string_type = 374 data_header->package_version_string_type; 375 package_header_info->package_version_string_length = 376 data_header->package_version_string_length; 377 package_version_str->ptr = 378 data + sizeof(struct pldm_package_header_information); 379 package_version_str->length = 380 package_header_info->package_version_string_length; 381 382 return PLDM_SUCCESS; 383 } 384 385 LIBPLDM_ABI_STABLE 386 int decode_firmware_device_id_record( 387 const uint8_t *data, size_t length, 388 uint16_t component_bitmap_bit_length, 389 struct pldm_firmware_device_id_record *fw_device_id_record, 390 struct variable_field *applicable_components, 391 struct variable_field *comp_image_set_version_str, 392 struct variable_field *record_descriptors, 393 struct variable_field *fw_device_pkg_data) 394 { 395 if (data == NULL || fw_device_id_record == NULL || 396 applicable_components == NULL || 397 comp_image_set_version_str == NULL || record_descriptors == NULL || 398 fw_device_pkg_data == NULL) { 399 return PLDM_ERROR_INVALID_DATA; 400 } 401 402 if (length < sizeof(struct pldm_firmware_device_id_record)) { 403 return PLDM_ERROR_INVALID_LENGTH; 404 } 405 406 if ((component_bitmap_bit_length % 407 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE) != 0) { 408 return PLDM_ERROR_INVALID_DATA; 409 } 410 411 struct pldm_firmware_device_id_record *data_record = 412 (struct pldm_firmware_device_id_record *)(data); 413 414 if (!is_string_type_valid( 415 data_record->comp_image_set_version_string_type) || 416 (data_record->comp_image_set_version_string_length == 0)) { 417 return PLDM_ERROR_INVALID_DATA; 418 } 419 420 fw_device_id_record->record_length = 421 le16toh(data_record->record_length); 422 fw_device_id_record->descriptor_count = data_record->descriptor_count; 423 fw_device_id_record->device_update_option_flags.value = 424 le32toh(data_record->device_update_option_flags.value); 425 fw_device_id_record->comp_image_set_version_string_type = 426 data_record->comp_image_set_version_string_type; 427 fw_device_id_record->comp_image_set_version_string_length = 428 data_record->comp_image_set_version_string_length; 429 fw_device_id_record->fw_device_pkg_data_length = 430 le16toh(data_record->fw_device_pkg_data_length); 431 432 if (length < fw_device_id_record->record_length) { 433 return PLDM_ERROR_INVALID_LENGTH; 434 } 435 436 uint16_t applicable_components_length = 437 component_bitmap_bit_length / 438 PLDM_FWUP_COMPONENT_BITMAP_MULTIPLE; 439 size_t calc_min_record_length = 440 sizeof(struct pldm_firmware_device_id_record) + 441 applicable_components_length + 442 data_record->comp_image_set_version_string_length + 443 PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN + 444 fw_device_id_record->fw_device_pkg_data_length; 445 446 if (fw_device_id_record->record_length < calc_min_record_length) { 447 return PLDM_ERROR_INVALID_LENGTH; 448 } 449 450 applicable_components->ptr = 451 data + sizeof(struct pldm_firmware_device_id_record); 452 applicable_components->length = applicable_components_length; 453 454 comp_image_set_version_str->ptr = 455 applicable_components->ptr + applicable_components->length; 456 comp_image_set_version_str->length = 457 fw_device_id_record->comp_image_set_version_string_length; 458 459 record_descriptors->ptr = comp_image_set_version_str->ptr + 460 comp_image_set_version_str->length; 461 record_descriptors->length = 462 fw_device_id_record->record_length - 463 sizeof(struct pldm_firmware_device_id_record) - 464 applicable_components_length - 465 fw_device_id_record->comp_image_set_version_string_length - 466 fw_device_id_record->fw_device_pkg_data_length; 467 468 if (fw_device_id_record->fw_device_pkg_data_length) { 469 fw_device_pkg_data->ptr = 470 record_descriptors->ptr + record_descriptors->length; 471 fw_device_pkg_data->length = 472 fw_device_id_record->fw_device_pkg_data_length; 473 } 474 475 return PLDM_SUCCESS; 476 } 477 478 LIBPLDM_ABI_TESTING 479 int decode_pldm_descriptor_from_iter(struct pldm_descriptor_iter *iter, 480 struct pldm_descriptor *desc) 481 { 482 struct pldm_msgbuf _buf; 483 struct pldm_msgbuf *buf = &_buf; 484 int rc; 485 486 if (!iter || !iter->field || !desc) { 487 return -EINVAL; 488 } 489 490 rc = pldm_msgbuf_init_errno(buf, PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN, 491 iter->field->ptr, iter->field->length); 492 if (rc) { 493 return rc; 494 } 495 496 pldm_msgbuf_extract(buf, desc->descriptor_type); 497 rc = pldm_msgbuf_extract(buf, desc->descriptor_length); 498 if (rc) { 499 return rc; 500 } 501 502 desc->descriptor_data = NULL; 503 pldm_msgbuf_span_required(buf, desc->descriptor_length, 504 (void **)&desc->descriptor_data); 505 iter->field->ptr = NULL; 506 pldm_msgbuf_span_remaining(buf, (void **)&iter->field->ptr, 507 &iter->field->length); 508 509 return pldm_msgbuf_destroy(buf); 510 } 511 512 LIBPLDM_ABI_STABLE 513 int decode_descriptor_type_length_value(const uint8_t *data, size_t length, 514 uint16_t *descriptor_type, 515 struct variable_field *descriptor_data) 516 { 517 uint16_t descriptor_length = 0; 518 519 if (data == NULL || descriptor_type == NULL || 520 descriptor_data == NULL) { 521 return PLDM_ERROR_INVALID_DATA; 522 } 523 524 if (length < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) { 525 return PLDM_ERROR_INVALID_LENGTH; 526 } 527 528 struct pldm_descriptor_tlv *entry = 529 (struct pldm_descriptor_tlv *)(data); 530 531 *descriptor_type = le16toh(entry->descriptor_type); 532 descriptor_length = le16toh(entry->descriptor_length); 533 if (*descriptor_type != PLDM_FWUP_VENDOR_DEFINED) { 534 if (descriptor_length != 535 get_descriptor_type_length(*descriptor_type)) { 536 return PLDM_ERROR_INVALID_LENGTH; 537 } 538 } 539 540 if (length < (sizeof(*descriptor_type) + sizeof(descriptor_length) + 541 descriptor_length)) { 542 return PLDM_ERROR_INVALID_LENGTH; 543 } 544 545 descriptor_data->ptr = entry->descriptor_data; 546 descriptor_data->length = descriptor_length; 547 548 return PLDM_SUCCESS; 549 } 550 551 LIBPLDM_ABI_STABLE 552 int decode_vendor_defined_descriptor_value( 553 const uint8_t *data, size_t length, uint8_t *descriptor_title_str_type, 554 struct variable_field *descriptor_title_str, 555 struct variable_field *descriptor_data) 556 { 557 if (data == NULL || descriptor_title_str_type == NULL || 558 descriptor_title_str == NULL || descriptor_data == NULL) { 559 return PLDM_ERROR_INVALID_DATA; 560 } 561 562 if (length < sizeof(struct pldm_vendor_defined_descriptor_title_data)) { 563 return PLDM_ERROR_INVALID_LENGTH; 564 } 565 566 struct pldm_vendor_defined_descriptor_title_data *entry = 567 (struct pldm_vendor_defined_descriptor_title_data *)(data); 568 if (!is_string_type_valid( 569 entry->vendor_defined_descriptor_title_str_type) || 570 (entry->vendor_defined_descriptor_title_str_len == 0)) { 571 return PLDM_ERROR_INVALID_DATA; 572 } 573 574 // Assuming at least 1 byte of VendorDefinedDescriptorData 575 if (length < (sizeof(struct pldm_vendor_defined_descriptor_title_data) + 576 entry->vendor_defined_descriptor_title_str_len)) { 577 return PLDM_ERROR_INVALID_LENGTH; 578 } 579 580 *descriptor_title_str_type = 581 entry->vendor_defined_descriptor_title_str_type; 582 descriptor_title_str->ptr = entry->vendor_defined_descriptor_title_str; 583 descriptor_title_str->length = 584 entry->vendor_defined_descriptor_title_str_len; 585 586 descriptor_data->ptr = 587 descriptor_title_str->ptr + descriptor_title_str->length; 588 descriptor_data->length = 589 length - 590 sizeof(entry->vendor_defined_descriptor_title_str_type) - 591 sizeof(entry->vendor_defined_descriptor_title_str_len) - 592 descriptor_title_str->length; 593 594 return PLDM_SUCCESS; 595 } 596 597 LIBPLDM_ABI_STABLE 598 int decode_pldm_comp_image_info( 599 const uint8_t *data, size_t length, 600 struct pldm_component_image_information *pldm_comp_image_info, 601 struct variable_field *comp_version_str) 602 { 603 if (data == NULL || pldm_comp_image_info == NULL || 604 comp_version_str == NULL) { 605 return PLDM_ERROR_INVALID_DATA; 606 } 607 608 if (length < sizeof(struct pldm_component_image_information)) { 609 return PLDM_ERROR_INVALID_LENGTH; 610 } 611 612 struct pldm_component_image_information *data_header = 613 (struct pldm_component_image_information *)(data); 614 615 if (!is_string_type_valid(data_header->comp_version_string_type) || 616 (data_header->comp_version_string_length == 0)) { 617 return PLDM_ERROR_INVALID_DATA; 618 } 619 620 if (length < sizeof(struct pldm_component_image_information) + 621 data_header->comp_version_string_length) { 622 return PLDM_ERROR_INVALID_LENGTH; 623 } 624 625 pldm_comp_image_info->comp_classification = 626 le16toh(data_header->comp_classification); 627 pldm_comp_image_info->comp_identifier = 628 le16toh(data_header->comp_identifier); 629 pldm_comp_image_info->comp_comparison_stamp = 630 le32toh(data_header->comp_comparison_stamp); 631 pldm_comp_image_info->comp_options.value = 632 le16toh(data_header->comp_options.value); 633 pldm_comp_image_info->requested_comp_activation_method.value = 634 le16toh(data_header->requested_comp_activation_method.value); 635 pldm_comp_image_info->comp_location_offset = 636 le32toh(data_header->comp_location_offset); 637 pldm_comp_image_info->comp_size = le32toh(data_header->comp_size); 638 pldm_comp_image_info->comp_version_string_type = 639 data_header->comp_version_string_type; 640 pldm_comp_image_info->comp_version_string_length = 641 data_header->comp_version_string_length; 642 643 if ((pldm_comp_image_info->comp_options.bits.bit1 == false && 644 pldm_comp_image_info->comp_comparison_stamp != 645 PLDM_FWUP_INVALID_COMPONENT_COMPARISON_TIMESTAMP)) { 646 return PLDM_ERROR_INVALID_DATA; 647 } 648 649 if (pldm_comp_image_info->comp_location_offset == 0 || 650 pldm_comp_image_info->comp_size == 0) { 651 return PLDM_ERROR_INVALID_DATA; 652 } 653 654 comp_version_str->ptr = 655 data + sizeof(struct pldm_component_image_information); 656 comp_version_str->length = 657 pldm_comp_image_info->comp_version_string_length; 658 659 return PLDM_SUCCESS; 660 } 661 662 LIBPLDM_ABI_STABLE 663 int encode_query_device_identifiers_req(uint8_t instance_id, 664 size_t payload_length, 665 struct pldm_msg *msg) 666 { 667 if (msg == NULL) { 668 return PLDM_ERROR_INVALID_DATA; 669 } 670 671 if (payload_length != PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES) { 672 return PLDM_ERROR_INVALID_LENGTH; 673 } 674 675 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 676 PLDM_QUERY_DEVICE_IDENTIFIERS, msg); 677 } 678 679 LIBPLDM_ABI_STABLE 680 int decode_query_device_identifiers_resp(const struct pldm_msg *msg, 681 size_t payload_length, 682 uint8_t *completion_code, 683 uint32_t *device_identifiers_len, 684 uint8_t *descriptor_count, 685 uint8_t **descriptor_data) 686 { 687 if (msg == NULL || completion_code == NULL || 688 device_identifiers_len == NULL || descriptor_count == NULL || 689 descriptor_data == NULL) { 690 return PLDM_ERROR_INVALID_DATA; 691 } 692 693 *completion_code = msg->payload[0]; 694 if (PLDM_SUCCESS != *completion_code) { 695 return PLDM_SUCCESS; 696 } 697 698 if (payload_length < 699 sizeof(struct pldm_query_device_identifiers_resp)) { 700 return PLDM_ERROR_INVALID_LENGTH; 701 } 702 703 struct pldm_query_device_identifiers_resp *response = 704 (struct pldm_query_device_identifiers_resp *)msg->payload; 705 *device_identifiers_len = le32toh(response->device_identifiers_len); 706 707 if (*device_identifiers_len < PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN) { 708 return PLDM_ERROR_INVALID_LENGTH; 709 } 710 711 if (payload_length != 712 sizeof(struct pldm_query_device_identifiers_resp) + 713 *device_identifiers_len) { 714 return PLDM_ERROR_INVALID_LENGTH; 715 } 716 *descriptor_count = response->descriptor_count; 717 718 if (*descriptor_count == 0) { 719 return PLDM_ERROR_INVALID_DATA; 720 } 721 *descriptor_data = 722 (uint8_t *)(msg->payload + 723 sizeof(struct pldm_query_device_identifiers_resp)); 724 return PLDM_SUCCESS; 725 } 726 727 LIBPLDM_ABI_TESTING 728 int encode_query_device_identifiers_resp( 729 uint8_t instance_id, uint8_t descriptor_count, 730 const struct pldm_descriptor *descriptors, struct pldm_msg *msg, 731 size_t *payload_length) 732 { 733 int rc; 734 struct pldm_msgbuf _buf; 735 struct pldm_msgbuf *buf = &_buf; 736 737 if (descriptors == NULL || msg == NULL || payload_length == NULL) { 738 return -EINVAL; 739 } 740 741 if (descriptor_count < 1) { 742 return -EINVAL; 743 } 744 745 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 746 PLDM_QUERY_DEVICE_IDENTIFIERS, msg); 747 if (rc) { 748 return -EINVAL; 749 } 750 751 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 752 if (rc) { 753 return rc; 754 } 755 756 /* Determine total length */ 757 uint32_t device_identifiers_len = 0; 758 for (uint8_t i = 0; i < descriptor_count; i++) { 759 const struct pldm_descriptor *d = &descriptors[i]; 760 device_identifiers_len += 761 2 * sizeof(uint16_t) + d->descriptor_length; 762 } 763 764 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 765 pldm_msgbuf_insert(buf, device_identifiers_len); 766 pldm_msgbuf_insert(buf, descriptor_count); 767 768 for (uint8_t i = 0; i < descriptor_count; i++) { 769 const struct pldm_descriptor *d = &descriptors[i]; 770 pldm_msgbuf_insert(buf, d->descriptor_type); 771 pldm_msgbuf_insert(buf, d->descriptor_length); 772 if (d->descriptor_data == NULL) { 773 return -EINVAL; 774 } 775 rc = pldm_msgbuf_insert_array( 776 buf, d->descriptor_length, 777 (const uint8_t *)d->descriptor_data, 778 d->descriptor_length); 779 if (rc) { 780 return rc; 781 } 782 } 783 784 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 785 } 786 787 LIBPLDM_ABI_STABLE 788 int encode_get_firmware_parameters_req(uint8_t instance_id, 789 size_t payload_length, 790 struct pldm_msg *msg) 791 { 792 if (msg == NULL) { 793 return PLDM_ERROR_INVALID_DATA; 794 } 795 796 if (payload_length != PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES) { 797 return PLDM_ERROR_INVALID_LENGTH; 798 } 799 800 return encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 801 PLDM_GET_FIRMWARE_PARAMETERS, msg); 802 } 803 804 LIBPLDM_ABI_STABLE 805 int decode_get_firmware_parameters_resp( 806 const struct pldm_msg *msg, size_t payload_length, 807 struct pldm_get_firmware_parameters_resp *resp_data, 808 struct variable_field *active_comp_image_set_ver_str, 809 struct variable_field *pending_comp_image_set_ver_str, 810 struct variable_field *comp_parameter_table) 811 { 812 if (msg == NULL || resp_data == NULL || 813 active_comp_image_set_ver_str == NULL || 814 pending_comp_image_set_ver_str == NULL || 815 comp_parameter_table == NULL || !payload_length) { 816 return PLDM_ERROR_INVALID_DATA; 817 } 818 819 resp_data->completion_code = msg->payload[0]; 820 if (PLDM_SUCCESS != resp_data->completion_code) { 821 return PLDM_SUCCESS; 822 } 823 824 if (payload_length < sizeof(struct pldm_get_firmware_parameters_resp)) { 825 return PLDM_ERROR_INVALID_LENGTH; 826 } 827 828 struct pldm_get_firmware_parameters_resp *response = 829 (struct pldm_get_firmware_parameters_resp *)msg->payload; 830 831 if (!is_string_type_valid( 832 response->active_comp_image_set_ver_str_type) || 833 (response->active_comp_image_set_ver_str_len == 0)) { 834 return PLDM_ERROR_INVALID_DATA; 835 } 836 837 if (response->pending_comp_image_set_ver_str_len == 0) { 838 if (response->pending_comp_image_set_ver_str_type != 839 PLDM_STR_TYPE_UNKNOWN) { 840 return PLDM_ERROR_INVALID_DATA; 841 } 842 } else { 843 if (!is_string_type_valid( 844 response->pending_comp_image_set_ver_str_type)) { 845 return PLDM_ERROR_INVALID_DATA; 846 } 847 } 848 849 size_t partial_response_length = 850 sizeof(struct pldm_get_firmware_parameters_resp) + 851 response->active_comp_image_set_ver_str_len + 852 response->pending_comp_image_set_ver_str_len; 853 854 if (payload_length < partial_response_length) { 855 return PLDM_ERROR_INVALID_LENGTH; 856 } 857 858 resp_data->capabilities_during_update.value = 859 le32toh(response->capabilities_during_update.value); 860 resp_data->comp_count = le16toh(response->comp_count); 861 resp_data->active_comp_image_set_ver_str_type = 862 response->active_comp_image_set_ver_str_type; 863 resp_data->active_comp_image_set_ver_str_len = 864 response->active_comp_image_set_ver_str_len; 865 resp_data->pending_comp_image_set_ver_str_type = 866 response->pending_comp_image_set_ver_str_type; 867 resp_data->pending_comp_image_set_ver_str_len = 868 response->pending_comp_image_set_ver_str_len; 869 870 active_comp_image_set_ver_str->ptr = 871 msg->payload + sizeof(struct pldm_get_firmware_parameters_resp); 872 active_comp_image_set_ver_str->length = 873 resp_data->active_comp_image_set_ver_str_len; 874 875 if (resp_data->pending_comp_image_set_ver_str_len != 0) { 876 pending_comp_image_set_ver_str->ptr = 877 msg->payload + 878 sizeof(struct pldm_get_firmware_parameters_resp) + 879 resp_data->active_comp_image_set_ver_str_len; 880 pending_comp_image_set_ver_str->length = 881 resp_data->pending_comp_image_set_ver_str_len; 882 } else { 883 pending_comp_image_set_ver_str->ptr = NULL; 884 pending_comp_image_set_ver_str->length = 0; 885 } 886 887 if (payload_length > partial_response_length && resp_data->comp_count) { 888 comp_parameter_table->ptr = 889 msg->payload + 890 sizeof(struct pldm_get_firmware_parameters_resp) + 891 resp_data->active_comp_image_set_ver_str_len + 892 resp_data->pending_comp_image_set_ver_str_len; 893 comp_parameter_table->length = 894 payload_length - partial_response_length; 895 } else { 896 comp_parameter_table->ptr = NULL; 897 comp_parameter_table->length = 0; 898 } 899 900 return PLDM_SUCCESS; 901 } 902 903 LIBPLDM_ABI_TESTING 904 int encode_get_firmware_parameters_resp( 905 uint8_t instance_id, 906 const struct pldm_get_firmware_parameters_resp_full *resp_data, 907 struct pldm_msg *msg, size_t *payload_length) 908 { 909 int rc; 910 struct pldm_msgbuf _buf; 911 struct pldm_msgbuf *buf = &_buf; 912 913 if (resp_data == NULL || msg == NULL || payload_length == NULL) { 914 return -EINVAL; 915 } 916 917 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 918 PLDM_GET_FIRMWARE_PARAMETERS, msg); 919 if (rc) { 920 return -EINVAL; 921 } 922 923 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 924 if (rc) { 925 return rc; 926 } 927 928 pldm_msgbuf_insert(buf, resp_data->completion_code); 929 pldm_msgbuf_insert(buf, resp_data->capabilities_during_update.value); 930 pldm_msgbuf_insert(buf, resp_data->comp_count); 931 pldm_msgbuf_insert(buf, 932 resp_data->active_comp_image_set_ver_str.str_type); 933 pldm_msgbuf_insert(buf, 934 resp_data->active_comp_image_set_ver_str.str_len); 935 pldm_msgbuf_insert(buf, 936 resp_data->pending_comp_image_set_ver_str.str_type); 937 pldm_msgbuf_insert(buf, 938 resp_data->pending_comp_image_set_ver_str.str_len); 939 /* String data appended */ 940 rc = pldm_msgbuf_insert_array( 941 buf, resp_data->active_comp_image_set_ver_str.str_len, 942 resp_data->active_comp_image_set_ver_str.str_data, 943 resp_data->active_comp_image_set_ver_str.str_len); 944 if (rc) { 945 return rc; 946 } 947 rc = pldm_msgbuf_insert_array( 948 buf, resp_data->pending_comp_image_set_ver_str.str_len, 949 resp_data->pending_comp_image_set_ver_str.str_data, 950 resp_data->pending_comp_image_set_ver_str.str_len); 951 if (rc) { 952 return rc; 953 } 954 955 /* Further calls to encode_get_firmware_parameters_resp_comp_entry 956 * will populate the remainder */ 957 958 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 959 } 960 961 LIBPLDM_ABI_TESTING 962 int encode_get_firmware_parameters_resp_comp_entry( 963 const struct pldm_component_parameter_entry_full *comp, 964 uint8_t *payload, size_t *payload_length) 965 { 966 int rc; 967 struct pldm_msgbuf _buf; 968 struct pldm_msgbuf *buf = &_buf; 969 970 if (comp == NULL || payload == NULL || payload_length == NULL) { 971 return -EINVAL; 972 } 973 974 rc = pldm_msgbuf_init_errno(buf, 0, payload, *payload_length); 975 if (rc) { 976 return rc; 977 } 978 979 pldm_msgbuf_insert(buf, comp->comp_classification); 980 pldm_msgbuf_insert(buf, comp->comp_identifier); 981 pldm_msgbuf_insert(buf, comp->comp_classification_index); 982 983 pldm_msgbuf_insert(buf, comp->active_ver.comparison_stamp); 984 pldm_msgbuf_insert(buf, (uint8_t)comp->active_ver.str.str_type); 985 pldm_msgbuf_insert(buf, comp->active_ver.str.str_len); 986 rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 987 comp->active_ver.date, 988 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN); 989 if (rc) { 990 return rc; 991 } 992 993 pldm_msgbuf_insert(buf, comp->pending_ver.comparison_stamp); 994 pldm_msgbuf_insert(buf, (uint8_t)comp->pending_ver.str.str_type); 995 pldm_msgbuf_insert(buf, comp->pending_ver.str.str_len); 996 rc = pldm_msgbuf_insert_array(buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 997 comp->pending_ver.date, 998 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN); 999 if (rc) { 1000 return rc; 1001 } 1002 1003 pldm_msgbuf_insert(buf, comp->comp_activation_methods.value); 1004 pldm_msgbuf_insert(buf, comp->capabilities_during_update.value); 1005 1006 rc = pldm_msgbuf_insert_array(buf, comp->active_ver.str.str_len, 1007 comp->active_ver.str.str_data, 1008 comp->active_ver.str.str_len); 1009 if (rc) { 1010 return rc; 1011 } 1012 rc = pldm_msgbuf_insert_array(buf, comp->pending_ver.str.str_len, 1013 comp->pending_ver.str.str_data, 1014 comp->pending_ver.str.str_len); 1015 if (rc) { 1016 return rc; 1017 } 1018 1019 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 1020 } 1021 1022 LIBPLDM_ABI_STABLE 1023 int decode_get_firmware_parameters_resp_comp_entry( 1024 const uint8_t *data, size_t length, 1025 struct pldm_component_parameter_entry *component_data, 1026 struct variable_field *active_comp_ver_str, 1027 struct variable_field *pending_comp_ver_str) 1028 { 1029 if (data == NULL || component_data == NULL || 1030 active_comp_ver_str == NULL || pending_comp_ver_str == NULL) { 1031 return PLDM_ERROR_INVALID_DATA; 1032 } 1033 1034 if (length < sizeof(struct pldm_component_parameter_entry)) { 1035 return PLDM_ERROR_INVALID_LENGTH; 1036 } 1037 1038 struct pldm_component_parameter_entry *entry = 1039 (struct pldm_component_parameter_entry *)(data); 1040 1041 size_t entry_length = sizeof(struct pldm_component_parameter_entry) + 1042 entry->active_comp_ver_str_len + 1043 entry->pending_comp_ver_str_len; 1044 1045 if (length < entry_length) { 1046 return PLDM_ERROR_INVALID_LENGTH; 1047 } 1048 1049 component_data->comp_classification = 1050 le16toh(entry->comp_classification); 1051 component_data->comp_identifier = le16toh(entry->comp_identifier); 1052 component_data->comp_classification_index = 1053 entry->comp_classification_index; 1054 component_data->active_comp_comparison_stamp = 1055 le32toh(entry->active_comp_comparison_stamp); 1056 component_data->active_comp_ver_str_type = 1057 entry->active_comp_ver_str_type; 1058 component_data->active_comp_ver_str_len = 1059 entry->active_comp_ver_str_len; 1060 memcpy(component_data->active_comp_release_date, 1061 entry->active_comp_release_date, 1062 sizeof(entry->active_comp_release_date)); 1063 component_data->pending_comp_comparison_stamp = 1064 le32toh(entry->pending_comp_comparison_stamp); 1065 component_data->pending_comp_ver_str_type = 1066 entry->pending_comp_ver_str_type; 1067 component_data->pending_comp_ver_str_len = 1068 entry->pending_comp_ver_str_len; 1069 memcpy(component_data->pending_comp_release_date, 1070 entry->pending_comp_release_date, 1071 sizeof(entry->pending_comp_release_date)); 1072 component_data->comp_activation_methods.value = 1073 le16toh(entry->comp_activation_methods.value); 1074 component_data->capabilities_during_update.value = 1075 le32toh(entry->capabilities_during_update.value); 1076 1077 if (entry->active_comp_ver_str_len != 0) { 1078 active_comp_ver_str->ptr = 1079 data + sizeof(struct pldm_component_parameter_entry); 1080 active_comp_ver_str->length = entry->active_comp_ver_str_len; 1081 } else { 1082 active_comp_ver_str->ptr = NULL; 1083 active_comp_ver_str->length = 0; 1084 } 1085 1086 if (entry->pending_comp_ver_str_len != 0) { 1087 pending_comp_ver_str->ptr = 1088 data + sizeof(struct pldm_component_parameter_entry) + 1089 entry->active_comp_ver_str_len; 1090 pending_comp_ver_str->length = entry->pending_comp_ver_str_len; 1091 } else { 1092 pending_comp_ver_str->ptr = NULL; 1093 pending_comp_ver_str->length = 0; 1094 } 1095 return PLDM_SUCCESS; 1096 } 1097 1098 LIBPLDM_ABI_TESTING 1099 int encode_query_downstream_devices_req(uint8_t instance_id, 1100 struct pldm_msg *msg) 1101 { 1102 if (msg == NULL) { 1103 return -EINVAL; 1104 } 1105 1106 return encode_pldm_header_only_errno(PLDM_REQUEST, instance_id, 1107 PLDM_FWUP, 1108 PLDM_QUERY_DOWNSTREAM_DEVICES, 1109 msg); 1110 } 1111 1112 LIBPLDM_ABI_TESTING 1113 int decode_query_downstream_devices_resp( 1114 const struct pldm_msg *msg, size_t payload_length, 1115 struct pldm_query_downstream_devices_resp *resp_data) 1116 { 1117 struct pldm_msgbuf _buf; 1118 struct pldm_msgbuf *buf = &_buf; 1119 int rc; 1120 1121 if (msg == NULL || resp_data == NULL || !payload_length) { 1122 return -EINVAL; 1123 } 1124 1125 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 1126 msg->payload, payload_length); 1127 if (rc) { 1128 return rc; 1129 } 1130 1131 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 1132 if (rc) { 1133 return rc; 1134 } 1135 if (PLDM_SUCCESS != resp_data->completion_code) { 1136 // Return the CC directly without decoding the rest of the payload 1137 return 0; 1138 } 1139 1140 if (payload_length < PLDM_QUERY_DOWNSTREAM_DEVICES_RESP_BYTES) { 1141 return -EBADMSG; 1142 } 1143 1144 rc = pldm_msgbuf_extract(buf, 1145 resp_data->downstream_device_update_supported); 1146 if (rc) { 1147 return rc; 1148 } 1149 1150 if (!is_downstream_device_update_support_valid( 1151 resp_data->downstream_device_update_supported)) { 1152 return -EINVAL; 1153 } 1154 1155 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices); 1156 pldm_msgbuf_extract(buf, resp_data->max_number_of_downstream_devices); 1157 pldm_msgbuf_extract(buf, resp_data->capabilities.value); 1158 1159 return pldm_msgbuf_destroy_consumed(buf); 1160 } 1161 1162 LIBPLDM_ABI_TESTING 1163 int encode_query_downstream_identifiers_req( 1164 uint8_t instance_id, 1165 const struct pldm_query_downstream_identifiers_req *params_req, 1166 struct pldm_msg *msg, size_t payload_length) 1167 { 1168 struct pldm_msgbuf _buf; 1169 struct pldm_msgbuf *buf = &_buf; 1170 int rc; 1171 1172 if (!msg || !params_req) { 1173 return -EINVAL; 1174 } 1175 1176 if (!is_transfer_operation_flag_valid( 1177 (enum transfer_op_flag) 1178 params_req->transfer_operation_flag)) { 1179 return -EINVAL; 1180 } 1181 1182 struct pldm_header_info header = { 0 }; 1183 header.instance = instance_id; 1184 header.msg_type = PLDM_REQUEST; 1185 header.pldm_type = PLDM_FWUP; 1186 header.command = PLDM_QUERY_DOWNSTREAM_IDENTIFIERS; 1187 rc = pack_pldm_header_errno(&header, &(msg->hdr)); 1188 if (rc) { 1189 return rc; 1190 } 1191 1192 rc = pldm_msgbuf_init_errno(buf, 1193 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES, 1194 msg->payload, payload_length); 1195 if (rc) { 1196 return rc; 1197 } 1198 1199 pldm_msgbuf_insert(buf, params_req->data_transfer_handle); 1200 // Data correctness has been verified, cast it to 1-byte data directly. 1201 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag); 1202 1203 return pldm_msgbuf_destroy(buf); 1204 } 1205 1206 LIBPLDM_ABI_TESTING 1207 int decode_query_downstream_identifiers_resp( 1208 const struct pldm_msg *msg, size_t payload_length, 1209 struct pldm_query_downstream_identifiers_resp *resp_data, 1210 struct pldm_downstream_device_iter *iter) 1211 { 1212 struct pldm_msgbuf _buf; 1213 struct pldm_msgbuf *buf = &_buf; 1214 void *remaining = NULL; 1215 int rc = 0; 1216 1217 if (msg == NULL || resp_data == NULL || iter == NULL || 1218 !payload_length) { 1219 return -EINVAL; 1220 } 1221 1222 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 1223 msg->payload, payload_length); 1224 if (rc) { 1225 return rc; 1226 } 1227 1228 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 1229 if (rc) { 1230 return rc; 1231 } 1232 if (PLDM_SUCCESS != resp_data->completion_code) { 1233 return 0; 1234 } 1235 1236 if (payload_length < PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_RESP_MIN_LEN) { 1237 return -EBADMSG; 1238 } 1239 1240 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle); 1241 pldm_msgbuf_extract(buf, resp_data->transfer_flag); 1242 1243 rc = pldm_msgbuf_extract(buf, resp_data->downstream_devices_length); 1244 if (rc) { 1245 return rc; 1246 } 1247 1248 pldm_msgbuf_extract(buf, resp_data->number_of_downstream_devices); 1249 rc = pldm_msgbuf_span_required( 1250 buf, resp_data->downstream_devices_length, &remaining); 1251 if (rc) { 1252 return rc; 1253 } 1254 1255 rc = pldm_msgbuf_destroy(buf); 1256 if (rc) { 1257 return rc; 1258 } 1259 1260 iter->field.ptr = remaining; 1261 iter->field.length = resp_data->downstream_devices_length; 1262 iter->devs = resp_data->number_of_downstream_devices; 1263 1264 return 0; 1265 } 1266 1267 LIBPLDM_ABI_TESTING 1268 int decode_pldm_downstream_device_from_iter( 1269 struct pldm_downstream_device_iter *iter, 1270 struct pldm_downstream_device *dev) 1271 { 1272 struct pldm_msgbuf _buf; 1273 struct pldm_msgbuf *buf = &_buf; 1274 int rc; 1275 1276 if (!iter || !dev) { 1277 return -EINVAL; 1278 } 1279 1280 rc = pldm_msgbuf_init_errno(buf, 3, iter->field.ptr, 1281 iter->field.length); 1282 if (rc) { 1283 return rc; 1284 } 1285 1286 pldm_msgbuf_extract(buf, dev->downstream_device_index); 1287 pldm_msgbuf_extract(buf, dev->downstream_descriptor_count); 1288 iter->field.ptr = NULL; 1289 pldm_msgbuf_span_remaining(buf, (void **)&iter->field.ptr, 1290 &iter->field.length); 1291 1292 return pldm_msgbuf_destroy(buf); 1293 } 1294 1295 LIBPLDM_ABI_TESTING 1296 int encode_get_downstream_firmware_parameters_req( 1297 uint8_t instance_id, 1298 const struct pldm_get_downstream_firmware_parameters_req *params_req, 1299 struct pldm_msg *msg, size_t payload_length) 1300 { 1301 struct pldm_msgbuf _buf; 1302 struct pldm_msgbuf *buf = &_buf; 1303 int rc; 1304 1305 if (!msg || !params_req) { 1306 return -EINVAL; 1307 } 1308 1309 rc = pldm_msgbuf_init_errno( 1310 buf, PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES, 1311 msg->payload, payload_length); 1312 if (rc < 0) { 1313 return rc; 1314 } 1315 1316 if (!is_transfer_operation_flag_valid( 1317 (enum transfer_op_flag) 1318 params_req->transfer_operation_flag)) { 1319 return -EBADMSG; 1320 } 1321 1322 struct pldm_header_info header = { 0 }; 1323 header.instance = instance_id; 1324 header.msg_type = PLDM_REQUEST; 1325 header.pldm_type = PLDM_FWUP; 1326 header.command = PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS; 1327 rc = pack_pldm_header_errno(&header, &msg->hdr); 1328 if (rc < 0) { 1329 return rc; 1330 } 1331 1332 pldm_msgbuf_insert(buf, params_req->data_transfer_handle); 1333 // Data correctness has been verified, cast it to 1-byte data directly. 1334 pldm_msgbuf_insert(buf, params_req->transfer_operation_flag); 1335 1336 return pldm_msgbuf_destroy(buf); 1337 } 1338 1339 LIBPLDM_ABI_TESTING 1340 int decode_get_downstream_firmware_parameters_resp( 1341 const struct pldm_msg *msg, size_t payload_length, 1342 struct pldm_get_downstream_firmware_parameters_resp *resp_data, 1343 struct pldm_downstream_device_parameters_iter *iter) 1344 { 1345 struct pldm_msgbuf _buf; 1346 struct pldm_msgbuf *buf = &_buf; 1347 void *remaining = NULL; 1348 size_t length; 1349 int rc; 1350 1351 if (msg == NULL || resp_data == NULL || iter == NULL) { 1352 return -EINVAL; 1353 } 1354 1355 rc = pldm_msgbuf_init_errno(buf, PLDM_OPTIONAL_COMMAND_RESP_MIN_LEN, 1356 msg->payload, payload_length); 1357 if (rc < 0) { 1358 return rc; 1359 } 1360 1361 rc = pldm_msgbuf_extract(buf, resp_data->completion_code); 1362 if (rc < 0) { 1363 return rc; 1364 } 1365 if (PLDM_SUCCESS != resp_data->completion_code) { 1366 return 0; 1367 } 1368 1369 if (payload_length < 1370 PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_RESP_MIN_LEN) { 1371 return -EBADMSG; 1372 } 1373 1374 pldm_msgbuf_extract(buf, resp_data->next_data_transfer_handle); 1375 pldm_msgbuf_extract(buf, resp_data->transfer_flag); 1376 pldm_msgbuf_extract(buf, 1377 resp_data->fdp_capabilities_during_update.value); 1378 pldm_msgbuf_extract(buf, resp_data->downstream_device_count); 1379 1380 rc = pldm_msgbuf_span_remaining(buf, &remaining, &length); 1381 if (rc) { 1382 return rc; 1383 } 1384 1385 rc = pldm_msgbuf_destroy(buf); 1386 if (rc) { 1387 return rc; 1388 } 1389 1390 iter->field.ptr = remaining; 1391 iter->field.length = length; 1392 iter->entries = resp_data->downstream_device_count; 1393 1394 return 0; 1395 } 1396 1397 LIBPLDM_ABI_TESTING 1398 int decode_pldm_downstream_device_parameters_entry_from_iter( 1399 struct pldm_downstream_device_parameters_iter *iter, 1400 struct pldm_downstream_device_parameters_entry *entry) 1401 { 1402 struct pldm_msgbuf _buf; 1403 struct pldm_msgbuf *buf = &_buf; 1404 void *comp_ver_str; 1405 size_t remaining; 1406 void *cursor; 1407 int rc; 1408 1409 if (iter == NULL || entry == NULL) { 1410 return -EINVAL; 1411 } 1412 1413 rc = pldm_msgbuf_init_errno( 1414 buf, PLDM_DOWNSTREAM_DEVICE_PARAMETERS_ENTRY_MIN_LEN, 1415 iter->field.ptr, iter->field.length); 1416 if (rc < 0) { 1417 return rc; 1418 } 1419 1420 pldm_msgbuf_extract(buf, entry->downstream_device_index); 1421 pldm_msgbuf_extract(buf, entry->active_comp_comparison_stamp); 1422 pldm_msgbuf_extract(buf, entry->active_comp_ver_str_type); 1423 rc = pldm_msgbuf_extract(buf, entry->active_comp_ver_str_len); 1424 if (rc < 0) { 1425 return rc; 1426 } 1427 rc = pldm_msgbuf_extract_array(buf, 1428 PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 1429 entry->active_comp_release_date, 1430 sizeof(entry->active_comp_release_date)); 1431 if (rc < 0) { 1432 return rc; 1433 } 1434 1435 // Fill the last byte with NULL character 1436 entry->active_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] = 1437 '\0'; 1438 1439 pldm_msgbuf_extract(buf, entry->pending_comp_comparison_stamp); 1440 pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_type); 1441 rc = pldm_msgbuf_extract(buf, entry->pending_comp_ver_str_len); 1442 if (rc < 0) { 1443 return rc; 1444 } 1445 1446 rc = pldm_msgbuf_extract_array( 1447 buf, PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN, 1448 entry->pending_comp_release_date, 1449 sizeof(entry->pending_comp_release_date)); 1450 if (rc < 0) { 1451 return rc; 1452 } 1453 1454 // Fill the last byte with NULL character 1455 entry->pending_comp_release_date[PLDM_FWUP_COMPONENT_RELEASE_DATA_LEN] = 1456 '\0'; 1457 1458 pldm_msgbuf_extract(buf, entry->comp_activation_methods.value); 1459 pldm_msgbuf_extract(buf, entry->capabilities_during_update.value); 1460 1461 comp_ver_str = NULL; 1462 pldm_msgbuf_span_required(buf, entry->active_comp_ver_str_len, 1463 &comp_ver_str); 1464 entry->active_comp_ver_str = comp_ver_str; 1465 1466 comp_ver_str = NULL; 1467 pldm_msgbuf_span_required(buf, entry->pending_comp_ver_str_len, 1468 &comp_ver_str); 1469 entry->pending_comp_ver_str = comp_ver_str; 1470 1471 cursor = NULL; 1472 rc = pldm_msgbuf_span_remaining(buf, &cursor, &remaining); 1473 if (rc < 0) { 1474 return rc; 1475 } 1476 1477 iter->field.ptr = cursor; 1478 iter->field.length = remaining; 1479 1480 return 0; 1481 } 1482 1483 LIBPLDM_ABI_STABLE 1484 int encode_request_update_req(uint8_t instance_id, uint32_t max_transfer_size, 1485 uint16_t num_of_comp, 1486 uint8_t max_outstanding_transfer_req, 1487 uint16_t pkg_data_len, 1488 uint8_t comp_image_set_ver_str_type, 1489 uint8_t comp_image_set_ver_str_len, 1490 const struct variable_field *comp_img_set_ver_str, 1491 struct pldm_msg *msg, size_t payload_length) 1492 { 1493 if (comp_img_set_ver_str == NULL || comp_img_set_ver_str->ptr == NULL || 1494 msg == NULL) { 1495 return PLDM_ERROR_INVALID_DATA; 1496 } 1497 1498 if (payload_length != sizeof(struct pldm_request_update_req) + 1499 comp_img_set_ver_str->length) { 1500 return PLDM_ERROR_INVALID_LENGTH; 1501 } 1502 1503 if ((comp_image_set_ver_str_len == 0) || 1504 (comp_image_set_ver_str_len != comp_img_set_ver_str->length)) { 1505 return PLDM_ERROR_INVALID_DATA; 1506 } 1507 1508 if ((max_transfer_size < PLDM_FWUP_BASELINE_TRANSFER_SIZE) || 1509 (max_outstanding_transfer_req < PLDM_FWUP_MIN_OUTSTANDING_REQ)) { 1510 return PLDM_ERROR_INVALID_DATA; 1511 } 1512 1513 if (!is_string_type_valid(comp_image_set_ver_str_type)) { 1514 return PLDM_ERROR_INVALID_DATA; 1515 } 1516 1517 struct pldm_header_info header = { 0 }; 1518 header.instance = instance_id; 1519 header.msg_type = PLDM_REQUEST; 1520 header.pldm_type = PLDM_FWUP; 1521 header.command = PLDM_REQUEST_UPDATE; 1522 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1523 if (rc) { 1524 return rc; 1525 } 1526 1527 struct pldm_request_update_req *request = 1528 (struct pldm_request_update_req *)msg->payload; 1529 1530 request->max_transfer_size = htole32(max_transfer_size); 1531 request->num_of_comp = htole16(num_of_comp); 1532 request->max_outstanding_transfer_req = max_outstanding_transfer_req; 1533 request->pkg_data_len = htole16(pkg_data_len); 1534 request->comp_image_set_ver_str_type = comp_image_set_ver_str_type; 1535 request->comp_image_set_ver_str_len = comp_image_set_ver_str_len; 1536 1537 memcpy(msg->payload + sizeof(struct pldm_request_update_req), 1538 comp_img_set_ver_str->ptr, comp_img_set_ver_str->length); 1539 1540 return PLDM_SUCCESS; 1541 } 1542 1543 LIBPLDM_ABI_TESTING 1544 int decode_request_update_req(const struct pldm_msg *msg, size_t payload_length, 1545 struct pldm_request_update_req_full *req) 1546 { 1547 int rc; 1548 uint8_t t; 1549 struct pldm_msgbuf _buf; 1550 struct pldm_msgbuf *buf = &_buf; 1551 1552 if (msg == NULL || req == NULL) { 1553 return -EINVAL; 1554 } 1555 1556 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length); 1557 if (rc) { 1558 return rc; 1559 } 1560 1561 pldm_msgbuf_extract(buf, req->max_transfer_size); 1562 pldm_msgbuf_extract(buf, req->num_of_comp); 1563 pldm_msgbuf_extract(buf, req->max_outstanding_transfer_req); 1564 pldm_msgbuf_extract(buf, req->pkg_data_len); 1565 rc = pldm_msgbuf_extract(buf, t); 1566 if (rc) { 1567 return rc; 1568 } 1569 if (t > PLDM_STR_TYPE_UTF_16BE) { 1570 return -EBADMSG; 1571 } 1572 req->image_set_ver.str_type = (enum pldm_firmware_update_string_type)t; 1573 pldm_msgbuf_extract(buf, req->image_set_ver.str_len); 1574 if (rc) { 1575 return rc; 1576 } 1577 1578 rc = pldm_msgbuf_extract_array(buf, req->image_set_ver.str_len, 1579 req->image_set_ver.str_data, 1580 PLDM_FIRMWARE_MAX_STRING); 1581 if (rc) { 1582 return rc; 1583 } 1584 1585 return pldm_msgbuf_destroy_consumed(buf); 1586 } 1587 1588 LIBPLDM_ABI_STABLE 1589 int decode_request_update_resp(const struct pldm_msg *msg, 1590 size_t payload_length, uint8_t *completion_code, 1591 uint16_t *fd_meta_data_len, 1592 uint8_t *fd_will_send_pkg_data) 1593 { 1594 if (msg == NULL || completion_code == NULL || 1595 fd_meta_data_len == NULL || fd_will_send_pkg_data == NULL || 1596 !payload_length) { 1597 return PLDM_ERROR_INVALID_DATA; 1598 } 1599 1600 *completion_code = msg->payload[0]; 1601 if (*completion_code != PLDM_SUCCESS) { 1602 return PLDM_SUCCESS; 1603 } 1604 1605 if (payload_length != sizeof(struct pldm_request_update_resp)) { 1606 return PLDM_ERROR_INVALID_LENGTH; 1607 } 1608 1609 struct pldm_request_update_resp *response = 1610 (struct pldm_request_update_resp *)msg->payload; 1611 1612 *fd_meta_data_len = le16toh(response->fd_meta_data_len); 1613 *fd_will_send_pkg_data = response->fd_will_send_pkg_data; 1614 1615 return PLDM_SUCCESS; 1616 } 1617 1618 LIBPLDM_ABI_TESTING 1619 int encode_request_update_resp(uint8_t instance_id, 1620 const struct pldm_request_update_resp *resp_data, 1621 struct pldm_msg *msg, size_t *payload_length) 1622 { 1623 int rc; 1624 struct pldm_msgbuf _buf; 1625 struct pldm_msgbuf *buf = &_buf; 1626 1627 if (msg == NULL || payload_length == NULL) { 1628 return -EINVAL; 1629 } 1630 1631 struct pldm_header_info header = { 1632 .instance = instance_id, 1633 .msg_type = PLDM_RESPONSE, 1634 .pldm_type = PLDM_FWUP, 1635 .command = PLDM_REQUEST_UPDATE, 1636 }; 1637 rc = pack_pldm_header(&header, &(msg->hdr)); 1638 if (rc) { 1639 return -EINVAL; 1640 } 1641 1642 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 1643 if (rc) { 1644 return rc; 1645 } 1646 1647 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 1648 pldm_msgbuf_insert(buf, resp_data->fd_meta_data_len); 1649 pldm_msgbuf_insert(buf, resp_data->fd_will_send_pkg_data); 1650 1651 /* TODO: DSP0267 1.3.0 adds GetPackageDataMaximumTransferSize */ 1652 1653 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 1654 } 1655 1656 LIBPLDM_ABI_STABLE 1657 int encode_pass_component_table_req(uint8_t instance_id, uint8_t transfer_flag, 1658 uint16_t comp_classification, 1659 uint16_t comp_identifier, 1660 uint8_t comp_classification_index, 1661 uint32_t comp_comparison_stamp, 1662 uint8_t comp_ver_str_type, 1663 uint8_t comp_ver_str_len, 1664 const struct variable_field *comp_ver_str, 1665 struct pldm_msg *msg, size_t payload_length) 1666 { 1667 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) { 1668 return PLDM_ERROR_INVALID_DATA; 1669 } 1670 1671 if (payload_length != sizeof(struct pldm_pass_component_table_req) + 1672 comp_ver_str->length) { 1673 return PLDM_ERROR_INVALID_LENGTH; 1674 } 1675 1676 if ((comp_ver_str_len == 0) || 1677 (comp_ver_str_len != comp_ver_str->length)) { 1678 return PLDM_ERROR_INVALID_DATA; 1679 } 1680 1681 if (!is_transfer_flag_valid(transfer_flag)) { 1682 return PLDM_INVALID_TRANSFER_OPERATION_FLAG; 1683 } 1684 1685 if (!is_string_type_valid(comp_ver_str_type)) { 1686 return PLDM_ERROR_INVALID_DATA; 1687 } 1688 1689 struct pldm_header_info header = { 0 }; 1690 header.instance = instance_id; 1691 header.msg_type = PLDM_REQUEST; 1692 header.pldm_type = PLDM_FWUP; 1693 header.command = PLDM_PASS_COMPONENT_TABLE; 1694 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1695 if (rc) { 1696 return rc; 1697 } 1698 1699 struct pldm_pass_component_table_req *request = 1700 (struct pldm_pass_component_table_req *)msg->payload; 1701 1702 request->transfer_flag = transfer_flag; 1703 request->comp_classification = htole16(comp_classification); 1704 request->comp_identifier = htole16(comp_identifier); 1705 request->comp_classification_index = comp_classification_index; 1706 request->comp_comparison_stamp = htole32(comp_comparison_stamp); 1707 request->comp_ver_str_type = comp_ver_str_type; 1708 request->comp_ver_str_len = comp_ver_str_len; 1709 1710 memcpy(msg->payload + sizeof(struct pldm_pass_component_table_req), 1711 comp_ver_str->ptr, comp_ver_str->length); 1712 1713 return PLDM_SUCCESS; 1714 } 1715 1716 LIBPLDM_ABI_TESTING 1717 int decode_pass_component_table_req( 1718 const struct pldm_msg *msg, size_t payload_length, 1719 struct pldm_pass_component_table_req_full *pcomp) 1720 { 1721 int rc; 1722 uint8_t t; 1723 struct pldm_msgbuf _buf; 1724 struct pldm_msgbuf *buf = &_buf; 1725 1726 if (msg == NULL || pcomp == NULL) { 1727 return -EINVAL; 1728 } 1729 1730 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length); 1731 if (rc) { 1732 return rc; 1733 } 1734 1735 pldm_msgbuf_extract(buf, pcomp->transfer_flag); 1736 pldm_msgbuf_extract(buf, pcomp->comp_classification); 1737 pldm_msgbuf_extract(buf, pcomp->comp_identifier); 1738 pldm_msgbuf_extract(buf, pcomp->comp_classification_index); 1739 pldm_msgbuf_extract(buf, pcomp->comp_comparison_stamp); 1740 rc = pldm_msgbuf_extract(buf, t); 1741 if (rc) { 1742 return rc; 1743 } 1744 if (t > PLDM_STR_TYPE_UTF_16BE) { 1745 return -EBADMSG; 1746 } 1747 pcomp->version.str_type = (enum pldm_firmware_update_string_type)t; 1748 rc = pldm_msgbuf_extract(buf, pcomp->version.str_len); 1749 if (rc) { 1750 return rc; 1751 } 1752 rc = pldm_msgbuf_extract_array(buf, pcomp->version.str_len, 1753 pcomp->version.str_data, 1754 PLDM_FIRMWARE_MAX_STRING); 1755 if (rc) { 1756 return rc; 1757 } 1758 1759 return pldm_msgbuf_destroy_consumed(buf); 1760 } 1761 1762 LIBPLDM_ABI_STABLE 1763 int decode_pass_component_table_resp(const struct pldm_msg *msg, 1764 const size_t payload_length, 1765 uint8_t *completion_code, 1766 uint8_t *comp_resp, 1767 uint8_t *comp_resp_code) 1768 { 1769 if (msg == NULL || completion_code == NULL || comp_resp == NULL || 1770 comp_resp_code == NULL || !payload_length) { 1771 return PLDM_ERROR_INVALID_DATA; 1772 } 1773 1774 *completion_code = msg->payload[0]; 1775 if (*completion_code != PLDM_SUCCESS) { 1776 return PLDM_SUCCESS; 1777 } 1778 1779 if (payload_length != sizeof(struct pldm_pass_component_table_resp)) { 1780 return PLDM_ERROR_INVALID_LENGTH; 1781 } 1782 1783 struct pldm_pass_component_table_resp *response = 1784 (struct pldm_pass_component_table_resp *)msg->payload; 1785 1786 if (!is_comp_resp_valid(response->comp_resp)) { 1787 return PLDM_ERROR_INVALID_DATA; 1788 } 1789 1790 if (!is_comp_resp_code_valid(response->comp_resp_code)) { 1791 return PLDM_ERROR_INVALID_DATA; 1792 } 1793 1794 *comp_resp = response->comp_resp; 1795 *comp_resp_code = response->comp_resp_code; 1796 1797 return PLDM_SUCCESS; 1798 } 1799 1800 LIBPLDM_ABI_TESTING 1801 int encode_pass_component_table_resp( 1802 uint8_t instance_id, 1803 const struct pldm_pass_component_table_resp *resp_data, 1804 struct pldm_msg *msg, size_t *payload_length) 1805 { 1806 int rc; 1807 struct pldm_msgbuf _buf; 1808 struct pldm_msgbuf *buf = &_buf; 1809 1810 if (msg == NULL || payload_length == NULL) { 1811 return -EINVAL; 1812 } 1813 1814 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 1815 PLDM_PASS_COMPONENT_TABLE, msg); 1816 if (rc) { 1817 return -EINVAL; 1818 } 1819 1820 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 1821 if (rc) { 1822 return rc; 1823 } 1824 1825 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 1826 pldm_msgbuf_insert(buf, resp_data->comp_resp); 1827 pldm_msgbuf_insert(buf, resp_data->comp_resp_code); 1828 1829 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 1830 } 1831 1832 LIBPLDM_ABI_STABLE 1833 int encode_update_component_req( 1834 uint8_t instance_id, uint16_t comp_classification, 1835 uint16_t comp_identifier, uint8_t comp_classification_index, 1836 uint32_t comp_comparison_stamp, uint32_t comp_image_size, 1837 bitfield32_t update_option_flags, uint8_t comp_ver_str_type, 1838 uint8_t comp_ver_str_len, const struct variable_field *comp_ver_str, 1839 struct pldm_msg *msg, size_t payload_length) 1840 { 1841 if (comp_ver_str == NULL || comp_ver_str->ptr == NULL || msg == NULL) { 1842 return PLDM_ERROR_INVALID_DATA; 1843 } 1844 1845 if (payload_length != 1846 sizeof(struct pldm_update_component_req) + comp_ver_str->length) { 1847 return PLDM_ERROR_INVALID_LENGTH; 1848 } 1849 1850 if (!comp_image_size) { 1851 return PLDM_ERROR_INVALID_DATA; 1852 } 1853 1854 if ((comp_ver_str_len == 0) || 1855 (comp_ver_str_len != comp_ver_str->length)) { 1856 return PLDM_ERROR_INVALID_DATA; 1857 } 1858 1859 if (!is_string_type_valid(comp_ver_str_type)) { 1860 return PLDM_ERROR_INVALID_DATA; 1861 } 1862 1863 struct pldm_header_info header = { 0 }; 1864 header.instance = instance_id; 1865 header.msg_type = PLDM_REQUEST; 1866 header.pldm_type = PLDM_FWUP; 1867 header.command = PLDM_UPDATE_COMPONENT; 1868 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 1869 if (rc) { 1870 return rc; 1871 } 1872 1873 struct pldm_update_component_req *request = 1874 (struct pldm_update_component_req *)msg->payload; 1875 1876 request->comp_classification = htole16(comp_classification); 1877 request->comp_identifier = htole16(comp_identifier); 1878 request->comp_classification_index = comp_classification_index; 1879 request->comp_comparison_stamp = htole32(comp_comparison_stamp); 1880 request->comp_image_size = htole32(comp_image_size); 1881 request->update_option_flags.value = htole32(update_option_flags.value); 1882 request->comp_ver_str_type = comp_ver_str_type; 1883 request->comp_ver_str_len = comp_ver_str_len; 1884 1885 memcpy(msg->payload + sizeof(struct pldm_update_component_req), 1886 comp_ver_str->ptr, comp_ver_str->length); 1887 1888 return PLDM_SUCCESS; 1889 } 1890 1891 LIBPLDM_ABI_TESTING 1892 int decode_update_component_req(const struct pldm_msg *msg, 1893 size_t payload_length, 1894 struct pldm_update_component_req_full *up) 1895 { 1896 int rc; 1897 uint8_t t; 1898 struct pldm_msgbuf _buf; 1899 struct pldm_msgbuf *buf = &_buf; 1900 1901 if (msg == NULL || up == NULL) { 1902 return -EINVAL; 1903 } 1904 1905 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length); 1906 if (rc) { 1907 return rc; 1908 } 1909 1910 pldm_msgbuf_extract(buf, up->comp_classification); 1911 pldm_msgbuf_extract(buf, up->comp_identifier); 1912 pldm_msgbuf_extract(buf, up->comp_classification_index); 1913 pldm_msgbuf_extract(buf, up->comp_comparison_stamp); 1914 pldm_msgbuf_extract(buf, up->comp_image_size); 1915 pldm_msgbuf_extract(buf, up->update_option_flags.value); 1916 rc = pldm_msgbuf_extract(buf, t); 1917 if (rc) { 1918 return rc; 1919 } 1920 if (t > PLDM_STR_TYPE_UTF_16BE) { 1921 return -EBADMSG; 1922 } 1923 up->version.str_type = (enum pldm_firmware_update_string_type)t; 1924 rc = pldm_msgbuf_extract(buf, up->version.str_len); 1925 if (rc) { 1926 return rc; 1927 } 1928 rc = pldm_msgbuf_extract_array(buf, up->version.str_len, 1929 up->version.str_data, 1930 PLDM_FIRMWARE_MAX_STRING); 1931 if (rc) { 1932 return rc; 1933 } 1934 1935 if (buf->remaining != 0) { 1936 return -EINVAL; 1937 } 1938 1939 return 0; 1940 } 1941 1942 LIBPLDM_ABI_STABLE 1943 int decode_update_component_resp(const struct pldm_msg *msg, 1944 size_t payload_length, 1945 uint8_t *completion_code, 1946 uint8_t *comp_compatibility_resp, 1947 uint8_t *comp_compatibility_resp_code, 1948 bitfield32_t *update_option_flags_enabled, 1949 uint16_t *time_before_req_fw_data) 1950 { 1951 if (msg == NULL || completion_code == NULL || 1952 comp_compatibility_resp == NULL || 1953 comp_compatibility_resp_code == NULL || 1954 update_option_flags_enabled == NULL || 1955 time_before_req_fw_data == NULL || !payload_length) { 1956 return PLDM_ERROR_INVALID_DATA; 1957 } 1958 1959 *completion_code = msg->payload[0]; 1960 if (*completion_code != PLDM_SUCCESS) { 1961 return PLDM_SUCCESS; 1962 } 1963 1964 if (payload_length != sizeof(struct pldm_update_component_resp)) { 1965 return PLDM_ERROR_INVALID_LENGTH; 1966 } 1967 1968 struct pldm_update_component_resp *response = 1969 (struct pldm_update_component_resp *)msg->payload; 1970 1971 if (!is_comp_compatibility_resp_valid( 1972 response->comp_compatibility_resp)) { 1973 return PLDM_ERROR_INVALID_DATA; 1974 } 1975 1976 if (!is_comp_compatibility_resp_code_valid( 1977 response->comp_compatibility_resp_code)) { 1978 return PLDM_ERROR_INVALID_DATA; 1979 } 1980 1981 *comp_compatibility_resp = response->comp_compatibility_resp; 1982 *comp_compatibility_resp_code = response->comp_compatibility_resp_code; 1983 update_option_flags_enabled->value = 1984 le32toh(response->update_option_flags_enabled.value); 1985 *time_before_req_fw_data = le16toh(response->time_before_req_fw_data); 1986 1987 return PLDM_SUCCESS; 1988 } 1989 1990 LIBPLDM_ABI_TESTING 1991 int encode_update_component_resp( 1992 uint8_t instance_id, const struct pldm_update_component_resp *resp_data, 1993 struct pldm_msg *msg, size_t *payload_length) 1994 { 1995 int rc; 1996 struct pldm_msgbuf _buf; 1997 struct pldm_msgbuf *buf = &_buf; 1998 1999 if (msg == NULL || payload_length == NULL) { 2000 return -EINVAL; 2001 } 2002 2003 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 2004 PLDM_UPDATE_COMPONENT, msg); 2005 if (rc) { 2006 return -EINVAL; 2007 } 2008 2009 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2010 if (rc) { 2011 return rc; 2012 } 2013 2014 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 2015 pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp); 2016 pldm_msgbuf_insert(buf, resp_data->comp_compatibility_resp_code); 2017 pldm_msgbuf_insert(buf, resp_data->update_option_flags_enabled.value); 2018 pldm_msgbuf_insert(buf, resp_data->time_before_req_fw_data); 2019 2020 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 2021 } 2022 2023 LIBPLDM_ABI_STABLE 2024 int decode_request_firmware_data_req(const struct pldm_msg *msg, 2025 size_t payload_length, uint32_t *offset, 2026 uint32_t *length) 2027 { 2028 if (msg == NULL || offset == NULL || length == NULL) { 2029 return PLDM_ERROR_INVALID_DATA; 2030 } 2031 if (payload_length != sizeof(struct pldm_request_firmware_data_req)) { 2032 return PLDM_ERROR_INVALID_LENGTH; 2033 } 2034 struct pldm_request_firmware_data_req *request = 2035 (struct pldm_request_firmware_data_req *)msg->payload; 2036 *offset = le32toh(request->offset); 2037 *length = le32toh(request->length); 2038 2039 if (*length < PLDM_FWUP_BASELINE_TRANSFER_SIZE) { 2040 return PLDM_FWUP_INVALID_TRANSFER_LENGTH; 2041 } 2042 2043 return PLDM_SUCCESS; 2044 } 2045 2046 LIBPLDM_ABI_TESTING 2047 int encode_request_firmware_data_req( 2048 uint8_t instance_id, 2049 const struct pldm_request_firmware_data_req *req_params, 2050 struct pldm_msg *msg, size_t *payload_length) 2051 { 2052 int rc; 2053 struct pldm_msgbuf _buf; 2054 struct pldm_msgbuf *buf = &_buf; 2055 2056 if (msg == NULL || payload_length == NULL) { 2057 return -EINVAL; 2058 } 2059 2060 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 2061 PLDM_REQUEST_FIRMWARE_DATA, msg); 2062 if (rc) { 2063 return -EINVAL; 2064 } 2065 2066 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2067 if (rc) { 2068 return rc; 2069 } 2070 2071 pldm_msgbuf_insert(buf, req_params->offset); 2072 pldm_msgbuf_insert(buf, req_params->length); 2073 2074 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 2075 } 2076 2077 LIBPLDM_ABI_STABLE 2078 int encode_request_firmware_data_resp(uint8_t instance_id, 2079 uint8_t completion_code, 2080 struct pldm_msg *msg, 2081 size_t payload_length) 2082 { 2083 if (msg == NULL || !payload_length) { 2084 return PLDM_ERROR_INVALID_DATA; 2085 } 2086 2087 struct pldm_header_info header = { 0 }; 2088 header.instance = instance_id; 2089 header.msg_type = PLDM_RESPONSE; 2090 header.pldm_type = PLDM_FWUP; 2091 header.command = PLDM_REQUEST_FIRMWARE_DATA; 2092 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2093 if (rc) { 2094 return rc; 2095 } 2096 2097 msg->payload[0] = completion_code; 2098 2099 return PLDM_SUCCESS; 2100 } 2101 2102 LIBPLDM_ABI_STABLE 2103 int decode_transfer_complete_req(const struct pldm_msg *msg, 2104 size_t payload_length, 2105 uint8_t *transfer_result) 2106 { 2107 if (msg == NULL || transfer_result == NULL) { 2108 return PLDM_ERROR_INVALID_DATA; 2109 } 2110 2111 if (payload_length != sizeof(*transfer_result)) { 2112 return PLDM_ERROR_INVALID_LENGTH; 2113 } 2114 2115 *transfer_result = msg->payload[0]; 2116 return PLDM_SUCCESS; 2117 } 2118 2119 LIBPLDM_ABI_TESTING 2120 int encode_transfer_complete_req(uint8_t instance_id, uint8_t transfer_result, 2121 struct pldm_msg *msg, size_t *payload_length) 2122 { 2123 int rc; 2124 struct pldm_msgbuf _buf; 2125 struct pldm_msgbuf *buf = &_buf; 2126 2127 if (msg == NULL || payload_length == NULL) { 2128 return -EINVAL; 2129 } 2130 2131 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 2132 PLDM_TRANSFER_COMPLETE, msg); 2133 if (rc) { 2134 return -EINVAL; 2135 } 2136 2137 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2138 if (rc) { 2139 return rc; 2140 } 2141 2142 rc = pldm_msgbuf_insert(buf, transfer_result); 2143 if (rc) { 2144 return rc; 2145 } 2146 2147 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 2148 } 2149 2150 LIBPLDM_ABI_STABLE 2151 int encode_transfer_complete_resp(uint8_t instance_id, uint8_t completion_code, 2152 struct pldm_msg *msg, size_t payload_length) 2153 { 2154 if (msg == NULL) { 2155 return PLDM_ERROR_INVALID_DATA; 2156 } 2157 2158 if (payload_length != sizeof(completion_code)) { 2159 return PLDM_ERROR_INVALID_LENGTH; 2160 } 2161 2162 struct pldm_header_info header = { 0 }; 2163 header.instance = instance_id; 2164 header.msg_type = PLDM_RESPONSE; 2165 header.pldm_type = PLDM_FWUP; 2166 header.command = PLDM_TRANSFER_COMPLETE; 2167 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2168 if (rc) { 2169 return rc; 2170 } 2171 2172 msg->payload[0] = completion_code; 2173 2174 return PLDM_SUCCESS; 2175 } 2176 2177 LIBPLDM_ABI_STABLE 2178 int decode_verify_complete_req(const struct pldm_msg *msg, 2179 size_t payload_length, uint8_t *verify_result) 2180 { 2181 if (msg == NULL || verify_result == NULL) { 2182 return PLDM_ERROR_INVALID_DATA; 2183 } 2184 2185 if (payload_length != sizeof(*verify_result)) { 2186 return PLDM_ERROR_INVALID_LENGTH; 2187 } 2188 2189 *verify_result = msg->payload[0]; 2190 return PLDM_SUCCESS; 2191 } 2192 2193 LIBPLDM_ABI_TESTING 2194 int encode_verify_complete_req(uint8_t instance_id, uint8_t verify_result, 2195 struct pldm_msg *msg, size_t *payload_length) 2196 { 2197 int rc; 2198 struct pldm_msgbuf _buf; 2199 struct pldm_msgbuf *buf = &_buf; 2200 2201 if (msg == NULL || payload_length == NULL) { 2202 return -EINVAL; 2203 } 2204 2205 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 2206 PLDM_VERIFY_COMPLETE, msg); 2207 if (rc) { 2208 return EINVAL; 2209 } 2210 2211 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2212 if (rc) { 2213 return rc; 2214 } 2215 2216 rc = pldm_msgbuf_insert(buf, verify_result); 2217 if (rc) { 2218 return rc; 2219 } 2220 2221 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 2222 } 2223 2224 LIBPLDM_ABI_STABLE 2225 int encode_verify_complete_resp(uint8_t instance_id, uint8_t completion_code, 2226 struct pldm_msg *msg, size_t payload_length) 2227 { 2228 if (msg == NULL) { 2229 return PLDM_ERROR_INVALID_DATA; 2230 } 2231 2232 if (payload_length != sizeof(completion_code)) { 2233 return PLDM_ERROR_INVALID_LENGTH; 2234 } 2235 2236 struct pldm_header_info header = { 0 }; 2237 header.instance = instance_id; 2238 header.msg_type = PLDM_RESPONSE; 2239 header.pldm_type = PLDM_FWUP; 2240 header.command = PLDM_VERIFY_COMPLETE; 2241 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2242 if (rc) { 2243 return rc; 2244 } 2245 2246 msg->payload[0] = completion_code; 2247 2248 return PLDM_SUCCESS; 2249 } 2250 2251 LIBPLDM_ABI_STABLE 2252 int decode_apply_complete_req(const struct pldm_msg *msg, size_t payload_length, 2253 uint8_t *apply_result, 2254 bitfield16_t *comp_activation_methods_modification) 2255 { 2256 if (msg == NULL || apply_result == NULL || 2257 comp_activation_methods_modification == NULL) { 2258 return PLDM_ERROR_INVALID_DATA; 2259 } 2260 2261 if (payload_length != sizeof(struct pldm_apply_complete_req)) { 2262 return PLDM_ERROR_INVALID_LENGTH; 2263 } 2264 2265 struct pldm_apply_complete_req *request = 2266 (struct pldm_apply_complete_req *)msg->payload; 2267 2268 *apply_result = request->apply_result; 2269 comp_activation_methods_modification->value = 2270 le16toh(request->comp_activation_methods_modification.value); 2271 2272 if ((*apply_result != PLDM_FWUP_APPLY_SUCCESS_WITH_ACTIVATION_METHOD) && 2273 comp_activation_methods_modification->value) { 2274 return PLDM_ERROR_INVALID_DATA; 2275 } 2276 2277 return PLDM_SUCCESS; 2278 } 2279 2280 LIBPLDM_ABI_TESTING 2281 int encode_apply_complete_req(uint8_t instance_id, 2282 const struct pldm_apply_complete_req *req_data, 2283 struct pldm_msg *msg, size_t *payload_length) 2284 { 2285 int rc; 2286 struct pldm_msgbuf _buf; 2287 struct pldm_msgbuf *buf = &_buf; 2288 2289 if (msg == NULL || payload_length == NULL) { 2290 return -EINVAL; 2291 } 2292 2293 rc = encode_pldm_header_only(PLDM_REQUEST, instance_id, PLDM_FWUP, 2294 PLDM_APPLY_COMPLETE, msg); 2295 if (rc) { 2296 return -EINVAL; 2297 } 2298 2299 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2300 if (rc) { 2301 return rc; 2302 } 2303 2304 pldm_msgbuf_insert(buf, req_data->apply_result); 2305 pldm_msgbuf_insert( 2306 buf, req_data->comp_activation_methods_modification.value); 2307 2308 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 2309 } 2310 2311 LIBPLDM_ABI_STABLE 2312 int encode_apply_complete_resp(uint8_t instance_id, uint8_t completion_code, 2313 struct pldm_msg *msg, size_t payload_length) 2314 { 2315 if (msg == NULL) { 2316 return PLDM_ERROR_INVALID_DATA; 2317 } 2318 2319 if (payload_length != sizeof(completion_code)) { 2320 return PLDM_ERROR_INVALID_LENGTH; 2321 } 2322 2323 struct pldm_header_info header = { 0 }; 2324 header.instance = instance_id; 2325 header.msg_type = PLDM_RESPONSE; 2326 header.pldm_type = PLDM_FWUP; 2327 header.command = PLDM_APPLY_COMPLETE; 2328 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2329 if (rc) { 2330 return rc; 2331 } 2332 2333 msg->payload[0] = completion_code; 2334 2335 return PLDM_SUCCESS; 2336 } 2337 2338 LIBPLDM_ABI_TESTING 2339 int decode_activate_firmware_req(const struct pldm_msg *msg, 2340 size_t payload_length, bool *self_contained) 2341 { 2342 int rc; 2343 struct pldm_msgbuf _buf; 2344 struct pldm_msgbuf *buf = &_buf; 2345 2346 if (msg == NULL || self_contained == NULL) { 2347 return -EINVAL; 2348 } 2349 2350 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, payload_length); 2351 if (rc) { 2352 return 0; 2353 } 2354 2355 uint8_t self_contained_u8 = 0; 2356 rc = pldm_msgbuf_extract(buf, self_contained_u8); 2357 if (rc) { 2358 return rc; 2359 } 2360 if (buf->remaining != 0) { 2361 return -EOVERFLOW; 2362 } 2363 *self_contained = (bool)self_contained_u8; 2364 return 0; 2365 } 2366 2367 LIBPLDM_ABI_STABLE 2368 int encode_activate_firmware_req(uint8_t instance_id, 2369 bool8_t self_contained_activation_req, 2370 struct pldm_msg *msg, size_t payload_length) 2371 { 2372 if (msg == NULL) { 2373 return PLDM_ERROR_INVALID_DATA; 2374 } 2375 2376 if (payload_length != sizeof(struct pldm_activate_firmware_req)) { 2377 return PLDM_ERROR_INVALID_LENGTH; 2378 } 2379 2380 if (!is_self_contained_activation_req_valid( 2381 self_contained_activation_req)) { 2382 return PLDM_ERROR_INVALID_DATA; 2383 } 2384 2385 struct pldm_header_info header = { 0 }; 2386 header.instance = instance_id; 2387 header.msg_type = PLDM_REQUEST; 2388 header.pldm_type = PLDM_FWUP; 2389 header.command = PLDM_ACTIVATE_FIRMWARE; 2390 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2391 if (rc) { 2392 return rc; 2393 } 2394 2395 struct pldm_activate_firmware_req *request = 2396 (struct pldm_activate_firmware_req *)msg->payload; 2397 2398 request->self_contained_activation_req = self_contained_activation_req; 2399 2400 return PLDM_SUCCESS; 2401 } 2402 2403 LIBPLDM_ABI_STABLE 2404 int decode_activate_firmware_resp(const struct pldm_msg *msg, 2405 size_t payload_length, 2406 uint8_t *completion_code, 2407 uint16_t *estimated_time_activation) 2408 { 2409 if (msg == NULL || completion_code == NULL || 2410 estimated_time_activation == NULL || !payload_length) { 2411 return PLDM_ERROR_INVALID_DATA; 2412 } 2413 2414 *completion_code = msg->payload[0]; 2415 if (*completion_code != PLDM_SUCCESS) { 2416 return PLDM_SUCCESS; 2417 } 2418 2419 if (payload_length != sizeof(struct pldm_activate_firmware_resp)) { 2420 return PLDM_ERROR_INVALID_LENGTH; 2421 } 2422 2423 struct pldm_activate_firmware_resp *response = 2424 (struct pldm_activate_firmware_resp *)msg->payload; 2425 2426 *estimated_time_activation = 2427 le16toh(response->estimated_time_activation); 2428 2429 return PLDM_SUCCESS; 2430 } 2431 2432 LIBPLDM_ABI_TESTING 2433 int encode_activate_firmware_resp( 2434 uint8_t instance_id, 2435 const struct pldm_activate_firmware_resp *resp_data, 2436 struct pldm_msg *msg, size_t *payload_length) 2437 { 2438 int rc; 2439 struct pldm_msgbuf _buf; 2440 struct pldm_msgbuf *buf = &_buf; 2441 2442 if (msg == NULL || payload_length == NULL) { 2443 return -EINVAL; 2444 } 2445 2446 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 2447 PLDM_ACTIVATE_FIRMWARE, msg); 2448 if (rc) { 2449 return -EINVAL; 2450 } 2451 2452 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2453 if (rc) { 2454 return rc; 2455 } 2456 2457 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 2458 pldm_msgbuf_insert(buf, resp_data->estimated_time_activation); 2459 2460 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 2461 } 2462 2463 LIBPLDM_ABI_STABLE 2464 int encode_get_status_req(uint8_t instance_id, struct pldm_msg *msg, 2465 size_t payload_length) 2466 { 2467 if (msg == NULL) { 2468 return PLDM_ERROR_INVALID_DATA; 2469 } 2470 2471 if (payload_length != PLDM_GET_STATUS_REQ_BYTES) { 2472 return PLDM_ERROR_INVALID_LENGTH; 2473 } 2474 2475 struct pldm_header_info header = { 0 }; 2476 header.instance = instance_id; 2477 header.msg_type = PLDM_REQUEST; 2478 header.pldm_type = PLDM_FWUP; 2479 header.command = PLDM_GET_STATUS; 2480 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2481 if (rc) { 2482 return rc; 2483 } 2484 2485 return PLDM_SUCCESS; 2486 } 2487 2488 LIBPLDM_ABI_STABLE 2489 int decode_get_status_resp(const struct pldm_msg *msg, size_t payload_length, 2490 uint8_t *completion_code, uint8_t *current_state, 2491 uint8_t *previous_state, uint8_t *aux_state, 2492 uint8_t *aux_state_status, uint8_t *progress_percent, 2493 uint8_t *reason_code, 2494 bitfield32_t *update_option_flags_enabled) 2495 { 2496 if (msg == NULL || completion_code == NULL || current_state == NULL || 2497 previous_state == NULL || aux_state == NULL || 2498 aux_state_status == NULL || progress_percent == NULL || 2499 reason_code == NULL || update_option_flags_enabled == NULL || 2500 !payload_length) { 2501 return PLDM_ERROR_INVALID_DATA; 2502 } 2503 2504 *completion_code = msg->payload[0]; 2505 if (*completion_code != PLDM_SUCCESS) { 2506 return PLDM_SUCCESS; 2507 } 2508 2509 if (payload_length != sizeof(struct pldm_get_status_resp)) { 2510 return PLDM_ERROR_INVALID_LENGTH; 2511 } 2512 struct pldm_get_status_resp *response = 2513 (struct pldm_get_status_resp *)msg->payload; 2514 2515 if (!is_state_valid(response->current_state)) { 2516 return PLDM_ERROR_INVALID_DATA; 2517 } 2518 if (!is_state_valid(response->previous_state)) { 2519 return PLDM_ERROR_INVALID_DATA; 2520 } 2521 if (!is_aux_state_valid(response->aux_state)) { 2522 return PLDM_ERROR_INVALID_DATA; 2523 } 2524 if (!is_aux_state_status_valid(response->aux_state_status)) { 2525 return PLDM_ERROR_INVALID_DATA; 2526 } 2527 if (response->progress_percent > PLDM_FWUP_MAX_PROGRESS_PERCENT) { 2528 return PLDM_ERROR_INVALID_DATA; 2529 } 2530 if (!is_reason_code_valid(response->reason_code)) { 2531 return PLDM_ERROR_INVALID_DATA; 2532 } 2533 2534 if ((response->current_state == PLDM_FD_STATE_IDLE) || 2535 (response->current_state == PLDM_FD_STATE_LEARN_COMPONENTS) || 2536 (response->current_state == PLDM_FD_STATE_READY_XFER)) { 2537 if (response->aux_state != 2538 PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER) { 2539 return PLDM_ERROR_INVALID_DATA; 2540 } 2541 } 2542 2543 *current_state = response->current_state; 2544 *previous_state = response->previous_state; 2545 *aux_state = response->aux_state; 2546 *aux_state_status = response->aux_state_status; 2547 *progress_percent = response->progress_percent; 2548 *reason_code = response->reason_code; 2549 update_option_flags_enabled->value = 2550 le32toh(response->update_option_flags_enabled.value); 2551 2552 return PLDM_SUCCESS; 2553 } 2554 2555 LIBPLDM_ABI_TESTING 2556 int encode_get_status_resp(uint8_t instance_id, 2557 const struct pldm_get_status_resp *status, 2558 struct pldm_msg *msg, size_t *payload_length) 2559 { 2560 int rc; 2561 struct pldm_msgbuf _buf; 2562 struct pldm_msgbuf *buf = &_buf; 2563 2564 if (status == NULL || msg == NULL || payload_length == NULL) { 2565 return -EINVAL; 2566 } 2567 2568 if (status->completion_code != PLDM_SUCCESS) { 2569 return -EINVAL; 2570 } 2571 2572 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 2573 PLDM_GET_STATUS, msg); 2574 if (rc) { 2575 return -EINVAL; 2576 } 2577 2578 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2579 if (rc) { 2580 return rc; 2581 } 2582 2583 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 2584 pldm_msgbuf_insert(buf, status->current_state); 2585 pldm_msgbuf_insert(buf, status->previous_state); 2586 pldm_msgbuf_insert(buf, status->aux_state); 2587 pldm_msgbuf_insert(buf, status->aux_state_status); 2588 pldm_msgbuf_insert(buf, status->progress_percent); 2589 pldm_msgbuf_insert(buf, status->reason_code); 2590 pldm_msgbuf_insert(buf, status->update_option_flags_enabled.value); 2591 2592 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 2593 } 2594 2595 LIBPLDM_ABI_STABLE 2596 int encode_cancel_update_component_req(uint8_t instance_id, 2597 struct pldm_msg *msg, 2598 size_t payload_length) 2599 { 2600 if (msg == NULL) { 2601 return PLDM_ERROR_INVALID_DATA; 2602 } 2603 2604 if (payload_length != PLDM_CANCEL_UPDATE_COMPONENT_REQ_BYTES) { 2605 return PLDM_ERROR_INVALID_LENGTH; 2606 } 2607 2608 struct pldm_header_info header = { 0 }; 2609 header.instance = instance_id; 2610 header.msg_type = PLDM_REQUEST; 2611 header.pldm_type = PLDM_FWUP; 2612 header.command = PLDM_CANCEL_UPDATE_COMPONENT; 2613 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2614 if (rc) { 2615 return rc; 2616 } 2617 2618 return PLDM_SUCCESS; 2619 } 2620 2621 LIBPLDM_ABI_STABLE 2622 int decode_cancel_update_component_resp(const struct pldm_msg *msg, 2623 size_t payload_length, 2624 uint8_t *completion_code) 2625 { 2626 if (msg == NULL || completion_code == NULL) { 2627 return PLDM_ERROR_INVALID_DATA; 2628 } 2629 2630 if (payload_length != sizeof(*completion_code)) { 2631 return PLDM_ERROR_INVALID_LENGTH; 2632 } 2633 2634 *completion_code = msg->payload[0]; 2635 return PLDM_SUCCESS; 2636 } 2637 2638 LIBPLDM_ABI_STABLE 2639 int encode_cancel_update_req(uint8_t instance_id, struct pldm_msg *msg, 2640 size_t payload_length) 2641 { 2642 if (msg == NULL) { 2643 return PLDM_ERROR_INVALID_DATA; 2644 } 2645 2646 if (payload_length != PLDM_CANCEL_UPDATE_REQ_BYTES) { 2647 return PLDM_ERROR_INVALID_LENGTH; 2648 } 2649 2650 struct pldm_header_info header = { 0 }; 2651 header.instance = instance_id; 2652 header.msg_type = PLDM_REQUEST; 2653 header.pldm_type = PLDM_FWUP; 2654 header.command = PLDM_CANCEL_UPDATE; 2655 uint8_t rc = pack_pldm_header(&header, &(msg->hdr)); 2656 if (rc) { 2657 return rc; 2658 } 2659 2660 return PLDM_SUCCESS; 2661 } 2662 2663 LIBPLDM_ABI_STABLE 2664 int decode_cancel_update_resp(const struct pldm_msg *msg, size_t payload_length, 2665 uint8_t *completion_code, 2666 bool8_t *non_functioning_component_indication, 2667 bitfield64_t *non_functioning_component_bitmap) 2668 { 2669 if (msg == NULL || completion_code == NULL || 2670 non_functioning_component_indication == NULL || 2671 non_functioning_component_bitmap == NULL || !payload_length) { 2672 return PLDM_ERROR_INVALID_DATA; 2673 } 2674 2675 *completion_code = msg->payload[0]; 2676 if (*completion_code != PLDM_SUCCESS) { 2677 return PLDM_SUCCESS; 2678 } 2679 2680 if (payload_length != sizeof(struct pldm_cancel_update_resp)) { 2681 return PLDM_ERROR_INVALID_LENGTH; 2682 } 2683 struct pldm_cancel_update_resp *response = 2684 (struct pldm_cancel_update_resp *)msg->payload; 2685 2686 if (!is_non_functioning_component_indication_valid( 2687 response->non_functioning_component_indication)) { 2688 return PLDM_ERROR_INVALID_DATA; 2689 } 2690 2691 *non_functioning_component_indication = 2692 response->non_functioning_component_indication; 2693 2694 if (*non_functioning_component_indication) { 2695 non_functioning_component_bitmap->value = 2696 le64toh(response->non_functioning_component_bitmap); 2697 } 2698 2699 return PLDM_SUCCESS; 2700 } 2701 2702 LIBPLDM_ABI_TESTING 2703 int encode_cancel_update_resp(uint8_t instance_id, 2704 const struct pldm_cancel_update_resp *resp_data, 2705 struct pldm_msg *msg, size_t *payload_length) 2706 { 2707 int rc; 2708 struct pldm_msgbuf _buf; 2709 struct pldm_msgbuf *buf = &_buf; 2710 2711 if (msg == NULL || payload_length == NULL) { 2712 return -EINVAL; 2713 } 2714 2715 rc = encode_pldm_header_only(PLDM_RESPONSE, instance_id, PLDM_FWUP, 2716 PLDM_CANCEL_UPDATE, msg); 2717 if (rc) { 2718 return -EINVAL; 2719 } 2720 2721 rc = pldm_msgbuf_init_errno(buf, 0, msg->payload, *payload_length); 2722 if (rc) { 2723 return rc; 2724 } 2725 2726 pldm_msgbuf_insert_uint8(buf, PLDM_SUCCESS); 2727 pldm_msgbuf_insert(buf, 2728 resp_data->non_functioning_component_indication); 2729 pldm_msgbuf_insert(buf, resp_data->non_functioning_component_bitmap); 2730 2731 return pldm_msgbuf_destroy_used(buf, *payload_length, payload_length); 2732 } 2733