blob: c3cf718043e7398916250af96104bd9f62032c2d [file] [log] [blame]
Alexander Hansencc372352025-01-14 14:15:39 +01001#include "software_manager.hpp"
2
3#include <phosphor-logging/lg2.hpp>
4#include <sdbusplus/asio/object_server.hpp>
5#include <sdbusplus/async.hpp>
6#include <sdbusplus/async/context.hpp>
7#include <sdbusplus/bus.hpp>
8#include <xyz/openbmc_project/Association/Definitions/server.hpp>
9#include <xyz/openbmc_project/ObjectMapper/client.hpp>
Alexander Hansende5e76f2025-02-20 16:30:11 +010010#include <xyz/openbmc_project/Software/Version/client.hpp>
Alexander Hansencc372352025-01-14 14:15:39 +010011#include <xyz/openbmc_project/State/Host/client.hpp>
12
13#include <cstdint>
14
15PHOSPHOR_LOG2_USING;
16
17using namespace phosphor::software::manager;
18
19SoftwareManager::SoftwareManager(sdbusplus::async::context& ctx,
20 const std::string& serviceNameSuffix) :
Alexander Hansende5e76f2025-02-20 16:30:11 +010021 ctx(ctx), serviceNameSuffix(serviceNameSuffix),
22 manager(ctx, sdbusplus::client::xyz::openbmc_project::software::Version<>::
23 namespace_path)
Alexander Hansencc372352025-01-14 14:15:39 +010024{
25 const std::string serviceNameFull =
26 "xyz.openbmc_project.Software." + serviceNameSuffix;
27
28 debug("requesting dbus name {BUSNAME}", "BUSNAME", serviceNameFull);
29
Alexander Hansende5e76f2025-02-20 16:30:11 +010030 ctx.request_name(serviceNameFull.c_str());
Alexander Hansencc372352025-01-14 14:15:39 +010031
Alexander Hansende5e76f2025-02-20 16:30:11 +010032 debug("Initialized SoftwareManager");
Alexander Hansencc372352025-01-14 14:15:39 +010033}
34
35// NOLINTBEGIN(readability-static-accessed-through-instance)
Alexander Hansenf3d407b2025-05-08 09:52:31 +020036static sdbusplus::async::task<std::optional<SoftwareConfig>> getConfig(
37 sdbusplus::async::context& ctx, const std::string& service,
38 const std::string& objectPath, const std::string& interfacePrefix)
39// NOLINTEND(readability-static-accessed-through-instance)
40{
41 auto client = sdbusplus::async::proxy()
42 .service(service)
43 .path(objectPath)
44 .interface("org.freedesktop.DBus.Properties");
45
46 uint64_t vendorIANA = 0;
47 std::string compatible{};
48 std::string configType{};
49 std::string configName{};
50
51 const std::string interfaceName = interfacePrefix + ".FirmwareInfo";
52
53 try
54 {
55 {
56 auto propVendorIANA = co_await client.call<std::variant<uint64_t>>(
57 ctx, "Get", interfaceName, "VendorIANA");
58
59 vendorIANA = std::get<uint64_t>(propVendorIANA);
60 }
61 {
62 auto propCompatible =
63 co_await client.call<std::variant<std::string>>(
64 ctx, "Get", interfaceName, "CompatibleHardware");
65
66 compatible = std::get<std::string>(propCompatible);
67 }
68 {
69 auto propConfigType =
70 co_await client.call<std::variant<std::string>>(
71 ctx, "Get", interfacePrefix, "Type");
72
73 configType = std::get<std::string>(propConfigType);
74 }
75 {
76 auto propConfigName =
77 co_await client.call<std::variant<std::string>>(
78 ctx, "Get", interfacePrefix, "Name");
79
80 configName = std::get<std::string>(propConfigName);
81 }
82 }
83 catch (std::exception& e)
84 {
85 error("Failed to get config with {ERROR}", "ERROR", e);
86 co_return std::nullopt;
87 }
88
89 co_return SoftwareConfig(objectPath, vendorIANA, compatible, configType,
90 configName);
91}
92
93// NOLINTBEGIN(readability-static-accessed-through-instance)
Alexander Hansencc372352025-01-14 14:15:39 +010094sdbusplus::async::task<> SoftwareManager::initDevices(
95 const std::vector<std::string>& configurationInterfaces)
96// NOLINTEND(readability-static-accessed-through-instance)
97{
98 auto client = sdbusplus::client::xyz::openbmc_project::ObjectMapper<>(ctx)
99 .service("xyz.openbmc_project.ObjectMapper")
100 .path("/xyz/openbmc_project/object_mapper");
101
Alexander Hansen0a457ff2025-02-25 16:13:47 +0100102 auto res = co_await client.get_sub_tree("/xyz/openbmc_project/inventory", 0,
103 configurationInterfaces);
Alexander Hansencc372352025-01-14 14:15:39 +0100104
105 for (auto& iface : configurationInterfaces)
106 {
107 debug("[config] looking for dbus interface {INTF}", "INTF", iface);
108 }
109
110 for (auto& [path, v] : res)
111 {
112 for (auto& [service, interfaceNames] : v)
113 {
114 std::string interfaceFound;
115
116 for (std::string& interfaceName : interfaceNames)
117 {
118 for (auto& iface : configurationInterfaces)
119 {
120 if (interfaceName == iface)
121 {
122 interfaceFound = interfaceName;
123 }
124 }
125 }
126
127 if (interfaceFound.empty())
128 {
129 continue;
130 }
131
132 debug(
133 "[config] found configuration interface at {SERVICE}, {OBJPATH}",
134 "SERVICE", service, "OBJPATH", path);
135
Alexander Hansenf3d407b2025-05-08 09:52:31 +0200136 auto optConfig =
137 co_await getConfig(ctx, service, path, interfaceFound);
138 if (!optConfig.has_value())
Alexander Hansencc372352025-01-14 14:15:39 +0100139 {
Alexander Hansenf3d407b2025-05-08 09:52:31 +0200140 error("Error fetching common configuration from {PATH}", "PATH",
141 path);
Alexander Hansencc372352025-01-14 14:15:39 +0100142 continue;
143 }
144
Alexander Hansenf3d407b2025-05-08 09:52:31 +0200145 co_await initDevice(service, path, optConfig.value());
Alexander Hansencc372352025-01-14 14:15:39 +0100146 }
147 }
148
Alexander Hansenf3d407b2025-05-08 09:52:31 +0200149 debug("Done with initial configuration");
Alexander Hansencc372352025-01-14 14:15:39 +0100150}