blob: 4f28154dad42bcadfb202d2bc8215d584a7e8ff2 [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 Tyner39fcf652021-10-19 20:38:29 -0500201/** @brief Read state of autoRebootEnabled property via dbus */
Ben Tynerffb48672021-07-23 12:29:03 -0500202bool autoRebootEnabled()
203{
Ben Tyner39fcf652021-10-19 20:38:29 -0500204 // Assume true in case autoRebootEnbabled property is not available
205 bool autoReboot = true;
Ben Tynerffb48672021-07-23 12:29:03 -0500206
207 constexpr auto interface = "xyz.openbmc_project.Control.Boot.RebootPolicy";
208
Ben Tyner39fcf652021-10-19 20:38:29 -0500209 DBusService service; // will find this
210 DBusPath path; // will find this
Ben Tynerffb48672021-07-23 12:29:03 -0500211
212 // find a dbus object and path that implements the interface
213 if (0 == find(interface, path, service))
214 {
215 DBusValue value;
216
217 // autoreboot policy is implemented as a property
218 constexpr auto property = "AutoReboot";
219
220 if (0 == getProperty(interface, path, service, property, value))
221 {
222 // return value is a variant, autoreboot policy is boolean
223 autoReboot = std::get<bool>(value);
224 }
225 }
226
227 return autoReboot;
228}
229
Ben Tynerfe2c50d2021-07-23 13:38:53 -0500230/** @brief Get the running state of the host */
231HostRunningState hostRunningState()
232{
233 // assume not able to get host running state
234 HostRunningState host = HostRunningState::Unknown;
235
236 constexpr auto interface = "xyz.openbmc_project.State.Boot.Progress";
237
238 DBusService service;
239 DBusPath path;
240
241 // find a dbus object and path that implements the interface
242 if (0 == find(interface, path, service))
243 {
244 DBusValue value;
245
246 // boot progress is implemented as a property
247 constexpr auto property = "BootProgress";
248
249 if (0 == getProperty(interface, path, service, property, value))
250 {
251 // return value is a variant, progress is in the vector of strings
252 std::string bootProgress(std::get<std::string>(value));
253
254 // convert boot progress to host state
255 using BootProgress = sdbusplus::xyz::openbmc_project::State::Boot::
256 server::Progress::ProgressStages;
257
258 BootProgress stage = sdbusplus::xyz::openbmc_project::State::Boot::
259 server::Progress::convertProgressStagesFromString(bootProgress);
260
261 if ((stage == BootProgress::SystemInitComplete) ||
262 (stage == BootProgress::OSStart) ||
263 (stage == BootProgress::OSRunning))
264 {
265 host = HostRunningState::Started;
266 }
267 else
268 {
269 host = HostRunningState::NotStarted;
270 }
271 }
272 }
273
274 return host;
275}
276
Ben Tyner39fcf652021-10-19 20:38:29 -0500277/** @brief Read state of dumpPolicyEnabled property via dbus */
278bool dumpPolicyEnabled()
279{
280 // Assume true In case dumpPolicyEnabled property is not available
281 bool dumpPolicyEnabled = true;
282
283 constexpr auto interface = "xyz.openbmc_project.Object.Enable";
284 constexpr auto path = "/xyz/openbmc_project/dump/system_dump_policy";
285
286 DBusService service; // will find this
287
288 // find a dbus object and path that implements the interface
289 if (0 == findService(interface, path, service))
290 {
291 DBusValue value;
292
293 // autoreboot policy is implemented as a property
294 constexpr auto property = "Enabled";
295
296 if (0 == getProperty(interface, path, service, property, value))
297 {
298 // return value is a variant, dump policy enabled is a boolean
299 dumpPolicyEnabled = std::get<bool>(value);
300 }
301 }
302
303 return dumpPolicyEnabled;
304}
305
Ben Tyner324234b2021-06-28 17:01:17 -0500306} // namespace dbus
307
308} // namespace util