blob: 635a73c35a70d6facc9dd8536fcd12c736a1a7b4 [file] [log] [blame]
Ben Tyner324234b2021-06-28 17:01:17 -05001#include <util/dbus.hpp>
2#include <util/trace.hpp>
Ben Tynerfe2c50d2021-07-23 13:38:53 -05003#include <xyz/openbmc_project/State/Boot/Progress/server.hpp>
Ben Tyner324234b2021-06-28 17:01:17 -05004
5namespace util
6{
7
8namespace dbus
9{
10
11//------------------------------------------------------------------------------
12
13constexpr auto objectMapperService = "xyz.openbmc_project.ObjectMapper";
14constexpr auto objectMapperPath = "/xyz/openbmc_project/object_mapper";
15constexpr auto objectMapperInterface = "xyz.openbmc_project.ObjectMapper";
16
17/** @brief Find the path and service that implements the given interface */
18int find(const std::string& i_interface, std::string& o_path,
19 std::string& o_service)
20{
21 int rc = 1; // assume not success
22
23 auto bus = sdbusplus::bus::new_default();
24
Ben Tyner324234b2021-06-28 17:01:17 -050025 try
26 {
Ben Tyner659e65c2021-07-21 09:49:35 -050027 constexpr auto function = "GetSubTree";
28
Ben Tyner324234b2021-06-28 17:01:17 -050029 auto method = bus.new_method_call(objectMapperService, objectMapperPath,
30 objectMapperInterface, function);
31
32 // Search the entire dbus tree for the specified interface
33 method.append(std::string{"/"}, 0,
34 std::vector<std::string>{i_interface});
35
36 auto reply = bus.call(method);
37
38 DBusSubTree response;
39 reply.read(response);
40
41 if (!response.empty())
42 {
43 // Response is a map of object paths to a map of service, interfaces
44 auto object = *(response.begin());
45 o_path = object.first; // return path
46 o_service = object.second.begin()->first; // return service
47
48 rc = 0; // success
49 }
50 }
51 catch (const sdbusplus::exception::SdBusError& e)
52 {
53 trace::err("util::dbus::find exception");
54 std::string traceMsg = std::string(e.what());
55 trace::err(traceMsg.c_str());
56 }
57
58 return rc;
59}
60
61/** @brief Find the service that implements the given object and interface */
62int findService(const std::string& i_interface, const std::string& i_path,
63 std::string& o_service)
64{
65 int rc = 1; // assume not success
66
67 auto bus = sdbusplus::bus::new_default();
68
Ben Tyner324234b2021-06-28 17:01:17 -050069 try
70 {
Ben Tyner659e65c2021-07-21 09:49:35 -050071 constexpr auto function = "GetObject";
72
Ben Tyner324234b2021-06-28 17:01:17 -050073 auto method = bus.new_method_call(objectMapperService, objectMapperPath,
74 objectMapperInterface, function);
75
76 // Find services that implement the object path, constrain the search
77 // to the given interface.
78 method.append(i_path, std::vector<std::string>{i_interface});
79
80 auto reply = bus.call(method);
81
82 // response is a map of service names to their interfaces
83 std::map<DBusService, DBusInterfaceList> response;
84 reply.read(response);
85
86 if (!response.empty())
87 {
88 // return the service
89 o_service = response.begin()->first;
90
91 rc = 0; // success
92 }
93 }
94 catch (const sdbusplus::exception::SdBusError& e)
95 {
96 trace::err("util::dbus::map exception");
97 std::string traceMsg = std::string(e.what());
98 trace::err(traceMsg.c_str());
99 }
100
101 return rc;
102}
103
104/** @brief Read a property from a dbus object interface */
105int getProperty(const std::string& i_interface, const std::string& i_path,
106 const std::string& i_service, const std::string& i_property,
107 DBusValue& o_response)
108{
109 int rc = 1; // assume not success
110
111 auto bus = sdbusplus::bus::new_default();
112
Ben Tyner324234b2021-06-28 17:01:17 -0500113 try
114 {
Ben Tyner659e65c2021-07-21 09:49:35 -0500115 constexpr auto interface = "org.freedesktop.DBus.Properties";
116 constexpr auto function = "Get";
117
Ben Tyner324234b2021-06-28 17:01:17 -0500118 // calling the get property method
119 auto method = bus.new_method_call(i_service.c_str(), i_path.c_str(),
120 interface, function);
121
122 method.append(i_interface, i_property);
123 auto reply = bus.call(method);
124
125 // returning the property value
126 reply.read(o_response);
127
128 rc = 0; // success
129 }
130 catch (const sdbusplus::exception::SdBusError& e)
131 {
132 trace::err("util::dbus::getProperty exception");
133 std::string traceMsg = std::string(e.what());
134 trace::err(traceMsg.c_str());
135 }
136
137 return rc;
138}
139
140/** @brief Get the IBM compatible names defined for this system */
141std::vector<std::string> systemNames()
142{
143 std::vector<std::string> names;
144
145 constexpr auto interface =
146 "xyz.openbmc_project.Configuration.IBMCompatibleSystem";
147
148 DBusService service;
149 DBusPath path;
150
151 // find a dbus object and path that implements the interface
152 if (0 == find(interface, path, service))
153 {
154 DBusValue value;
155
156 // compatible system names are implemented as a property
157 constexpr auto property = "Names";
158
159 if (0 == getProperty(interface, path, service, property, value))
160 {
161 // return value is a variant, names are in the vector
162 names = std::get<std::vector<std::string>>(value);
163 }
164 }
165
166 return names;
167}
168
Ben Tyner93067162021-07-23 10:39:30 -0500169/** @brief Transition the host state */
170void transitionHost(const HostState i_hostState)
171{
172 try
173 {
174 // We will be transitioning host by starting appropriate dbus target
175 std::string target = "obmc-host-quiesce@0.target"; // quiesce is default
176
177 // crash (mpipl) mode state requested
178 if (HostState::Crash == i_hostState)
179 {
180 target = "obmc-host-crash@0.target";
181 }
182
183 auto bus = sdbusplus::bus::new_system();
184 auto method = bus.new_method_call(
185 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
186 "org.freedesktop.systemd1.Manager", "StartUnit");
187
188 method.append(target); // target unit to start
189 method.append("replace"); // mode = replace conflicting queued jobs
190
191 bus.call_noreply(method); // start the service
192 }
193 catch (const sdbusplus::exception::SdBusError& e)
194 {
195 trace::err("util::dbus::transitionHost exception");
196 std::string traceMsg = std::string(e.what());
197 trace::err(traceMsg.c_str());
198 }
199}
200
Ben Tynerffb48672021-07-23 12:29:03 -0500201/** @brief Read state of autoreboot propertyi via dbus */
202bool autoRebootEnabled()
203{
204 bool autoReboot = false; // assume autoreboot attribute not available
205
206 constexpr auto interface = "xyz.openbmc_project.Control.Boot.RebootPolicy";
207
208 DBusService service;
209 DBusPath path;
210
211 // find a dbus object and path that implements the interface
212 if (0 == find(interface, path, service))
213 {
214 DBusValue value;
215
216 // autoreboot policy is implemented as a property
217 constexpr auto property = "AutoReboot";
218
219 if (0 == getProperty(interface, path, service, property, value))
220 {
221 // return value is a variant, autoreboot policy is boolean
222 autoReboot = std::get<bool>(value);
223 }
224 }
225
226 return autoReboot;
227}
228
Ben Tynerfe2c50d2021-07-23 13:38:53 -0500229/** @brief Get the running state of the host */
230HostRunningState hostRunningState()
231{
232 // assume not able to get host running state
233 HostRunningState host = HostRunningState::Unknown;
234
235 constexpr auto interface = "xyz.openbmc_project.State.Boot.Progress";
236
237 DBusService service;
238 DBusPath path;
239
240 // find a dbus object and path that implements the interface
241 if (0 == find(interface, path, service))
242 {
243 DBusValue value;
244
245 // boot progress is implemented as a property
246 constexpr auto property = "BootProgress";
247
248 if (0 == getProperty(interface, path, service, property, value))
249 {
250 // return value is a variant, progress is in the vector of strings
251 std::string bootProgress(std::get<std::string>(value));
252
253 // convert boot progress to host state
254 using BootProgress = sdbusplus::xyz::openbmc_project::State::Boot::
255 server::Progress::ProgressStages;
256
257 BootProgress stage = sdbusplus::xyz::openbmc_project::State::Boot::
258 server::Progress::convertProgressStagesFromString(bootProgress);
259
260 if ((stage == BootProgress::SystemInitComplete) ||
261 (stage == BootProgress::OSStart) ||
262 (stage == BootProgress::OSRunning))
263 {
264 host = HostRunningState::Started;
265 }
266 else
267 {
268 host = HostRunningState::NotStarted;
269 }
270 }
271 }
272
273 return host;
274}
275
Ben Tyner324234b2021-06-28 17:01:17 -0500276} // namespace dbus
277
278} // namespace util