xref: /openbmc/pldm/fw-update/firmware_inventory_manager.cpp (revision 05d15a06fe6c3aed1a940b557d723921f912dc28)
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     // 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 
deleteFirmwareEntry(const pldm::eid & eid)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 
getBoardPath(const pldm::utils::DBusHandler & handler,const InventoryPath & path)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 
getInventoryPath(const pldm::eid & eid) const84 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