xref: /openbmc/pldm/fw-update/firmware_inventory_manager.cpp (revision 7ad45b401134e3b3a05a75200dbba00afd5aee46)
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 
createFirmwareEntry(const SoftwareIdentifier & softwareIdentifier,const SoftwareName & softwareName,const std::string & activeVersion,const Descriptors & descriptors,const ComponentInfo & componentInfo)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     auto& eid = softwareIdentifier.first;
24     const auto inventoryPath = getInventoryPath(eid);
25     if (!inventoryPath)
26     {
27         error("No inventory path found for EID {EID}", "EID", eid);
28         return;
29     }
30     auto boardPath = getBoardPath(*dbusHandler, *inventoryPath);
31 
32     if (!boardPath)
33     {
34         error("Failed to get board path for EID {EID}", "EID", eid);
35         return;
36     }
37     const auto boardName = boardPath->filename().string();
38     const auto softwarePath =
39         std::format("/xyz/openbmc_project/software/{}_{}_{}", boardName,
40                     softwareName, utils::generateSwId());
41 
42     softwareMap.insert_or_assign(
43         softwareIdentifier, std::make_unique<FirmwareInventory>(
44                                 softwareIdentifier, softwarePath, activeVersion,
45                                 *boardPath, descriptors, componentInfo));
46 }
47 
deleteFirmwareEntry(const pldm::eid & eid)48 void FirmwareInventoryManager::deleteFirmwareEntry(const pldm::eid& eid)
49 {
50     std::erase_if(softwareMap,
51                   [&](const auto& pair) { return pair.first.first == eid; });
52 }
53 
getBoardPath(const pldm::utils::DBusHandler & handler,const InventoryPath & path)54 std::optional<std::filesystem::path> getBoardPath(
55     const pldm::utils::DBusHandler& handler, const InventoryPath& path)
56 {
57     constexpr auto boardInterface = "xyz.openbmc_project.Inventory.Item.Board";
58     pldm::utils::GetAncestorsResponse response;
59 
60     try
61     {
62         response = handler.getAncestors(path.c_str(), {boardInterface});
63     }
64     catch (const sdbusplus::exception_t& e)
65     {
66         error("Failed to get ancestors for path {PATH}: {ERROR}", "PATH", path,
67               "ERROR", e);
68         return std::nullopt;
69     }
70 
71     if (response.empty())
72     {
73         error(
74             "Failed to get unique board path for Inventory path {PATH}, found: {SIZE}",
75             "PATH", path, "SIZE", response.size());
76         return std::nullopt;
77     }
78 
79     return std::get<ObjectPath>(response.front());
80 }
81 
getInventoryPath(const pldm::eid & eid) const82 std::optional<InventoryPath> FirmwareInventoryManager::getInventoryPath(
83     const pldm::eid& eid) const
84 {
85     for (const auto& [configDbusPath, configMctpInfo] : configurations)
86     {
87         if (std::get<pldm::eid>(configMctpInfo) == eid)
88         {
89             return configDbusPath;
90         }
91     }
92     warning("No inventory path found for EID {EID}", "EID", eid);
93     return std::nullopt;
94 }
95 
96 } // namespace pldm::fw_update
97