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