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