xref: /openbmc/openpower-hw-diags/util/dbus.cpp (revision df9f8e4052fe31a59c0c15dbc6c4adbfd37cd2dc)
1324234b4SBen Tyner #include <util/dbus.hpp>
2324234b4SBen Tyner #include <util/trace.hpp>
3fe2c50d7SBen Tyner #include <xyz/openbmc_project/State/Boot/Progress/server.hpp>
4324234b4SBen Tyner 
5710101c0SPatrick Williams #include <format>
6710101c0SPatrick Williams 
7324234b4SBen Tyner namespace util
8324234b4SBen Tyner {
9324234b4SBen Tyner namespace dbus
10324234b4SBen Tyner {
11324234b4SBen Tyner //------------------------------------------------------------------------------
12324234b4SBen Tyner 
13324234b4SBen Tyner constexpr auto objectMapperService = "xyz.openbmc_project.ObjectMapper";
14324234b4SBen Tyner constexpr auto objectMapperPath = "/xyz/openbmc_project/object_mapper";
15324234b4SBen Tyner constexpr auto objectMapperInterface = "xyz.openbmc_project.ObjectMapper";
16324234b4SBen Tyner 
1788b10093SBen Tyner constexpr uint8_t terminusIdZero = 0;
1888b10093SBen Tyner 
19324234b4SBen Tyner /** @brief Find the path and service that implements the given interface */
find(const std::string & i_interface,std::string & o_path,std::string & o_service)20324234b4SBen Tyner int find(const std::string& i_interface, std::string& o_path,
21324234b4SBen Tyner          std::string& o_service)
22324234b4SBen Tyner {
23324234b4SBen Tyner     int rc = 1; // assume not success
24324234b4SBen Tyner 
25324234b4SBen Tyner     auto bus = sdbusplus::bus::new_default();
26324234b4SBen Tyner 
27324234b4SBen Tyner     try
28324234b4SBen Tyner     {
29659e65cfSBen Tyner         constexpr auto function = "GetSubTree";
30659e65cfSBen Tyner 
31324234b4SBen Tyner         auto method = bus.new_method_call(objectMapperService, objectMapperPath,
32324234b4SBen Tyner                                           objectMapperInterface, function);
33324234b4SBen Tyner 
34324234b4SBen Tyner         // Search the entire dbus tree for the specified interface
35324234b4SBen Tyner         method.append(std::string{"/"}, 0,
36324234b4SBen Tyner                       std::vector<std::string>{i_interface});
37324234b4SBen Tyner 
38324234b4SBen Tyner         auto reply = bus.call(method);
39324234b4SBen Tyner 
40324234b4SBen Tyner         DBusSubTree response;
41324234b4SBen Tyner         reply.read(response);
42324234b4SBen Tyner 
43324234b4SBen Tyner         if (!response.empty())
44324234b4SBen Tyner         {
45324234b4SBen Tyner             // Response is a map of object paths to a map of service, interfaces
46324234b4SBen Tyner             auto object = *(response.begin());
47324234b4SBen Tyner             o_path = object.first;                    // return path
48324234b4SBen Tyner             o_service = object.second.begin()->first; // return service
49324234b4SBen Tyner 
50324234b4SBen Tyner             rc = 0;                                   // success
51324234b4SBen Tyner         }
52324234b4SBen Tyner     }
53324234b4SBen Tyner     catch (const sdbusplus::exception::SdBusError& e)
54324234b4SBen Tyner     {
55324234b4SBen Tyner         trace::err("util::dbus::find exception");
56324234b4SBen Tyner         std::string traceMsg = std::string(e.what());
57324234b4SBen Tyner         trace::err(traceMsg.c_str());
58324234b4SBen Tyner     }
59324234b4SBen Tyner 
60324234b4SBen Tyner     return rc;
61324234b4SBen Tyner }
62324234b4SBen Tyner 
63324234b4SBen Tyner /** @brief Find the service that implements the given object and interface */
findService(const std::string & i_interface,const std::string & i_path,std::string & o_service)64324234b4SBen Tyner int findService(const std::string& i_interface, const std::string& i_path,
65324234b4SBen Tyner                 std::string& o_service)
66324234b4SBen Tyner {
67324234b4SBen Tyner     int rc = 1; // assume not success
68324234b4SBen Tyner 
69324234b4SBen Tyner     auto bus = sdbusplus::bus::new_default();
70324234b4SBen Tyner 
71324234b4SBen Tyner     try
72324234b4SBen Tyner     {
73659e65cfSBen Tyner         constexpr auto function = "GetObject";
74659e65cfSBen Tyner 
75324234b4SBen Tyner         auto method = bus.new_method_call(objectMapperService, objectMapperPath,
76324234b4SBen Tyner                                           objectMapperInterface, function);
77324234b4SBen Tyner 
78324234b4SBen Tyner         // Find services that implement the object path, constrain the search
79324234b4SBen Tyner         // to the given interface.
80324234b4SBen Tyner         method.append(i_path, std::vector<std::string>{i_interface});
81324234b4SBen Tyner 
82324234b4SBen Tyner         auto reply = bus.call(method);
83324234b4SBen Tyner 
84324234b4SBen Tyner         // response is a map of service names to their interfaces
85324234b4SBen Tyner         std::map<DBusService, DBusInterfaceList> response;
86324234b4SBen Tyner         reply.read(response);
87324234b4SBen Tyner 
88324234b4SBen Tyner         if (!response.empty())
89324234b4SBen Tyner         {
90324234b4SBen Tyner             // return the service
91324234b4SBen Tyner             o_service = response.begin()->first;
92324234b4SBen Tyner 
93324234b4SBen Tyner             rc = 0; // success
94324234b4SBen Tyner         }
95324234b4SBen Tyner     }
96324234b4SBen Tyner     catch (const sdbusplus::exception::SdBusError& e)
97324234b4SBen Tyner     {
98324234b4SBen Tyner         trace::err("util::dbus::map exception");
99324234b4SBen Tyner         std::string traceMsg = std::string(e.what());
100324234b4SBen Tyner         trace::err(traceMsg.c_str());
101324234b4SBen Tyner     }
102324234b4SBen Tyner 
103324234b4SBen Tyner     return rc;
104324234b4SBen Tyner }
105324234b4SBen Tyner 
106324234b4SBen Tyner /** @brief Read a property from a dbus object interface */
getProperty(const std::string & i_interface,const std::string & i_path,const std::string & i_service,const std::string & i_property,DBusValue & o_response)107324234b4SBen Tyner int getProperty(const std::string& i_interface, const std::string& i_path,
108324234b4SBen Tyner                 const std::string& i_service, const std::string& i_property,
109324234b4SBen Tyner                 DBusValue& o_response)
110324234b4SBen Tyner {
111324234b4SBen Tyner     int rc = 1; // assume not success
112324234b4SBen Tyner 
113324234b4SBen Tyner     auto bus = sdbusplus::bus::new_default();
114324234b4SBen Tyner 
115659e65cfSBen Tyner     try
116659e65cfSBen Tyner     {
117324234b4SBen Tyner         constexpr auto interface = "org.freedesktop.DBus.Properties";
118324234b4SBen Tyner         constexpr auto function = "Get";
119324234b4SBen Tyner 
120324234b4SBen Tyner         // calling the get property method
121324234b4SBen Tyner         auto method = bus.new_method_call(i_service.c_str(), i_path.c_str(),
122324234b4SBen Tyner                                           interface, function);
123324234b4SBen Tyner 
124324234b4SBen Tyner         method.append(i_interface, i_property);
125324234b4SBen Tyner         auto reply = bus.call(method);
126324234b4SBen Tyner 
127324234b4SBen Tyner         // returning the property value
128324234b4SBen Tyner         reply.read(o_response);
129324234b4SBen Tyner 
130324234b4SBen Tyner         rc = 0; // success
131324234b4SBen Tyner     }
132324234b4SBen Tyner     catch (const sdbusplus::exception::SdBusError& e)
133324234b4SBen Tyner     {
134324234b4SBen Tyner         trace::err("util::dbus::getProperty exception");
135324234b4SBen Tyner         std::string traceMsg = std::string(e.what());
136324234b4SBen Tyner         trace::err(traceMsg.c_str());
137324234b4SBen Tyner     }
138324234b4SBen Tyner 
139324234b4SBen Tyner     return rc;
140324234b4SBen Tyner }
141324234b4SBen Tyner 
142324234b4SBen Tyner /** @brief Get the IBM compatible names defined for this system */
systemNames()143324234b4SBen Tyner std::vector<std::string> systemNames()
144324234b4SBen Tyner {
145324234b4SBen Tyner     std::vector<std::string> names;
146324234b4SBen Tyner 
147324234b4SBen Tyner     constexpr auto interface =
148324234b4SBen Tyner         "xyz.openbmc_project.Configuration.IBMCompatibleSystem";
149324234b4SBen Tyner 
150324234b4SBen Tyner     DBusService service;
151324234b4SBen Tyner     DBusPath path;
152324234b4SBen Tyner 
153324234b4SBen Tyner     // find a dbus object and path that implements the interface
154324234b4SBen Tyner     if (0 == find(interface, path, service))
155324234b4SBen Tyner     {
156324234b4SBen Tyner         DBusValue value;
157324234b4SBen Tyner 
158324234b4SBen Tyner         // compatible system names are implemented as a property
159324234b4SBen Tyner         constexpr auto property = "Names";
160324234b4SBen Tyner 
161324234b4SBen Tyner         if (0 == getProperty(interface, path, service, property, value))
162324234b4SBen Tyner         {
163324234b4SBen Tyner             // return value is a variant, names are in the vector
164324234b4SBen Tyner             names = std::get<std::vector<std::string>>(value);
165324234b4SBen Tyner         }
166324234b4SBen Tyner     }
167324234b4SBen Tyner 
168324234b4SBen Tyner     return names;
169324234b4SBen Tyner }
170324234b4SBen Tyner 
1719306716dSBen Tyner /** @brief Transition the host state */
transitionHost(const HostState i_hostState)1729306716dSBen Tyner void transitionHost(const HostState i_hostState)
1739306716dSBen Tyner {
1749306716dSBen Tyner     try
1759306716dSBen Tyner     {
1769306716dSBen Tyner         // We will be transitioning host by starting appropriate dbus target
1779306716dSBen Tyner         std::string target = "obmc-host-quiesce@0.target"; // quiesce is default
1789306716dSBen Tyner 
1799306716dSBen Tyner         // crash (mpipl) mode state requested
1809306716dSBen Tyner         if (HostState::Crash == i_hostState)
1819306716dSBen Tyner         {
1829306716dSBen Tyner             target = "obmc-host-crash@0.target";
1839306716dSBen Tyner         }
1849306716dSBen Tyner 
1851ff926e0SAndrew Geissler         // If the system is powering off for any reason (ex. we hit a PHYP TI
1861ff926e0SAndrew Geissler         // in the graceful power off path), then we want to call the immediate
1871ff926e0SAndrew Geissler         // power off target
1881ff926e0SAndrew Geissler         if (hostRunningState() == HostRunningState::Stopping)
1891ff926e0SAndrew Geissler         {
1901ff926e0SAndrew Geissler             trace::inf("system is powering off so no dump will be requested");
1911ff926e0SAndrew Geissler             target = "obmc-chassis-hard-poweroff@0.target";
1921ff926e0SAndrew Geissler         }
1931ff926e0SAndrew Geissler 
1949306716dSBen Tyner         auto bus = sdbusplus::bus::new_system();
1959306716dSBen Tyner         auto method = bus.new_method_call(
1969306716dSBen Tyner             "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
1979306716dSBen Tyner             "org.freedesktop.systemd1.Manager", "StartUnit");
1989306716dSBen Tyner 
1999306716dSBen Tyner         method.append(target);    // target unit to start
2009306716dSBen Tyner         method.append("replace"); // mode = replace conflicting queued jobs
2019306716dSBen Tyner 
2029306716dSBen Tyner         bus.call_noreply(method); // start the service
2039306716dSBen Tyner     }
2049306716dSBen Tyner     catch (const sdbusplus::exception::SdBusError& e)
2059306716dSBen Tyner     {
2069306716dSBen Tyner         trace::err("util::dbus::transitionHost exception");
2079306716dSBen Tyner         std::string traceMsg = std::string(e.what());
2089306716dSBen Tyner         trace::err(traceMsg.c_str());
2099306716dSBen Tyner     }
2109306716dSBen Tyner }
2119306716dSBen Tyner 
21239fcf65dSBen Tyner /** @brief Read state of autoRebootEnabled property via dbus */
autoRebootEnabled()213ffb4867fSBen Tyner bool autoRebootEnabled()
214ffb4867fSBen Tyner {
21539fcf65dSBen Tyner     // Assume true in case autoRebootEnbabled property is not available
21639fcf65dSBen Tyner     bool autoReboot = true;
217ffb4867fSBen Tyner 
218ffb4867fSBen Tyner     constexpr auto interface = "xyz.openbmc_project.Control.Boot.RebootPolicy";
219ffb4867fSBen Tyner 
22039fcf65dSBen Tyner     DBusService service; // will find this
22139fcf65dSBen Tyner     DBusPath path;       // will find this
222ffb4867fSBen Tyner 
223ffb4867fSBen Tyner     // find a dbus object and path that implements the interface
224ffb4867fSBen Tyner     if (0 == find(interface, path, service))
225ffb4867fSBen Tyner     {
226ffb4867fSBen Tyner         DBusValue value;
227ffb4867fSBen Tyner 
228ffb4867fSBen Tyner         // autoreboot policy is implemented as a property
229ffb4867fSBen Tyner         constexpr auto property = "AutoReboot";
230ffb4867fSBen Tyner 
231ffb4867fSBen Tyner         if (0 == getProperty(interface, path, service, property, value))
232ffb4867fSBen Tyner         {
233ffb4867fSBen Tyner             // return value is a variant, autoreboot policy is boolean
234ffb4867fSBen Tyner             autoReboot = std::get<bool>(value);
235ffb4867fSBen Tyner         }
236ffb4867fSBen Tyner     }
237ffb4867fSBen Tyner 
238ffb4867fSBen Tyner     return autoReboot;
239ffb4867fSBen Tyner }
240ffb4867fSBen Tyner 
241fe2c50d7SBen Tyner /** @brief Get the running state of the host */
hostRunningState()242fe2c50d7SBen Tyner HostRunningState hostRunningState()
243fe2c50d7SBen Tyner {
244fe2c50d7SBen Tyner     // assume not able to get host running state
245fe2c50d7SBen Tyner     HostRunningState host = HostRunningState::Unknown;
246fe2c50d7SBen Tyner 
247fe2c50d7SBen Tyner     constexpr auto interface = "xyz.openbmc_project.State.Boot.Progress";
248fe2c50d7SBen Tyner 
249fe2c50d7SBen Tyner     DBusService service;
250fe2c50d7SBen Tyner     DBusPath path;
251fe2c50d7SBen Tyner 
252fe2c50d7SBen Tyner     // find a dbus object and path that implements the interface
253fe2c50d7SBen Tyner     if (0 == find(interface, path, service))
254fe2c50d7SBen Tyner     {
255fe2c50d7SBen Tyner         DBusValue value;
256fe2c50d7SBen Tyner 
257fe2c50d7SBen Tyner         // boot progress is implemented as a property
258fe2c50d7SBen Tyner         constexpr auto property = "BootProgress";
259fe2c50d7SBen Tyner 
260fe2c50d7SBen Tyner         if (0 == getProperty(interface, path, service, property, value))
261fe2c50d7SBen Tyner         {
262fe2c50d7SBen Tyner             // return value is a variant, progress is in the vector of strings
263fe2c50d7SBen Tyner             std::string bootProgress(std::get<std::string>(value));
264fe2c50d7SBen Tyner 
265fe2c50d7SBen Tyner             // convert boot progress to host state
266fe2c50d7SBen Tyner             using BootProgress = sdbusplus::xyz::openbmc_project::State::Boot::
267fe2c50d7SBen Tyner                 server::Progress::ProgressStages;
268fe2c50d7SBen Tyner 
269fe2c50d7SBen Tyner             BootProgress stage = sdbusplus::xyz::openbmc_project::State::Boot::
270fe2c50d7SBen Tyner                 server::Progress::convertProgressStagesFromString(bootProgress);
271fe2c50d7SBen Tyner 
272fe2c50d7SBen Tyner             if ((stage == BootProgress::SystemInitComplete) ||
273fe2c50d7SBen Tyner                 (stage == BootProgress::OSRunning))
274fe2c50d7SBen Tyner             {
275fe2c50d7SBen Tyner                 host = HostRunningState::Started;
276fe2c50d7SBen Tyner             }
277fe2c50d7SBen Tyner             else
278fe2c50d7SBen Tyner             {
279fe2c50d7SBen Tyner                 host = HostRunningState::NotStarted;
280fe2c50d7SBen Tyner             }
281fe2c50d7SBen Tyner         }
282fe2c50d7SBen Tyner     }
283fe2c50d7SBen Tyner 
2841ff926e0SAndrew Geissler     // See if host in process of powering off when we get NotStarted
2851ff926e0SAndrew Geissler     if (host == HostRunningState::NotStarted)
2861ff926e0SAndrew Geissler     {
2871ff926e0SAndrew Geissler         constexpr auto hostStateInterface = "xyz.openbmc_project.State.Host";
2881ff926e0SAndrew Geissler         if (0 == find(hostStateInterface, path, service))
2891ff926e0SAndrew Geissler         {
2901ff926e0SAndrew Geissler             DBusValue value;
2911ff926e0SAndrew Geissler 
2921ff926e0SAndrew Geissler             // current host state is implemented as a property
2931ff926e0SAndrew Geissler             constexpr auto stateProperty = "CurrentHostState";
2941ff926e0SAndrew Geissler 
2951ff926e0SAndrew Geissler             if (0 == getProperty(hostStateInterface, path, service,
2961ff926e0SAndrew Geissler                                  stateProperty, value))
2971ff926e0SAndrew Geissler             {
2981ff926e0SAndrew Geissler                 // return value is a variant, host state is in the vector of
2991ff926e0SAndrew Geissler                 // strings
3001ff926e0SAndrew Geissler                 std::string hostState(std::get<std::string>(value));
3011ff926e0SAndrew Geissler                 if (hostState == "xyz.openbmc_project.State.Host.HostState."
3021ff926e0SAndrew Geissler                                  "TransitioningToOff")
3031ff926e0SAndrew Geissler                 {
3041ff926e0SAndrew Geissler                     host = HostRunningState::Stopping;
3051ff926e0SAndrew Geissler                 }
3061ff926e0SAndrew Geissler             }
3071ff926e0SAndrew Geissler         }
3081ff926e0SAndrew Geissler     }
3091ff926e0SAndrew Geissler 
310fe2c50d7SBen Tyner     return host;
311fe2c50d7SBen Tyner }
312fe2c50d7SBen Tyner 
31339fcf65dSBen Tyner /** @brief Read state of dumpPolicyEnabled property via dbus */
dumpPolicyEnabled()31439fcf65dSBen Tyner bool dumpPolicyEnabled()
31539fcf65dSBen Tyner {
31639fcf65dSBen Tyner     // Assume true In case dumpPolicyEnabled property is not available
31739fcf65dSBen Tyner     bool dumpPolicyEnabled = true;
31839fcf65dSBen Tyner 
31939fcf65dSBen Tyner     constexpr auto interface = "xyz.openbmc_project.Object.Enable";
32039fcf65dSBen Tyner     constexpr auto path = "/xyz/openbmc_project/dump/system_dump_policy";
32139fcf65dSBen Tyner 
32239fcf65dSBen Tyner     DBusService service; // will find this
32339fcf65dSBen Tyner 
32439fcf65dSBen Tyner     // find a dbus object and path that implements the interface
32539fcf65dSBen Tyner     if (0 == findService(interface, path, service))
32639fcf65dSBen Tyner     {
32739fcf65dSBen Tyner         DBusValue value;
32839fcf65dSBen Tyner 
32939fcf65dSBen Tyner         // autoreboot policy is implemented as a property
33039fcf65dSBen Tyner         constexpr auto property = "Enabled";
33139fcf65dSBen Tyner 
33239fcf65dSBen Tyner         if (0 == getProperty(interface, path, service, property, value))
33339fcf65dSBen Tyner         {
33439fcf65dSBen Tyner             // return value is a variant, dump policy enabled is a boolean
33539fcf65dSBen Tyner             dumpPolicyEnabled = std::get<bool>(value);
33639fcf65dSBen Tyner         }
33739fcf65dSBen Tyner     }
33839fcf65dSBen Tyner 
33939fcf65dSBen Tyner     return dumpPolicyEnabled;
34039fcf65dSBen Tyner }
34139fcf65dSBen Tyner 
3421315968cSBen Tyner /** @brief Create a PEL */
createPel(const std::string & i_message,const std::string & i_severity,std::map<std::string,std::string> & io_additional,const std::vector<util::FFDCTuple> & i_ffdc)3431315968cSBen Tyner uint32_t createPel(const std::string& i_message, const std::string& i_severity,
3441315968cSBen Tyner                    std::map<std::string, std::string>& io_additional,
3451315968cSBen Tyner                    const std::vector<util::FFDCTuple>& i_ffdc)
3461315968cSBen Tyner {
3471315968cSBen Tyner     // CreatePELWithFFDCFiles returns plid
3481315968cSBen Tyner     int plid = 0;
3491315968cSBen Tyner 
3501315968cSBen Tyner     // Sdbus call specifics
3511315968cSBen Tyner     constexpr auto interface = "org.open_power.Logging.PEL";
3521315968cSBen Tyner     constexpr auto path = "/xyz/openbmc_project/logging";
3531315968cSBen Tyner 
3541315968cSBen Tyner     // we need to find the service implementing the interface
3551315968cSBen Tyner     util::dbus::DBusService service;
3561315968cSBen Tyner 
3571315968cSBen Tyner     if (0 == findService(interface, path, service))
3581315968cSBen Tyner     {
3591315968cSBen Tyner         try
3601315968cSBen Tyner         {
3611315968cSBen Tyner             constexpr auto function = "CreatePELWithFFDCFiles";
3621315968cSBen Tyner 
3631315968cSBen Tyner             // The "Create" method requires manually adding the process ID.
3641315968cSBen Tyner             io_additional["_PID"] = std::to_string(getpid());
3651315968cSBen Tyner 
3661315968cSBen Tyner             // create dbus method
3671315968cSBen Tyner             auto bus = sdbusplus::bus::new_system();
368e212fb06SPatrick Williams             sdbusplus::message_t method =
3691315968cSBen Tyner                 bus.new_method_call(service.c_str(), path, interface, function);
3701315968cSBen Tyner 
3711315968cSBen Tyner             // append additional dbus call paramaters
3721315968cSBen Tyner             method.append(i_message, i_severity, io_additional, i_ffdc);
3731315968cSBen Tyner 
3741315968cSBen Tyner             // using system dbus
3751315968cSBen Tyner             auto response = bus.call(method);
3761315968cSBen Tyner 
3771315968cSBen Tyner             // reply will be tuple containing bmc log id, platform log id
3781315968cSBen Tyner             std::tuple<uint32_t, uint32_t> reply = {0, 0};
3791315968cSBen Tyner 
3801315968cSBen Tyner             // parse dbus response into reply
3811315968cSBen Tyner             response.read(reply);
3821315968cSBen Tyner             plid = std::get<1>(reply); // platform log id is tuple "second"
3831315968cSBen Tyner         }
3841315968cSBen Tyner         catch (const sdbusplus::exception::SdBusError& e)
3851315968cSBen Tyner         {
3861315968cSBen Tyner             trace::err("createPel exception");
3871315968cSBen Tyner             trace::err(e.what());
3881315968cSBen Tyner         }
3891315968cSBen Tyner     }
3901315968cSBen Tyner 
3911315968cSBen Tyner     return plid; // platform log id or 0
3921315968cSBen Tyner }
3931315968cSBen Tyner 
getMachineType()394626270afSCaleb Palmer MachineType getMachineType()
395626270afSCaleb Palmer {
396626270afSCaleb Palmer     // default to Rainier 2S4U
397626270afSCaleb Palmer     MachineType machineType = MachineType::Rainier_2S4U;
398626270afSCaleb Palmer 
399626270afSCaleb Palmer     // The return value of the dbus operation is a vector of 4 uint8_ts
400626270afSCaleb Palmer     std::vector<uint8_t> ids;
401626270afSCaleb Palmer 
402626270afSCaleb Palmer     constexpr auto interface = "com.ibm.ipzvpd.VSBP";
403626270afSCaleb Palmer 
404626270afSCaleb Palmer     DBusService service;
405626270afSCaleb Palmer     DBusPath path;
406626270afSCaleb Palmer 
407626270afSCaleb Palmer     if (0 == find(interface, path, service))
408626270afSCaleb Palmer     {
409626270afSCaleb Palmer         DBusValue value;
410626270afSCaleb Palmer 
411626270afSCaleb Palmer         // Machine ID is given from the "IM" keyword
412626270afSCaleb Palmer         constexpr auto property = "IM";
413626270afSCaleb Palmer 
414626270afSCaleb Palmer         if (0 == getProperty(interface, path, service, property, value))
415626270afSCaleb Palmer         {
416626270afSCaleb Palmer             // return value is a variant, ID value is a vector of 4 uint8_ts
417626270afSCaleb Palmer             ids = std::get<std::vector<uint8_t>>(value);
418626270afSCaleb Palmer 
419626270afSCaleb Palmer             // Convert the returned ID value to a hex string to determine
420626270afSCaleb Palmer             // machine type. The hex values corresponding to the machine type
421626270afSCaleb Palmer             // are defined in /openbmc/openpower-vpd-parser/const.hpp
422626270afSCaleb Palmer             // RAINIER_2S4U == 0x50001000
423626270afSCaleb Palmer             // RAINIER_2S2U == 0x50001001
424626270afSCaleb Palmer             // RAINIER_1S4U == 0x50001002
425626270afSCaleb Palmer             // RAINIER_1S2U == 0x50001003
426626270afSCaleb Palmer             // EVEREST      == 0x50003000
427a7dc66baSZane Shelley             // BONNELL      == 0x50004000
428626270afSCaleb Palmer             try
429626270afSCaleb Palmer             {
430626270afSCaleb Palmer                 // Format the vector into a single hex string to compare to.
431a0c724d3SPatrick Williams                 std::string hexId =
432a0c724d3SPatrick Williams                     std::format("0x{:02x}{:02x}{:02x}{:02x}", ids.at(0),
433a0c724d3SPatrick Williams                                 ids.at(1), ids.at(2), ids.at(3));
434626270afSCaleb Palmer 
435626270afSCaleb Palmer                 std::map<std::string, MachineType> typeMap = {
436626270afSCaleb Palmer                     {"0x50001000", MachineType::Rainier_2S4U},
437626270afSCaleb Palmer                     {"0x50001001", MachineType::Rainier_2S2U},
438626270afSCaleb Palmer                     {"0x50001002", MachineType::Rainier_1S4U},
439626270afSCaleb Palmer                     {"0x50001003", MachineType::Rainier_1S2U},
440626270afSCaleb Palmer                     {"0x50003000", MachineType::Everest},
441a7dc66baSZane Shelley                     {"0x50004000", MachineType::Bonnell},
442*df9f8e40SZane Shelley                     {"0x60001000", MachineType::BlueRidge_2S4U},
443*df9f8e40SZane Shelley                     {"0x60001001", MachineType::BlueRidge_2S2U},
444*df9f8e40SZane Shelley                     {"0x60001002", MachineType::BlueRidge_1S4U},
445*df9f8e40SZane Shelley                     {"0x60002000", MachineType::Fuji},
446*df9f8e40SZane Shelley                     {"0x60004000", MachineType::Balcones},
447626270afSCaleb Palmer                 };
448626270afSCaleb Palmer 
449626270afSCaleb Palmer                 machineType = typeMap.at(hexId);
450626270afSCaleb Palmer             }
451626270afSCaleb Palmer             catch (const std::out_of_range& e)
452626270afSCaleb Palmer             {
453626270afSCaleb Palmer                 trace::err("Out of range exception caught from returned "
454626270afSCaleb Palmer                            "machine ID.");
455626270afSCaleb Palmer                 for (const auto& id : ids)
456626270afSCaleb Palmer                 {
457626270afSCaleb Palmer                     trace::err("Returned Machine ID value: 0x%x", id);
458626270afSCaleb Palmer                 }
459626270afSCaleb Palmer                 throw;
460626270afSCaleb Palmer             }
461626270afSCaleb Palmer         }
462626270afSCaleb Palmer     }
463626270afSCaleb Palmer     else
464626270afSCaleb Palmer     {
465626270afSCaleb Palmer         throw std::invalid_argument(
466626270afSCaleb Palmer             "Unable to find dbus service to get machine type.");
467626270afSCaleb Palmer     }
468626270afSCaleb Palmer 
469626270afSCaleb Palmer     return machineType;
470626270afSCaleb Palmer }
471626270afSCaleb Palmer 
47288b10093SBen Tyner /** @brief Get list of state effecter PDRs */
getStateEffecterPdrs(std::vector<std::vector<uint8_t>> & pdrList,uint16_t stateSetId)47388b10093SBen Tyner bool getStateEffecterPdrs(std::vector<std::vector<uint8_t>>& pdrList,
47488b10093SBen Tyner                           uint16_t stateSetId)
47588b10093SBen Tyner {
47688b10093SBen Tyner     constexpr auto service = "xyz.openbmc_project.PLDM";
47788b10093SBen Tyner     constexpr auto path = "/xyz/openbmc_project/pldm";
47888b10093SBen Tyner     constexpr auto interface = "xyz.openbmc_project.PLDM.PDR";
47988b10093SBen Tyner     constexpr auto function = "FindStateEffecterPDR";
480324234b4SBen Tyner 
48188b10093SBen Tyner     constexpr uint16_t PLDM_ENTITY_PROC = 135;
48288b10093SBen Tyner 
48388b10093SBen Tyner     try
48488b10093SBen Tyner     {
48588b10093SBen Tyner         // create dbus method
48688b10093SBen Tyner         auto bus = sdbusplus::bus::new_default();
487a0c724d3SPatrick Williams         sdbusplus::message_t method =
488a0c724d3SPatrick Williams             bus.new_method_call(service, path, interface, function);
48988b10093SBen Tyner 
49088b10093SBen Tyner         // append additional method data
49188b10093SBen Tyner         method.append(terminusIdZero, PLDM_ENTITY_PROC, stateSetId);
49288b10093SBen Tyner 
49388b10093SBen Tyner         // request PDRs
49488b10093SBen Tyner         auto reply = bus.call(method);
49588b10093SBen Tyner         reply.read(pdrList);
49688b10093SBen Tyner     }
49788b10093SBen Tyner     catch (const sdbusplus::exception_t& e)
49888b10093SBen Tyner     {
49988b10093SBen Tyner         trace::err("failed to find state effecter PDRs");
50088b10093SBen Tyner         trace::err(e.what());
50188b10093SBen Tyner         return false;
50288b10093SBen Tyner     }
50388b10093SBen Tyner 
50488b10093SBen Tyner     return true;
50588b10093SBen Tyner }
50688b10093SBen Tyner 
50788b10093SBen Tyner /** @brief Get list of state sensor PDRs */
getStateSensorPdrs(std::vector<std::vector<uint8_t>> & pdrList,uint16_t stateSetId)50888b10093SBen Tyner bool getStateSensorPdrs(std::vector<std::vector<uint8_t>>& pdrList,
50988b10093SBen Tyner                         uint16_t stateSetId)
51088b10093SBen Tyner {
51188b10093SBen Tyner     constexpr auto service = "xyz.openbmc_project.PLDM";
51288b10093SBen Tyner     constexpr auto path = "/xyz/openbmc_project/pldm";
51388b10093SBen Tyner     constexpr auto interface = "xyz.openbmc_project.PLDM.PDR";
51488b10093SBen Tyner     constexpr auto function = "FindStateSensorPDR";
51588b10093SBen Tyner 
51688b10093SBen Tyner     constexpr uint16_t PLDM_ENTITY_PROC = 135;
51788b10093SBen Tyner 
51888b10093SBen Tyner     try
51988b10093SBen Tyner     {
52088b10093SBen Tyner         // create dbus method
52188b10093SBen Tyner         auto bus = sdbusplus::bus::new_default();
522a0c724d3SPatrick Williams         sdbusplus::message_t method =
523a0c724d3SPatrick Williams             bus.new_method_call(service, path, interface, function);
52488b10093SBen Tyner 
52588b10093SBen Tyner         // append additional method data
52688b10093SBen Tyner         method.append(terminusIdZero, PLDM_ENTITY_PROC, stateSetId);
52788b10093SBen Tyner 
52888b10093SBen Tyner         // request PDRs
52988b10093SBen Tyner         auto reply = bus.call(method);
53088b10093SBen Tyner         reply.read(pdrList);
53188b10093SBen Tyner     }
53288b10093SBen Tyner     catch (const sdbusplus::exception_t& e)
53388b10093SBen Tyner     {
53488b10093SBen Tyner         trace::err("failed to find state sensor PDRs");
53588b10093SBen Tyner         trace::err(e.what());
53688b10093SBen Tyner         return false;
53788b10093SBen Tyner     }
53888b10093SBen Tyner 
53988b10093SBen Tyner     return true;
54088b10093SBen Tyner }
54188b10093SBen Tyner 
5422b26b2bbSBen Tyner /** @brief Determine if power fault was detected */
powerFault()5432b26b2bbSBen Tyner bool powerFault()
5442b26b2bbSBen Tyner {
5452b26b2bbSBen Tyner     // power fault based on pgood property
5462b26b2bbSBen Tyner     int32_t pgood = 0; // assume fault or unknown
5472b26b2bbSBen Tyner 
5482b26b2bbSBen Tyner     constexpr auto interface = "org.openbmc.control.Power";
5492b26b2bbSBen Tyner 
5502b26b2bbSBen Tyner     DBusService service;
5512b26b2bbSBen Tyner     DBusPath path;
5522b26b2bbSBen Tyner 
5532b26b2bbSBen Tyner     // find a dbus service and object path that implements the interface
5542b26b2bbSBen Tyner     if (0 == find(interface, path, service))
5552b26b2bbSBen Tyner     {
5562b26b2bbSBen Tyner         DBusValue value;
5572b26b2bbSBen Tyner 
5582b26b2bbSBen Tyner         // chassis pgood is implemented as a property
5592b26b2bbSBen Tyner         constexpr auto property = "pgood";
5602b26b2bbSBen Tyner 
5612b26b2bbSBen Tyner         if (0 == getProperty(interface, path, service, property, value))
5622b26b2bbSBen Tyner         {
5632b26b2bbSBen Tyner             // return value is a variant, int32 == 1 for pgood OK
5642b26b2bbSBen Tyner             pgood = std::get<int32_t>(value);
5652b26b2bbSBen Tyner         }
5662b26b2bbSBen Tyner     }
5672b26b2bbSBen Tyner 
5682b26b2bbSBen Tyner     return pgood != 1 ? true : false; // if not pgood then power fault
5692b26b2bbSBen Tyner }
5702b26b2bbSBen Tyner 
57188b10093SBen Tyner } // namespace dbus
572324234b4SBen Tyner } // namespace util
573