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>
getProperty(const std::string & interface,const std::string & propertyName,const std::string & path,const std::string & service,sdbusplus::bus_t & bus,T & value)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>
setProperty(const std::string & interface,const std::string & propertyName,const std::string & path,const std::string & service,sdbusplus::bus_t & bus,T & value)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>
powerOff(sdbusplus::bus_t & bus)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