xref: /openbmc/witherspoon-pfault-analysis/utility.hpp (revision f0f02b9ae21ece3d691c1bbea348b468787ed2ff)
1 #pragma once
2 
3 #include <phosphor-logging/elog.hpp>
4 #include <phosphor-logging/log.hpp>
5 #include <sdbusplus/bus.hpp>
6 #include <string>
7 
8 namespace witherspoon
9 {
10 namespace power
11 {
12 namespace util
13 {
14 
15 constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
16 constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
17 constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
18 constexpr auto POWEROFF_TARGET = "obmc-chassis-hard-poweroff@0.target";
19 constexpr auto PROPERTY_INTF = "org.freedesktop.DBus.Properties";
20 
21 /**
22  * @brief Get the service name from the mapper for the
23  *        interface and path passed in.
24  *
25  * @param[in] path - the D-Bus path name
26  * @param[in] interface - the D-Bus interface name
27  * @param[in] bus - the D-Bus object
28  *
29  * @return The service name
30  */
31 std::string getService(const std::string& path, const std::string& interface,
32                        sdbusplus::bus::bus& bus);
33 
34 /**
35  * @brief Read a D-Bus property
36  *
37  * @param[in] interface - the interface the property is on
38  * @param[in] propertName - the name of the property
39  * @param[in] path - the D-Bus path
40  * @param[in] service - the D-Bus service
41  * @param[in] bus - the D-Bus object
42  * @param[out] value - filled in with the property value
43  */
44 template <typename T>
45 void getProperty(const std::string& interface, const std::string& propertyName,
46                  const std::string& path, const std::string& service,
47                  sdbusplus::bus::bus& bus, T& value)
48 {
49     sdbusplus::message::variant<T> property;
50 
51     auto method = bus.new_method_call(service.c_str(), path.c_str(),
52                                       PROPERTY_INTF, "Get");
53 
54     method.append(interface, propertyName);
55 
56     auto reply = bus.call(method);
57     if (reply.is_method_error())
58     {
59         using namespace phosphor::logging;
60         log<level::ERR>("Error in property get call",
61                         entry("PATH=%s", path.c_str()),
62                         entry("PROPERTY=%s", propertyName.c_str()));
63 
64         // TODO openbmc/openbmc#851 - Once available, throw returned error
65         throw std::runtime_error("Error in property get call");
66     }
67 
68     reply.read(property);
69     value = sdbusplus::message::variant_ns::get<T>(property);
70 }
71 
72 /**
73  * @brief Write a D-Bus property
74  *
75  * @param[in] interface - the interface the property is on
76  * @param[in] propertName - the name of the property
77  * @param[in] path - the D-Bus path
78  * @param[in] service - the D-Bus service
79  * @param[in] bus - the D-Bus object
80  * @param[in] value - the value to set the property to
81  */
82 template <typename T>
83 void setProperty(const std::string& interface, const std::string& propertyName,
84                  const std::string& path, const std::string& service,
85                  sdbusplus::bus::bus& bus, T& value)
86 {
87     sdbusplus::message::variant<T> propertyValue(value);
88 
89     auto method = bus.new_method_call(service.c_str(), path.c_str(),
90                                       PROPERTY_INTF, "Set");
91 
92     method.append(interface, propertyName, propertyValue);
93 
94     auto reply = bus.call(method);
95     if (reply.is_method_error())
96     {
97         using namespace phosphor::logging;
98         log<level::ERR>("Error in property set call",
99                         entry("SERVICE=%s", service.c_str()),
100                         entry("PATH=%s", path.c_str()),
101                         entry("PROPERTY=%s", propertyName.c_str()));
102 
103         // TODO openbmc/openbmc#851 - Once available, throw returned error
104         throw std::runtime_error("Error in property set call");
105     }
106 }
107 
108 /**
109  * Logs an error and powers off the system.
110  *
111  * @tparam T - error that will be logged before the power off
112  * @param[in] bus - D-Bus object
113  */
114 template <typename T>
115 void powerOff(sdbusplus::bus::bus& bus)
116 {
117     phosphor::logging::report<T>();
118 
119     auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
120                                       SYSTEMD_INTERFACE, "StartUnit");
121 
122     method.append(POWEROFF_TARGET);
123     method.append("replace");
124 
125     bus.call_noreply(method);
126 }
127 
128 } // namespace util
129 } // namespace power
130 } // namespace witherspoon
131