1 #pragma once
2
3 #include "pmbus.hpp"
4
5 #include <nlohmann/json.hpp>
6 #include <phosphor-logging/elog.hpp>
7 #include <phosphor-logging/log.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
26 using DbusPath = std::string;
27 using DbusProperty = std::string;
28 using DbusService = std::string;
29 using DbusInterface = std::string;
30 using DbusInterfaceList = std::vector<DbusInterface>;
31 using DbusSubtree =
32 std::map<DbusPath, std::map<DbusService, DbusInterfaceList>>;
33 using DbusVariant =
34 std::variant<bool, uint64_t, std::string, std::vector<uint64_t>,
35 std::vector<std::string>>;
36 using DbusPropertyMap = std::map<DbusProperty, DbusVariant>;
37 /**
38 * @brief Get the service name from the mapper for the
39 * interface and path passed in.
40 *
41 * @param[in] path - the D-Bus path name
42 * @param[in] interface - the D-Bus interface name
43 * @param[in] bus - the D-Bus object
44 * @param[in] logError - log error when no service found
45 *
46 * @return The service name
47 */
48 std::string getService(const std::string& path, const std::string& interface,
49 sdbusplus::bus_t& bus, bool logError = true);
50
51 /**
52 * @brief Read a D-Bus property
53 *
54 * @param[in] interface - the interface the property is on
55 * @param[in] propertName - the name of the property
56 * @param[in] path - the D-Bus path
57 * @param[in] service - the D-Bus service
58 * @param[in] bus - the D-Bus object
59 * @param[out] value - filled in with the property value
60 */
61 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)62 void getProperty(const std::string& interface, const std::string& propertyName,
63 const std::string& path, const std::string& service,
64 sdbusplus::bus_t& bus, T& value)
65 {
66 std::variant<T> property;
67
68 auto method = bus.new_method_call(service.c_str(), path.c_str(),
69 PROPERTY_INTF, "Get");
70
71 method.append(interface, propertyName);
72
73 auto reply = bus.call(method);
74
75 reply.read(property);
76 value = std::get<T>(property);
77 }
78
79 /**
80 * @brief Write a D-Bus property
81 *
82 * @param[in] interface - the interface the property is on
83 * @param[in] propertName - the name of the property
84 * @param[in] path - the D-Bus path
85 * @param[in] service - the D-Bus service
86 * @param[in] bus - the D-Bus object
87 * @param[in] value - the value to set the property to
88 */
89 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)90 void setProperty(const std::string& interface, const std::string& propertyName,
91 const std::string& path, const std::string& service,
92 sdbusplus::bus_t& bus, T& value)
93 {
94 std::variant<T> propertyValue(value);
95
96 auto method = bus.new_method_call(service.c_str(), path.c_str(),
97 PROPERTY_INTF, "Set");
98
99 method.append(interface, propertyName, propertyValue);
100
101 auto reply = bus.call(method);
102 }
103
104 /**
105 * @brief Get all D-Bus properties
106 *
107 * @param[in] bus - the D-Bus object
108 * @param[in] path - the D-Bus object path
109 * @param[in] interface - the D-Bus interface name
110 * @param[in] service - the D-Bus service name (optional)
111 *
112 * @return DbusPropertyMap - Map of property names and values
113 */
114 DbusPropertyMap getAllProperties(sdbusplus::bus_t& bus, const std::string& path,
115 const std::string& interface,
116 const std::string& service = std::string());
117
118 /** @brief Get subtree from the object mapper.
119 *
120 * Helper function to find objects, services, and interfaces.
121 * See:
122 * https://github.com/openbmc/docs/blob/master/architecture/object-mapper.md
123 *
124 * @param[in] bus - The D-Bus object.
125 * @param[in] path - The root of the tree to search.
126 * @param[in] interface - Interface in the subtree to search for
127 * @param[in] depth - The number of path elements to descend.
128 *
129 * @return DbusSubtree - Map of object paths to a map of service names to their
130 * interfaces.
131 */
132 DbusSubtree getSubTree(sdbusplus::bus_t& bus, const std::string& path,
133 const std::string& interface, int32_t depth);
134
135 /** @brief Get subtree from the object mapper.
136 *
137 * Helper function to find objects, services, and interfaces.
138 * See:
139 * https://github.com/openbmc/docs/blob/master/architecture/object-mapper.md
140 *
141 * @param[in] bus - The D-Bus object.
142 * @param[in] path - The root of the tree to search.
143 * @param[in] interfaces - Interfaces in the subtree to search for.
144 * @param[in] depth - The number of path elements to descend.
145 *
146 * @return DbusSubtree - Map of object paths to a map of service names to their
147 * interfaces.
148 */
149 DbusSubtree getSubTree(sdbusplus::bus_t& bus, const std::string& path,
150 const std::vector<std::string>& interfaces,
151 int32_t depth);
152
153 /** @brief GetAssociatedSubTreePaths wrapper from the object mapper.
154 *
155 * Helper function to find object paths that implement a certain
156 * interface and are also an association endpoint.
157 * See:
158 * https://github.com/openbmc/docs/blob/master/architecture/object-mapper.md
159 *
160 * @param[in] bus - The D-Bus object.
161 * @param[in] associationPath - The association it must be an endpoint of.
162 * @param[in] path - The root of the tree to search.
163 * @param[in] interfaces - The interfaces in the subtree to search for
164 * @param[in] depth - The number of path elements to descend.
165 *
166 * @return std::vector<DbusPath> - The object paths.
167 */
168 std::vector<DbusPath> getAssociatedSubTreePaths(
169 sdbusplus::bus_t& bus,
170 const sdbusplus::message::object_path& associationPath,
171 const sdbusplus::message::object_path& path,
172 const std::vector<std::string>& interfaces, int32_t depth);
173
174 /**
175 * Logs an error and powers off the system.
176 *
177 * @tparam T - error that will be logged before the power off
178 * @param[in] bus - D-Bus object
179 */
180 template <typename T>
powerOff(sdbusplus::bus_t & bus)181 void powerOff(sdbusplus::bus_t& bus)
182 {
183 phosphor::logging::report<T>();
184
185 auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
186 SYSTEMD_INTERFACE, "StartUnit");
187
188 method.append(POWEROFF_TARGET);
189 method.append("replace");
190
191 bus.call_noreply(method);
192 }
193
194 /**
195 * Load json from a file
196 *
197 * @param[in] path - The path of the json file
198 *
199 * @return The nlohmann::json object
200 */
201 nlohmann::json loadJSONFromFile(const char* path);
202
203 /**
204 * Get PmBus access type from the json config
205 *
206 * @param[in] json - The json object
207 *
208 * @return The pmbus access type
209 */
210 phosphor::pmbus::Type getPMBusAccessType(const nlohmann::json& json);
211
212 /**
213 * Check if power is on
214 *
215 * @param[in] bus - D-Bus object
216 * @param[in] defaultState - The default state if the function fails to get
217 * the power state.
218 *
219 * @return true if power is on, otherwise false;
220 * defaultState if it fails to get the power state.
221 */
222 bool isPoweredOn(sdbusplus::bus_t& bus, bool defaultState = false);
223
224 /**
225 * Get all PSU inventory paths from D-Bus
226 *
227 * @param[in] bus - D-Bus object
228 *
229 * @return The list of PSU inventory paths
230 */
231 std::vector<std::string> getPSUInventoryPaths(sdbusplus::bus_t& bus);
232
233 } // namespace util
234 } // namespace power
235 } // namespace phosphor
236