xref: /openbmc/phosphor-power/utility.hpp (revision 8b38b177315d40f1f9bc1e4d0784d45ea17cbd5c)
1 #pragma once
2 
3 #include "pmbus.hpp"
4 
5 #include <nlohmann/json.hpp>
6 #include <phosphor-logging/elog.hpp>
7 #include <phosphor-logging/lg2.hpp>
8 #include <sdbusplus/bus.hpp>
9 
10 #include <string>
11 #include <vector>
12 
13 namespace phosphor
14 {
15 namespace power
16 {
17 namespace util
18 {
19 
20 constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
21 constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
22 constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
23 constexpr auto POWEROFF_TARGET = "obmc-chassis-hard-poweroff@0.target";
24 constexpr auto PROPERTY_INTF = "org.freedesktop.DBus.Properties";
25 constexpr auto ENTITY_MGR_SERVICE = "xyz.openbmc_project.EntityManager";
26 
27 using DbusPath = std::string;
28 using DbusProperty = std::string;
29 using DbusService = std::string;
30 using DbusInterface = std::string;
31 using DbusInterfaceList = std::vector<DbusInterface>;
32 using DbusSubtree =
33     std::map<DbusPath, std::map<DbusService, DbusInterfaceList>>;
34 using DbusVariant =
35     std::variant<bool, uint64_t, std::string, std::vector<uint64_t>,
36                  std::vector<std::string>>;
37 using DbusPropertyMap = std::map<DbusProperty, DbusVariant>;
38 /**
39  * @brief Get the service name from the mapper for the
40  *        interface and path passed in.
41  *
42  * @param[in] path - the D-Bus path name
43  * @param[in] interface - the D-Bus interface name
44  * @param[in] bus - the D-Bus object
45  * @param[in] logError - log error when no service found
46  *
47  * @return The service name
48  */
49 std::string getService(const std::string& path, const std::string& interface,
50                        sdbusplus::bus_t& bus, bool logError = true);
51 
52 /**
53  * @brief Read a D-Bus property
54  *
55  * @param[in] interface - the interface the property is on
56  * @param[in] propertName - the name of the property
57  * @param[in] path - the D-Bus path
58  * @param[in] service - the D-Bus service
59  * @param[in] bus - the D-Bus object
60  * @param[out] value - filled in with the property value
61  */
62 template <typename T>
63 void getProperty(const std::string& interface, const std::string& propertyName,
64                  const std::string& path, const std::string& service,
65                  sdbusplus::bus_t& bus, T& value)
66 {
67     std::variant<T> property;
68 
69     auto method = bus.new_method_call(service.c_str(), path.c_str(),
70                                       PROPERTY_INTF, "Get");
71 
72     method.append(interface, propertyName);
73 
74     auto reply = bus.call(method);
75 
76     reply.read(property);
77     value = std::get<T>(property);
78 }
79 
80 /**
81  * @brief Write a D-Bus property
82  *
83  * @param[in] interface - the interface the property is on
84  * @param[in] propertName - the name of the property
85  * @param[in] path - the D-Bus path
86  * @param[in] service - the D-Bus service
87  * @param[in] bus - the D-Bus object
88  * @param[in] value - the value to set the property to
89  */
90 template <typename T>
91 void setProperty(const std::string& interface, const std::string& propertyName,
92                  const std::string& path, const std::string& service,
93                  sdbusplus::bus_t& bus, T& value)
94 {
95     std::variant<T> propertyValue(value);
96 
97     auto method = bus.new_method_call(service.c_str(), path.c_str(),
98                                       PROPERTY_INTF, "Set");
99 
100     method.append(interface, propertyName, propertyValue);
101 
102     auto reply = bus.call(method);
103 }
104 
105 /**
106  * @brief Get all D-Bus properties
107  *
108  * @param[in] bus - the D-Bus object
109  * @param[in] path - the D-Bus object path
110  * @param[in] interface - the D-Bus interface name
111  * @param[in] service - the D-Bus service name (optional)
112  *
113  * @return DbusPropertyMap - Map of property names and values
114  */
115 DbusPropertyMap getAllProperties(sdbusplus::bus_t& bus, const std::string& path,
116                                  const std::string& interface,
117                                  const std::string& service = std::string());
118 
119 /** @brief Get subtree from the object mapper.
120  *
121  * Helper function to find objects, services, and interfaces.
122  * See:
123  * https://github.com/openbmc/docs/blob/master/architecture/object-mapper.md
124  *
125  * @param[in] bus - The D-Bus object.
126  * @param[in] path - The root of the tree to search.
127  * @param[in] interface - Interface in the subtree to search for
128  * @param[in] depth - The number of path elements to descend.
129  *
130  * @return DbusSubtree - Map of object paths to a map of service names to their
131  *                       interfaces.
132  */
133 DbusSubtree getSubTree(sdbusplus::bus_t& bus, const std::string& path,
134                        const std::string& interface, int32_t depth);
135 
136 /** @brief Get subtree from the object mapper.
137  *
138  * Helper function to find objects, services, and interfaces.
139  * See:
140  * https://github.com/openbmc/docs/blob/master/architecture/object-mapper.md
141  *
142  * @param[in] bus - The D-Bus object.
143  * @param[in] path - The root of the tree to search.
144  * @param[in] interfaces - Interfaces in the subtree to search for.
145  * @param[in] depth - The number of path elements to descend.
146  *
147  * @return DbusSubtree - Map of object paths to a map of service names to their
148  *                       interfaces.
149  */
150 DbusSubtree getSubTree(sdbusplus::bus_t& bus, const std::string& path,
151                        const std::vector<std::string>& interfaces,
152                        int32_t depth);
153 
154 /** @brief GetAssociatedSubTreePaths wrapper from the object mapper.
155  *
156  * Helper function to find object paths that implement a certain
157  * interface and are also an association endpoint.
158  * See:
159  * https://github.com/openbmc/docs/blob/master/architecture/object-mapper.md
160  *
161  * @param[in] bus - The D-Bus object.
162  * @param[in] associationPath - The association it must be an endpoint of.
163  * @param[in] path - The root of the tree to search.
164  * @param[in] interfaces - The interfaces in the subtree to search for
165  * @param[in] depth - The number of path elements to descend.
166  *
167  * @return std::vector<DbusPath> - The object paths.
168  */
169 std::vector<DbusPath> getAssociatedSubTreePaths(
170     sdbusplus::bus_t& bus,
171     const sdbusplus::message::object_path& associationPath,
172     const sdbusplus::message::object_path& path,
173     const std::vector<std::string>& interfaces, int32_t depth);
174 
175 /**
176  * Logs an error and powers off the system.
177  *
178  * @tparam T - error that will be logged before the power off
179  * @param[in] bus - D-Bus object
180  */
181 template <typename T>
182 void powerOff(sdbusplus::bus_t& bus)
183 {
184     phosphor::logging::report<T>();
185 
186     auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
187                                       SYSTEMD_INTERFACE, "StartUnit");
188 
189     method.append(POWEROFF_TARGET);
190     method.append("replace");
191 
192     bus.call_noreply(method);
193 }
194 
195 /**
196  * Load json from a file
197  *
198  * @param[in] path - The path of the json file
199  *
200  * @return The nlohmann::json object
201  */
202 nlohmann::json loadJSONFromFile(const char* path);
203 
204 /**
205  * Get PmBus access type from the json config
206  *
207  * @param[in] json - The json object
208  *
209  * @return The pmbus access type
210  */
211 phosphor::pmbus::Type getPMBusAccessType(const nlohmann::json& json);
212 
213 /**
214  * Check if power is on
215  *
216  * @param[in] bus - D-Bus object
217  * @param[in] defaultState - The default state if the function fails to get
218  *                           the power state.
219  *
220  * @return true if power is on, otherwise false;
221  *         defaultState if it fails to get the power state.
222  */
223 bool isPoweredOn(sdbusplus::bus_t& bus, bool defaultState = false);
224 
225 /**
226  * Get all PSU inventory paths from D-Bus
227  *
228  * @param[in] bus - D-Bus object
229  *
230  * @return The list of PSU inventory paths
231  */
232 std::vector<std::string> getPSUInventoryPaths(sdbusplus::bus_t& bus);
233 
234 /**
235  * @detail Get all chassis inventory paths from D-Bus
236  *
237  * @param[in] bus - D-Bus object
238  *
239  * @return The list of chassis inventory paths
240  */
241 std::vector<std::string> getChassisInventoryPaths(sdbusplus::bus_t& bus);
242 
243 /**
244  * @brief Retrieve the chassis ID for the given D-Bus inventory path.
245  * Query the D-Bus interface for inventory object path and retrieve its unique
246  * ID (ID specified by SlotNumber)
247  *
248  * @param[in] bus - D-Bus object
249  * @param[in] path - The inventory manager D-Bus path for a chassis.
250  *
251  * @return uint64_t - Chassis unique ID
252  */
253 uint64_t getChassisInventoryUniqueId(sdbusplus::bus_t& bus,
254                                      const std::string& path);
255 /**
256  * @brief Retrieve the parent chassis unique ID from the Entity Manager.
257  * Given a D-Bus object path, this function extracts the parent path (board or
258  * chassis) and retrieve the chassis unique ID from Entity Manager.
259  *
260  * @param[in] bus - D-Bus object
261  * @param[in] path - The EntityManager D-Bus path for hardware within a chassis
262  * or board.
263  *
264  * @return uint64_t - Chassis unique ID
265  *
266  * @note This function assumes the parent object path contains property in
267  * Entity Manager.
268  */
269 uint64_t getParentEMUniqueId(sdbusplus::bus_t& bus, const std::string& path);
270 
271 } // namespace util
272 } // namespace power
273 } // namespace phosphor
274