1 #include "inventory_manager.hpp" 2 3 #include "common/utils.hpp" 4 #include "xyz/openbmc_project/Software/Version/server.hpp" 5 6 #include <libpldm/firmware_update.h> 7 8 #include <phosphor-logging/lg2.hpp> 9 10 #include <functional> 11 12 PHOSPHOR_LOG2_USING; 13 14 namespace pldm 15 { 16 namespace fw_update 17 { 18 void InventoryManager::discoverFDs(const MctpInfos& mctpInfos) 19 { 20 for (const auto& mctpInfo : mctpInfos) 21 { 22 auto eid = std::get<pldm::eid>(mctpInfo); 23 try 24 { 25 sendQueryDeviceIdentifiersRequest(eid); 26 } 27 catch (const std::exception& e) 28 { 29 error( 30 "Failed to discover file descriptors for endpoint ID {EID} with {ERROR}", 31 "EID", eid, "ERROR", e); 32 } 33 } 34 } 35 36 void InventoryManager::removeFDs(const MctpInfos& mctpInfos) 37 { 38 for (const auto& mctpInfo : mctpInfos) 39 { 40 auto eid = std::get<pldm::eid>(mctpInfo); 41 firmwareDeviceNameMap.erase(eid); 42 descriptorMap.erase(eid); 43 downstreamDescriptorMap.erase(eid); 44 componentInfoMap.erase(eid); 45 firmwareInventoryManager.deleteFirmwareEntry(eid); 46 } 47 } 48 49 void InventoryManager::sendQueryDeviceIdentifiersRequest(mctp_eid_t eid) 50 { 51 auto instanceId = instanceIdDb.next(eid); 52 Request requestMsg( 53 sizeof(pldm_msg_hdr) + PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES); 54 auto request = new (requestMsg.data()) pldm_msg; 55 auto rc = encode_query_device_identifiers_req( 56 instanceId, PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES, request); 57 if (rc) 58 { 59 instanceIdDb.free(eid, instanceId); 60 error( 61 "Failed to encode query device identifiers request for endpoint ID {EID} with response code {RC}", 62 "EID", eid, "RC", rc); 63 throw std::runtime_error( 64 "Failed to encode QueryDeviceIdentifiers request"); 65 } 66 67 rc = handler.registerRequest( 68 eid, instanceId, PLDM_FWUP, PLDM_QUERY_DEVICE_IDENTIFIERS, 69 std::move(requestMsg), 70 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) { 71 this->queryDeviceIdentifiers(eid, response, respMsgLen); 72 }); 73 if (rc) 74 { 75 error( 76 "Failed to send query device identifiers request for endpoint ID {EID} with response code {RC}", 77 "EID", eid, "RC", rc); 78 throw std::runtime_error( 79 "Failed to send QueryDeviceIdentifiers request"); 80 } 81 } 82 83 void InventoryManager::queryDeviceIdentifiers( 84 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) 85 { 86 if (response == nullptr || !respMsgLen) 87 { 88 error( 89 "No response received for query device identifiers for endpoint ID {EID}", 90 "EID", eid); 91 return; 92 } 93 94 uint8_t completionCode = PLDM_SUCCESS; 95 uint32_t deviceIdentifiersLen = 0; 96 uint8_t descriptorCount = 0; 97 uint8_t* descriptorPtr = nullptr; 98 99 auto rc = decode_query_device_identifiers_resp( 100 response, respMsgLen, &completionCode, &deviceIdentifiersLen, 101 &descriptorCount, &descriptorPtr); 102 if (rc) 103 { 104 error( 105 "Failed to decode query device identifiers response for endpoint ID {EID} and descriptor count {DESCRIPTOR_COUNT}, response code {RC}", 106 "EID", eid, "DESCRIPTOR_COUNT", descriptorCount, "RC", rc); 107 return; 108 } 109 110 if (completionCode) 111 { 112 error( 113 "Failed to query device identifiers response for endpoint ID {EID}, completion code {CC}", 114 "EID", eid, "CC", completionCode); 115 return; 116 } 117 118 Descriptors descriptors{}; 119 while (descriptorCount-- && (deviceIdentifiersLen > 0)) 120 { 121 uint16_t descriptorType = 0; 122 variable_field descriptorData{}; 123 124 rc = decode_descriptor_type_length_value( 125 descriptorPtr, deviceIdentifiersLen, &descriptorType, 126 &descriptorData); 127 if (rc) 128 { 129 error( 130 "Failed to decode descriptor type {TYPE}, length {LENGTH} and value for endpoint ID {EID}, response code {RC}", 131 "TYPE", descriptorType, "LENGTH", deviceIdentifiersLen, "EID", 132 eid, "RC", rc); 133 return; 134 } 135 136 if (descriptorType != PLDM_FWUP_VENDOR_DEFINED) 137 { 138 std::vector<uint8_t> descData( 139 descriptorData.ptr, descriptorData.ptr + descriptorData.length); 140 descriptors.emplace(descriptorType, std::move(descData)); 141 } 142 else 143 { 144 uint8_t descriptorTitleStrType = 0; 145 variable_field descriptorTitleStr{}; 146 variable_field vendorDefinedDescriptorData{}; 147 148 rc = decode_vendor_defined_descriptor_value( 149 descriptorData.ptr, descriptorData.length, 150 &descriptorTitleStrType, &descriptorTitleStr, 151 &vendorDefinedDescriptorData); 152 if (rc) 153 { 154 error( 155 "Failed to decode vendor-defined descriptor value for endpoint ID {EID}, response code {RC}", 156 "EID", eid, "RC", rc); 157 return; 158 } 159 160 auto vendorDefinedDescriptorTitleStr = 161 utils::toString(descriptorTitleStr); 162 std::vector<uint8_t> vendorDescData( 163 vendorDefinedDescriptorData.ptr, 164 vendorDefinedDescriptorData.ptr + 165 vendorDefinedDescriptorData.length); 166 descriptors.emplace(descriptorType, 167 std::make_tuple(vendorDefinedDescriptorTitleStr, 168 vendorDescData)); 169 } 170 auto nextDescriptorOffset = 171 sizeof(pldm_descriptor_tlv().descriptor_type) + 172 sizeof(pldm_descriptor_tlv().descriptor_length) + 173 descriptorData.length; 174 descriptorPtr += nextDescriptorOffset; 175 deviceIdentifiersLen -= nextDescriptorOffset; 176 } 177 178 obtainFirmwareDeviceName(eid, descriptors); 179 descriptorMap.insert_or_assign(eid, std::move(descriptors)); 180 181 // Send GetFirmwareParameters request 182 sendGetFirmwareParametersRequest(eid); 183 } 184 185 void InventoryManager::sendQueryDownstreamDevicesRequest(mctp_eid_t eid) 186 { 187 Request requestMsg(sizeof(pldm_msg_hdr)); 188 auto instanceId = instanceIdDb.next(eid); 189 auto request = new (requestMsg.data()) pldm_msg; 190 auto rc = encode_query_downstream_devices_req(instanceId, request); 191 if (rc) 192 { 193 instanceIdDb.free(eid, instanceId); 194 error( 195 "Failed to encode query downstream devices request for endpoint ID EID {EID} with response code {RC}", 196 "EID", eid, "RC", rc); 197 throw std::runtime_error( 198 "Failed to encode query downstream devices request"); 199 } 200 201 rc = handler.registerRequest( 202 eid, instanceId, PLDM_FWUP, PLDM_QUERY_DOWNSTREAM_DEVICES, 203 std::move(requestMsg), 204 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) { 205 this->queryDownstreamDevices(eid, response, respMsgLen); 206 }); 207 if (rc) 208 { 209 error( 210 "Failed to send QueryDownstreamDevices request for endpoint ID {EID} with response code {RC}", 211 "EID", eid, "RC", rc); 212 } 213 } 214 215 void InventoryManager::queryDownstreamDevices( 216 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) 217 { 218 if (!response || !respMsgLen) 219 { 220 error( 221 "No response received for QueryDownstreamDevices for endpoint ID {EID}", 222 "EID", eid); 223 return; 224 } 225 226 pldm_query_downstream_devices_resp downstreamDevicesResp{}; 227 auto rc = decode_query_downstream_devices_resp(response, respMsgLen, 228 &downstreamDevicesResp); 229 if (rc) 230 { 231 error( 232 "Decoding QueryDownstreamDevices response failed for endpoint ID {EID} with response code {RC}", 233 "EID", eid, "RC", rc); 234 return; 235 } 236 237 switch (downstreamDevicesResp.completion_code) 238 { 239 case PLDM_SUCCESS: 240 break; 241 case PLDM_ERROR_UNSUPPORTED_PLDM_CMD: 242 /* QueryDownstreamDevices is optional, consider the device does not 243 * support Downstream Devices. 244 */ 245 info("Endpoint ID {EID} does not support QueryDownstreamDevices", 246 "EID", eid); 247 return; 248 default: 249 error( 250 "QueryDownstreamDevices response failed with error completion code for endpoint ID {EID} with completion code {CC}", 251 "EID", eid, "CC", downstreamDevicesResp.completion_code); 252 return; 253 } 254 255 switch (downstreamDevicesResp.downstream_device_update_supported) 256 { 257 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_SUPPORTED: 258 /** DataTransferHandle will be skipped when TransferOperationFlag is 259 * `GetFirstPart`. Use 0x0 as default by following example in 260 * Figure 9 in DSP0267 1.1.0 261 */ 262 try 263 { 264 sendQueryDownstreamIdentifiersRequest(eid, 0x0, 265 PLDM_GET_FIRSTPART); 266 } 267 catch (const std::exception& e) 268 { 269 error( 270 "Failed to send QueryDownstreamIdentifiers request for endpoint ID {EID} with {ERROR}", 271 "EID", eid, "ERROR", e); 272 } 273 break; 274 case PLDM_FWUP_DOWNSTREAM_DEVICE_UPDATE_NOT_SUPPORTED: 275 /* The FDP does not support firmware updates but may report 276 * inventory information on downstream devices. 277 * In this scenario, sends only GetDownstreamFirmwareParameters 278 * to the FDP. 279 * The definition can be found at Table 15 of DSP0267_1.1.0 280 */ 281 break; 282 default: 283 error( 284 "Unknown response of DownstreamDeviceUpdateSupported from endpoint ID {EID} with value {VALUE}", 285 "EID", eid, "VALUE", 286 downstreamDevicesResp.downstream_device_update_supported); 287 return; 288 } 289 } 290 291 void InventoryManager::sendQueryDownstreamIdentifiersRequest( 292 mctp_eid_t eid, uint32_t dataTransferHandle, 293 enum transfer_op_flag transferOperationFlag) 294 { 295 auto instanceId = instanceIdDb.next(eid); 296 Request requestMsg( 297 sizeof(pldm_msg_hdr) + PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES); 298 auto request = new (requestMsg.data()) pldm_msg; 299 pldm_query_downstream_identifiers_req requestParameters{ 300 dataTransferHandle, static_cast<uint8_t>(transferOperationFlag)}; 301 302 auto rc = encode_query_downstream_identifiers_req( 303 instanceId, &requestParameters, request, 304 PLDM_QUERY_DOWNSTREAM_IDENTIFIERS_REQ_BYTES); 305 if (rc) 306 { 307 instanceIdDb.free(eid, instanceId); 308 error( 309 "Failed to encode query downstream identifiers request for endpoint ID {EID} with response code {RC}", 310 "EID", eid, "RC", rc); 311 throw std::runtime_error( 312 "Failed to encode query downstream identifiers request"); 313 } 314 315 rc = handler.registerRequest( 316 eid, instanceId, PLDM_FWUP, PLDM_QUERY_DOWNSTREAM_IDENTIFIERS, 317 std::move(requestMsg), 318 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) { 319 this->queryDownstreamIdentifiers(eid, response, respMsgLen); 320 }); 321 if (rc) 322 { 323 error( 324 "Failed to send QueryDownstreamIdentifiers request for endpoint ID {EID} with response code {RC}", 325 "EID", eid, "RC", rc); 326 } 327 } 328 329 void InventoryManager::queryDownstreamIdentifiers( 330 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) 331 { 332 if (!response || !respMsgLen) 333 { 334 error( 335 "No response received for QueryDownstreamIdentifiers for endpoint ID {EID}", 336 "EID", eid); 337 descriptorMap.erase(eid); 338 return; 339 } 340 341 pldm_query_downstream_identifiers_resp downstreamIds{}; 342 pldm_downstream_device_iter devs{}; 343 344 auto rc = decode_query_downstream_identifiers_resp(response, respMsgLen, 345 &downstreamIds, &devs); 346 if (rc) 347 { 348 error( 349 "Decoding QueryDownstreamIdentifiers response failed for endpoint ID {EID} with response code {RC}", 350 "EID", eid, "RC", rc); 351 return; 352 } 353 354 if (downstreamIds.completion_code) 355 { 356 error( 357 "QueryDownstreamIdentifiers response failed with error completion code for endpoint ID {EID} with completion code {CC}", 358 "EID", eid, "CC", unsigned(downstreamIds.completion_code)); 359 return; 360 } 361 362 DownstreamDeviceInfo initialDownstreamDevices{}; 363 DownstreamDeviceInfo* downstreamDevices; 364 if (!downstreamDescriptorMap.contains(eid) || 365 downstreamIds.transfer_flag == PLDM_START || 366 downstreamIds.transfer_flag == PLDM_START_AND_END) 367 { 368 downstreamDevices = &initialDownstreamDevices; 369 } 370 else 371 { 372 downstreamDevices = &downstreamDescriptorMap.at(eid); 373 } 374 375 pldm_downstream_device dev; 376 foreach_pldm_downstream_device(devs, dev, rc) 377 { 378 pldm_descriptor desc; 379 Descriptors descriptors{}; 380 foreach_pldm_downstream_device_descriptor(devs, dev, desc, rc) 381 { 382 const auto descriptorData = 383 new (const_cast<void*>(desc.descriptor_data)) 384 uint8_t[desc.descriptor_length]; 385 if (desc.descriptor_type != PLDM_FWUP_VENDOR_DEFINED) 386 { 387 std::vector<uint8_t> descData( 388 descriptorData, descriptorData + desc.descriptor_length); 389 descriptors.emplace(desc.descriptor_type, std::move(descData)); 390 } 391 else 392 { 393 uint8_t descriptorTitleStrType = 0; 394 variable_field descriptorTitleStr{}; 395 variable_field vendorDefinedDescriptorData{}; 396 397 rc = decode_vendor_defined_descriptor_value( 398 descriptorData, desc.descriptor_length, 399 &descriptorTitleStrType, &descriptorTitleStr, 400 &vendorDefinedDescriptorData); 401 402 if (rc) 403 { 404 error( 405 "Decoding Vendor-defined descriptor value failed for endpoint ID {EID} with response code {RC}", 406 "EID", eid, "RC", rc); 407 return; 408 } 409 410 auto vendorDefinedDescriptorTitleStr = 411 utils::toString(descriptorTitleStr); 412 std::vector<uint8_t> vendorDescData( 413 vendorDefinedDescriptorData.ptr, 414 vendorDefinedDescriptorData.ptr + 415 vendorDefinedDescriptorData.length); 416 descriptors.emplace( 417 desc.descriptor_type, 418 std::make_tuple(vendorDefinedDescriptorTitleStr, 419 vendorDescData)); 420 } 421 } 422 if (rc) 423 { 424 error( 425 "Failed to decode downstream device descriptor for endpoint ID {EID} with response code {RC}", 426 "EID", eid, "RC", rc); 427 return; 428 } 429 downstreamDevices->emplace(dev.downstream_device_index, descriptors); 430 } 431 if (rc) 432 { 433 error( 434 "Failed to decode downstream devices from iterator for endpoint ID {EID} with response code {RC}", 435 "EID", eid, "RC", rc); 436 return; 437 } 438 439 switch (downstreamIds.transfer_flag) 440 { 441 case PLDM_START: 442 downstreamDescriptorMap.insert_or_assign( 443 eid, std::move(initialDownstreamDevices)); 444 [[fallthrough]]; 445 case PLDM_MIDDLE: 446 sendQueryDownstreamIdentifiersRequest( 447 eid, downstreamIds.next_data_transfer_handle, 448 PLDM_GET_NEXTPART); 449 break; 450 case PLDM_START_AND_END: 451 downstreamDescriptorMap.insert_or_assign( 452 eid, std::move(initialDownstreamDevices)); 453 /** DataTransferHandle will be skipped when TransferOperationFlag is 454 * `GetFirstPart`. Use 0x0 as default by following example in 455 * Figure 9 in DSP0267 1.1.0 456 */ 457 [[fallthrough]]; 458 case PLDM_END: 459 sendGetDownstreamFirmwareParametersRequest(eid, 0x0, 460 PLDM_GET_FIRSTPART); 461 break; 462 } 463 } 464 465 void InventoryManager::sendGetDownstreamFirmwareParametersRequest( 466 mctp_eid_t eid, uint32_t dataTransferHandle, 467 enum transfer_op_flag transferOperationFlag) 468 { 469 Request requestMsg(sizeof(pldm_msg_hdr) + 470 PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES); 471 auto instanceId = instanceIdDb.next(eid); 472 auto request = new (requestMsg.data()) pldm_msg; 473 pldm_get_downstream_firmware_parameters_req requestParameters{ 474 dataTransferHandle, static_cast<uint8_t>(transferOperationFlag)}; 475 auto rc = encode_get_downstream_firmware_parameters_req( 476 instanceId, &requestParameters, request, 477 PLDM_GET_DOWNSTREAM_FIRMWARE_PARAMETERS_REQ_BYTES); 478 if (rc) 479 { 480 instanceIdDb.free(eid, instanceId); 481 error( 482 "Failed to encode query downstream firmware parameters request for endpoint ID {EID} with response code {RC}", 483 "EID", eid, "RC", rc); 484 throw std::runtime_error( 485 "Failed to encode query downstream firmware parameters request"); 486 } 487 488 rc = handler.registerRequest( 489 eid, instanceId, PLDM_FWUP, PLDM_QUERY_DOWNSTREAM_FIRMWARE_PARAMETERS, 490 std::move(requestMsg), 491 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) { 492 this->getDownstreamFirmwareParameters(eid, response, respMsgLen); 493 }); 494 if (rc) 495 { 496 error( 497 "Failed to send QueryDownstreamFirmwareParameters request for endpoint ID {EID} with response code {RC}", 498 "EID", eid, "RC", rc); 499 } 500 } 501 502 void InventoryManager::getDownstreamFirmwareParameters( 503 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) 504 { 505 if (!response || !respMsgLen) 506 { 507 error( 508 "No response received for QueryDownstreamFirmwareParameters for endpoint ID {EID}", 509 "EID", eid); 510 descriptorMap.erase(eid); 511 return; 512 } 513 514 pldm_get_downstream_firmware_parameters_resp resp{}; 515 pldm_downstream_device_parameters_iter params{}; 516 pldm_downstream_device_parameters_entry entry{}; 517 518 auto rc = decode_get_downstream_firmware_parameters_resp( 519 response, respMsgLen, &resp, ¶ms); 520 521 if (rc) 522 { 523 error( 524 "Decoding QueryDownstreamFirmwareParameters response failed for endpoint ID {EID} with response code {RC}", 525 "EID", eid, "RC", rc); 526 return; 527 } 528 529 if (resp.completion_code) 530 { 531 error( 532 "QueryDownstreamFirmwareParameters response failed with error completion code for endpoint ID {EID} with completion code {CC}", 533 "EID", eid, "CC", resp.completion_code); 534 return; 535 } 536 537 foreach_pldm_downstream_device_parameters_entry(params, entry, rc) 538 { 539 // Reserved for upcoming use 540 [[maybe_unused]] variable_field activeCompVerStr{ 541 reinterpret_cast<const uint8_t*>(entry.active_comp_ver_str), 542 entry.active_comp_ver_str_len}; 543 } 544 if (rc) 545 { 546 error( 547 "Failed to decode downstream device parameters from iterator for endpoint ID {EID} with response code {RC}", 548 "EID", eid, "RC", rc); 549 return; 550 } 551 552 switch (resp.transfer_flag) 553 { 554 case PLDM_START: 555 case PLDM_MIDDLE: 556 sendGetDownstreamFirmwareParametersRequest( 557 eid, resp.next_data_transfer_handle, PLDM_GET_NEXTPART); 558 break; 559 } 560 } 561 562 void InventoryManager::obtainFirmwareDeviceName(pldm::eid eid, 563 const Descriptors& descriptors) 564 { 565 auto firmwareDeviceName = 566 obtainDeviceNameFromConfigurations(configurations, eid); 567 568 if (!firmwareDeviceName) 569 { 570 firmwareDeviceName = obtainDeviceNameFromDescriptors(descriptors); 571 } 572 573 if (!firmwareDeviceName) 574 { 575 firmwareDeviceName = std::format("Firmware_Device_{}", eid); 576 } 577 578 firmwareDeviceNameMap.insert_or_assign(eid, *firmwareDeviceName); 579 } 580 581 void InventoryManager::sendGetFirmwareParametersRequest(mctp_eid_t eid) 582 { 583 auto instanceId = instanceIdDb.next(eid); 584 Request requestMsg( 585 sizeof(pldm_msg_hdr) + PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES); 586 auto request = new (requestMsg.data()) pldm_msg; 587 auto rc = encode_get_firmware_parameters_req( 588 instanceId, PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES, request); 589 if (rc) 590 { 591 instanceIdDb.free(eid, instanceId); 592 error( 593 "Failed to encode get firmware parameters req for endpoint ID {EID}, response code {RC}", 594 "EID", eid, "RC", rc); 595 return; 596 } 597 598 rc = handler.registerRequest( 599 eid, instanceId, PLDM_FWUP, PLDM_GET_FIRMWARE_PARAMETERS, 600 std::move(requestMsg), 601 [this](mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) { 602 this->getFirmwareParameters(eid, response, respMsgLen); 603 }); 604 if (rc) 605 { 606 error( 607 "Failed to send get firmware parameters request for endpoint ID {EID}, response code {RC}", 608 "EID", eid, "RC", rc); 609 } 610 } 611 612 void InventoryManager::getFirmwareParameters( 613 mctp_eid_t eid, const pldm_msg* response, size_t respMsgLen) 614 { 615 if (response == nullptr || !respMsgLen) 616 { 617 error( 618 "No response received for get firmware parameters for endpoint ID {EID}", 619 "EID", eid); 620 descriptorMap.erase(eid); 621 return; 622 } 623 624 pldm_get_firmware_parameters_resp fwParams{}; 625 variable_field activeCompImageSetVerStr{}; 626 variable_field pendingCompImageSetVerStr{}; 627 variable_field compParamTable{}; 628 629 auto rc = decode_get_firmware_parameters_resp( 630 response, respMsgLen, &fwParams, &activeCompImageSetVerStr, 631 &pendingCompImageSetVerStr, &compParamTable); 632 if (rc) 633 { 634 error( 635 "Failed to decode get firmware parameters response for endpoint ID {EID}, response code {RC}", 636 "EID", eid, "RC", rc); 637 return; 638 } 639 640 if (fwParams.completion_code) 641 { 642 auto fw_param_cc = fwParams.completion_code; 643 error( 644 "Failed to get firmware parameters response for endpoint ID {EID}, completion code {CC}", 645 "EID", eid, "CC", fw_param_cc); 646 return; 647 } 648 649 auto compParamPtr = compParamTable.ptr; 650 auto compParamTableLen = compParamTable.length; 651 pldm_component_parameter_entry compEntry{}; 652 variable_field activeCompVerStr{}; 653 variable_field pendingCompVerStr{}; 654 655 ComponentInfo componentInfo{}; 656 while (fwParams.comp_count-- && (compParamTableLen > 0)) 657 { 658 auto rc = decode_get_firmware_parameters_resp_comp_entry( 659 compParamPtr, compParamTableLen, &compEntry, &activeCompVerStr, 660 &pendingCompVerStr); 661 if (rc) 662 { 663 error( 664 "Failed to decode component parameter table entry for endpoint ID {EID}, response code {RC}", 665 "EID", eid, "RC", rc); 666 return; 667 } 668 669 auto compClassification = compEntry.comp_classification; 670 auto compIdentifier = compEntry.comp_identifier; 671 componentInfo.emplace( 672 std::make_pair(compClassification, compIdentifier), 673 compEntry.comp_classification_index); 674 compParamPtr += sizeof(pldm_component_parameter_entry) + 675 activeCompVerStr.length + pendingCompVerStr.length; 676 compParamTableLen -= sizeof(pldm_component_parameter_entry) + 677 activeCompVerStr.length + pendingCompVerStr.length; 678 } 679 680 if (firmwareDeviceNameMap.contains(eid)) 681 { 682 firmwareInventoryManager.createFirmwareEntry( 683 SoftwareIdentifier(eid, 0), firmwareDeviceNameMap.at(eid), 684 utils::toString(activeCompImageSetVerStr), descriptorMap[eid], 685 componentInfo); 686 } 687 else 688 { 689 error("Firmware device name not found for endpoint ID {EID}", "EID", 690 eid); 691 } 692 693 componentInfoMap.insert_or_assign(eid, std::move(componentInfo)); 694 } 695 696 std::optional<SoftwareName> obtainDeviceNameFromConfigurations( 697 const Configurations& configurations, pldm::eid eid) 698 { 699 for (const auto& [_, mctpInfo] : configurations) 700 { 701 if (std::get<pldm::eid>(mctpInfo) == eid) 702 { 703 auto nameOption = std::get<std::optional<std::string>>(mctpInfo); 704 if (nameOption) 705 { 706 return *nameOption; 707 } 708 break; 709 } 710 } 711 return std::nullopt; 712 } 713 714 std::optional<SoftwareName> obtainDeviceNameFromDescriptors( 715 const Descriptors& descriptors) 716 { 717 for (const auto& [descriptorType, descriptorData] : descriptors) 718 { 719 if (descriptorType == PLDM_FWUP_VENDOR_DEFINED) 720 { 721 auto vendorInfo = 722 std::get<VendorDefinedDescriptorInfo>(descriptorData); 723 auto title = std::get<VendorDefinedDescriptorTitle>(vendorInfo); 724 if (title == "OpenBMC.Name") 725 { 726 auto deviceNameData = 727 std::get<VendorDefinedDescriptorData>(vendorInfo); 728 return SoftwareName{ 729 reinterpret_cast<char*>(deviceNameData.data()), 730 deviceNameData.size()}; 731 } 732 } 733 } 734 return std::nullopt; 735 } 736 737 } // namespace fw_update 738 739 } // namespace pldm 740