1 #include "firmware_inventory_manager.hpp" 2 3 #include "common/types.hpp" 4 #include "common/utils.hpp" 5 6 #include <phosphor-logging/lg2.hpp> 7 8 PHOSPHOR_LOG2_USING; 9 10 namespace pldm::fw_update 11 { 12 13 void FirmwareInventoryManager::createFirmwareEntry( 14 const SoftwareIdentifier& softwareIdentifier, 15 const SoftwareName& softwareName, const std::string& activeVersion, 16 const Descriptors& descriptors, const ComponentInfo& componentInfo) 17 { 18 struct timespec ts; 19 clock_gettime(CLOCK_REALTIME, &ts); 20 unsigned seed = ts.tv_nsec ^ getpid(); 21 srandom(seed); 22 23 // Determine the inventory board path for this EID. If Entity-Manager 24 // has provided a mapping, use it; otherwise fall back to a default 25 // placeholder path so that a software object can still be created. 26 27 std::optional<std::filesystem::path> boardPath; 28 29 auto& eid = softwareIdentifier.first; 30 const auto inventoryPath = getInventoryPath(eid); 31 if (inventoryPath) 32 { 33 boardPath = getBoardPath(*dbusHandler, *inventoryPath); 34 } 35 else 36 { 37 boardPath = "/xyz/openbmc_project/inventory/system/board/PLDM_Device"; 38 } 39 const auto boardName = boardPath->filename().string(); 40 const auto softwarePath = 41 std::format("/xyz/openbmc_project/software/{}_{}_{}", boardName, 42 softwareName, utils::generateSwId()); 43 44 softwareMap.insert_or_assign( 45 softwareIdentifier, std::make_unique<FirmwareInventory>( 46 softwareIdentifier, softwarePath, activeVersion, 47 *boardPath, descriptors, componentInfo)); 48 } 49 50 void FirmwareInventoryManager::deleteFirmwareEntry(const pldm::eid& eid) 51 { 52 std::erase_if(softwareMap, 53 [&](const auto& pair) { return pair.first.first == eid; }); 54 } 55 56 std::optional<std::filesystem::path> getBoardPath( 57 const pldm::utils::DBusHandler& handler, const InventoryPath& path) 58 { 59 constexpr auto boardInterface = "xyz.openbmc_project.Inventory.Item.Board"; 60 pldm::utils::GetAncestorsResponse response; 61 62 try 63 { 64 response = handler.getAncestors(path.c_str(), {boardInterface}); 65 } 66 catch (const sdbusplus::exception_t& e) 67 { 68 error("Failed to get ancestors for path {PATH}: {ERROR}", "PATH", path, 69 "ERROR", e); 70 return std::nullopt; 71 } 72 73 if (response.empty()) 74 { 75 error( 76 "Failed to get unique board path for Inventory path {PATH}, found: {SIZE}", 77 "PATH", path, "SIZE", response.size()); 78 return std::nullopt; 79 } 80 81 return std::get<ObjectPath>(response.front()); 82 } 83 84 std::optional<InventoryPath> FirmwareInventoryManager::getInventoryPath( 85 const pldm::eid& eid) const 86 { 87 for (const auto& [configDbusPath, configMctpInfo] : configurations) 88 { 89 if (std::get<pldm::eid>(configMctpInfo) == eid) 90 { 91 return configDbusPath; 92 } 93 } 94 warning("No inventory path found for EID {EID}", "EID", eid); 95 return std::nullopt; 96 } 97 98 } // namespace pldm::fw_update 99