blob: b8b59bf6efa74dae7507e9fb241064606a2c07be [file] [log] [blame]
Tom Josephbe703f72017-03-09 12:34:35 +05301#pragma once
Patrick Venture0b02be92018-08-31 11:55:55 -07002
Vernon Maueryeeb0f982019-05-29 16:36:58 -07003#include <boost/system/error_code.hpp>
Kun Yi5dcf41e2019-03-05 14:02:51 -08004#include <chrono>
Yong Li7dc4ac02019-08-23 17:44:32 +08005#include <ipmid/api-types.hpp>
Vernon Maueryeeb0f982019-05-29 16:36:58 -07006#include <ipmid/message.hpp>
Vernon Mauery33250242019-03-12 16:49:26 -07007#include <ipmid/types.hpp>
Vernon Mauery54012502018-11-07 10:17:31 -08008#include <optional>
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -07009#include <sdbusplus/server.hpp>
Tom Josephbe703f72017-03-09 12:34:35 +053010
Tom Josephbe703f72017-03-09 12:34:35 +053011namespace ipmi
12{
13
Kun Yi5dcf41e2019-03-05 14:02:51 -080014using namespace std::literals::chrono_literals;
15
Ratan Guptacc8feb42017-07-25 21:52:10 +053016constexpr auto MAPPER_BUS_NAME = "xyz.openbmc_project.ObjectMapper";
17constexpr auto MAPPER_OBJ = "/xyz/openbmc_project/object_mapper";
18constexpr auto MAPPER_INTF = "xyz.openbmc_project.ObjectMapper";
19
20constexpr auto ROOT = "/";
21constexpr auto HOST_MATCH = "host0";
Ratan Guptacc8feb42017-07-25 21:52:10 +053022
Ratan Guptab8e99552017-07-27 07:07:48 +053023constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties";
24constexpr auto DELETE_INTERFACE = "xyz.openbmc_project.Object.Delete";
Ratan Guptacc8feb42017-07-25 21:52:10 +053025
26constexpr auto METHOD_GET = "Get";
27constexpr auto METHOD_GET_ALL = "GetAll";
28constexpr auto METHOD_SET = "Set";
29
Kun Yi5dcf41e2019-03-05 14:02:51 -080030/* Use a value of 5s which aligns with BT/KCS bridged timeouts, rather
31 * than the default 25s D-Bus timeout. */
32constexpr std::chrono::microseconds IPMI_DBUS_TIMEOUT = 5s;
33
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -070034/** @class ServiceCache
35 * @brief Caches lookups of service names from the object mapper.
36 * @details Most ipmi commands need to talk to other dbus daemons to perform
37 * their intended actions on the BMC. This usually means they will
38 * first look up the service name providing the interface they
39 * require. This class reduces the number of such calls by caching
40 * the lookup for a specific service.
41 */
Patrick Venture0b02be92018-08-31 11:55:55 -070042class ServiceCache
43{
44 public:
45 /** @brief Creates a new service cache for the given interface
46 * and path.
47 *
48 * @param[in] intf - The interface used for each lookup
49 * @param[in] path - The path used for each lookup
50 */
51 ServiceCache(const std::string& intf, const std::string& path);
52 ServiceCache(std::string&& intf, std::string&& path);
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -070053
Patrick Venture0b02be92018-08-31 11:55:55 -070054 /** @brief Gets the service name from the cache or does in a
55 * lookup when invalid.
56 *
57 * @param[in] bus - The bus associated with and used for looking
58 * up the service.
59 */
60 const std::string& getService(sdbusplus::bus::bus& bus);
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -070061
Patrick Venture0b02be92018-08-31 11:55:55 -070062 /** @brief Invalidates the current service name */
63 void invalidate();
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -070064
Patrick Venture0b02be92018-08-31 11:55:55 -070065 /** @brief A wrapper around sdbusplus bus.new_method_call
66 *
67 * @param[in] bus - The bus used for calling the method
68 * @param[in] intf - The interface containing the method
69 * @param[in] method - The method name
70 * @return The message containing the method call.
71 */
72 sdbusplus::message::message newMethodCall(sdbusplus::bus::bus& bus,
73 const char* intf,
74 const char* method);
William A. Kennington III82c173a2018-05-11 16:10:12 -070075
Patrick Venture0b02be92018-08-31 11:55:55 -070076 /** @brief Check to see if the current cache is valid
77 *
78 * @param[in] bus - The bus used for the service lookup
79 * @return True if the cache is valid false otherwise.
80 */
81 bool isValid(sdbusplus::bus::bus& bus) const;
82
83 private:
84 /** @brief DBUS interface provided by the service */
85 const std::string intf;
86 /** @brief DBUS path provided by the service */
87 const std::string path;
88 /** @brief The name of the service if valid */
Vernon Mauery54012502018-11-07 10:17:31 -080089 std::optional<std::string> cachedService;
Patrick Venture0b02be92018-08-31 11:55:55 -070090 /** @brief The name of the bus used in the service lookup */
Vernon Mauery54012502018-11-07 10:17:31 -080091 std::optional<std::string> cachedBusName;
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -070092};
93
Tom Josephbe703f72017-03-09 12:34:35 +053094/**
95 * @brief Get the DBUS Service name for the input dbus path
96 *
97 * @param[in] bus - DBUS Bus Object
98 * @param[in] intf - DBUS Interface
99 * @param[in] path - DBUS Object Path
100 *
101 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700102std::string getService(sdbusplus::bus::bus& bus, const std::string& intf,
Tom Josephbe703f72017-03-09 12:34:35 +0530103 const std::string& path);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530104
105/** @brief Gets the dbus object info implementing the given interface
106 * from the given subtree.
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530107 * @param[in] bus - DBUS Bus Object.
Ratan Guptacc8feb42017-07-25 21:52:10 +0530108 * @param[in] interface - Dbus interface.
109 * @param[in] subtreePath - subtree from where the search should start.
110 * @param[in] match - identifier for object.
111 * @return On success returns the object having objectpath and servicename.
112 */
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530113DbusObjectInfo getDbusObject(sdbusplus::bus::bus& bus,
114 const std::string& interface,
Ratan Guptacc8feb42017-07-25 21:52:10 +0530115 const std::string& subtreePath = ROOT,
116 const std::string& match = {});
117
118/** @brief Gets the value associated with the given object
119 * and the interface.
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530120 * @param[in] bus - DBUS Bus Object.
Ratan Guptacc8feb42017-07-25 21:52:10 +0530121 * @param[in] service - Dbus service name.
122 * @param[in] objPath - Dbus object path.
123 * @param[in] interface - Dbus interface.
124 * @param[in] property - name of the property.
125 * @return On success returns the value of the property.
126 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700127Value getDbusProperty(sdbusplus::bus::bus& bus, const std::string& service,
128 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800129 const std::string& property,
130 std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530131
132/** @brief Gets all the properties associated with the given object
133 * and the interface.
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530134 * @param[in] bus - DBUS Bus Object.
Ratan Guptacc8feb42017-07-25 21:52:10 +0530135 * @param[in] service - Dbus service name.
136 * @param[in] objPath - Dbus object path.
137 * @param[in] interface - Dbus interface.
138 * @return On success returns the map of name value pair.
139 */
Kun Yi5dcf41e2019-03-05 14:02:51 -0800140PropertyMap
141 getAllDbusProperties(sdbusplus::bus::bus& bus, const std::string& service,
142 const std::string& objPath,
143 const std::string& interface,
144 std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530145
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600146/** @brief Gets all managed objects associated with the given object
147 * path and service.
148 * @param[in] bus - D-Bus Bus Object.
149 * @param[in] service - D-Bus service name.
150 * @param[in] objPath - D-Bus object path.
151 * @return On success returns the map of name value pair.
152 */
153ObjectValueTree getManagedObjects(sdbusplus::bus::bus& bus,
Patrick Venture0b02be92018-08-31 11:55:55 -0700154 const std::string& service,
155 const std::string& objPath);
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600156
Ratan Guptacc8feb42017-07-25 21:52:10 +0530157/** @brief Sets the property value of the given object.
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530158 * @param[in] bus - DBUS Bus Object.
Ratan Guptacc8feb42017-07-25 21:52:10 +0530159 * @param[in] service - Dbus service name.
160 * @param[in] objPath - Dbus object path.
161 * @param[in] interface - Dbus interface.
162 * @param[in] property - name of the property.
163 * @param[in] value - value which needs to be set.
164 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700165void setDbusProperty(sdbusplus::bus::bus& bus, const std::string& service,
166 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800167 const std::string& property, const Value& value,
168 std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530169
Ratan Guptab8e99552017-07-27 07:07:48 +0530170/** @brief Gets all the dbus objects from the given service root
171 * which matches the object identifier.
172 * @param[in] bus - DBUS Bus Object.
173 * @param[in] serviceRoot - Service root path.
174 * @param[in] interface - Dbus interface.
175 * @param[in] match - Identifier for a path.
176 * @returns map of object path and service info.
177 */
178ObjectTree getAllDbusObjects(sdbusplus::bus::bus& bus,
179 const std::string& serviceRoot,
180 const std::string& interface,
Vernon Mauery6f2c8cd2018-07-28 06:40:39 -0700181 const std::string& match = {});
Ratan Guptab8e99552017-07-27 07:07:48 +0530182
183/** @brief Deletes all the dbus objects from the given service root
184 which matches the object identifier.
185 * @param[in] bus - DBUS Bus Object.
186 * @param[in] serviceRoot - Service root path.
187 * @param[in] interface - Dbus interface.
188 * @param[in] match - Identifier for object.
189 */
190void deleteAllDbusObjects(sdbusplus::bus::bus& bus,
191 const std::string& serviceRoot,
192 const std::string& interface,
193 const std::string& match = {});
194
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530195/** @brief Gets the ancestor objects of the given object
196 which implements the given interface.
197 * @param[in] bus - Dbus bus object.
198 * @param[in] path - Child Dbus object path.
199 * @param[in] interfaces - Dbus interface list.
200 * @return map of object path and service info.
201 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700202ObjectTree getAllAncestors(sdbusplus::bus::bus& bus, const std::string& path,
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530203 InterfaceList&& interfaces);
204
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700205/********* Begin co-routine yielding alternatives ***************/
206
207/** @brief Get the D-Bus Service name for the input D-Bus path
208 *
209 * @param[in] ctx - ipmi::Context::ptr
210 * @param[in] intf - D-Bus Interface
211 * @param[in] path - D-Bus Object Path
212 * @param[out] service - requested service name
213 * @return boost error code
214 *
215 */
216boost::system::error_code getService(Context::ptr ctx, const std::string& intf,
217 const std::string& path,
218 std::string& service);
219
220/** @brief Gets the D-Bus object info implementing the given interface
221 * from the given subtree.
222 * @param[in] ctx - ipmi::Context::ptr
223 * @param[in] interface - D-Bus interface.
224 * @param[in][optional] subtreePath - subtree from where the search starts.
225 * @param[in][optional] match - identifier for object.
226 * @param[out] D-Bus object with path and service name
227 * @return - boost error code object
228 */
229boost::system::error_code getDbusObject(Context::ptr ctx,
230 const std::string& interface,
231 const std::string& subtreePath,
232 const std::string& match,
233 DbusObjectInfo& dbusObject);
234
235// default for ROOT for subtreePath and std::string{} for match
236static inline boost::system::error_code
237 getDbusObject(Context::ptr ctx, const std::string& interface,
238 DbusObjectInfo& dbusObject)
239{
240 return getDbusObject(ctx, interface, ROOT, {}, dbusObject);
241}
242
243// default std::string{} for match
244static inline boost::system::error_code
245 getDbusObject(Context::ptr ctx, const std::string& interface,
246 const std::string& subtreePath, DbusObjectInfo& dbusObject)
247{
248 return getDbusObject(ctx, interface, subtreePath, {}, dbusObject);
249}
250
251/** @brief Gets the value associated with the given object
252 * and the interface.
253 * @param[in] ctx - ipmi::Context::ptr
254 * @param[in] service - D-Bus service name.
255 * @param[in] objPath - D-Bus object path.
256 * @param[in] interface - D-Bus interface.
257 * @param[in] property - name of the property.
258 * @param[out] propertyValue - value of the D-Bus property.
259 * @return - boost error code object
260 */
261template <typename Type>
262boost::system::error_code
263 getDbusProperty(Context::ptr ctx, const std::string& service,
264 const std::string& objPath, const std::string& interface,
265 const std::string& property, Type& propertyValue)
266{
267 boost::system::error_code ec;
268 auto variant = ctx->bus->yield_method_call<std::variant<Type>>(
269 ctx->yield, ec, service.c_str(), objPath.c_str(), PROP_INTF, METHOD_GET,
270 interface, property);
271 if (!ec)
272 {
273 Type* tmp = std::get_if<Type>(&variant);
274 if (tmp)
275 {
276 propertyValue = *tmp;
277 return ec;
278 }
279 // user requested incorrect type; make an error code for them
280 ec = boost::system::errc::make_error_code(
281 boost::system::errc::invalid_argument);
282 }
283 return ec;
284}
285
286/** @brief Gets all the properties associated with the given object
287 * and the interface.
288 * @param[in] ctx - ipmi::Context::ptr
289 * @param[in] service - D-Bus service name.
290 * @param[in] objPath - D-Bus object path.
291 * @param[in] interface - D-Bus interface.
292 * @param[out] properties - map of name value pair.
293 * @return - boost error code object
294 */
295boost::system::error_code getAllDbusProperties(Context::ptr ctx,
296 const std::string& service,
297 const std::string& objPath,
298 const std::string& interface,
299 PropertyMap& properties);
300
301/** @brief Sets the property value of the given object.
302 * @param[in] ctx - ipmi::Context::ptr
303 * @param[in] service - D-Bus service name.
304 * @param[in] objPath - D-Bus object path.
305 * @param[in] interface - D-Bus interface.
306 * @param[in] property - name of the property.
307 * @param[in] value - value which needs to be set.
308 * @return - boost error code object
309 */
310boost::system::error_code
311 setDbusProperty(Context::ptr ctx, const std::string& service,
312 const std::string& objPath, const std::string& interface,
313 const std::string& property, const Value& value);
314
315/** @brief Gets all the D-Bus objects from the given service root
316 * which matches the object identifier.
317 * @param[in] ctx - ipmi::Context::ptr
318 * @param[in] serviceRoot - Service root path.
319 * @param[in] interface - D-Bus interface.
320 * @param[in][optional] match - Identifier for a path.
321 * @param[out] objectree - map of object path and service info.
322 * @return - boost error code object
323 */
324boost::system::error_code getAllDbusObjects(Context::ptr ctx,
325 const std::string& serviceRoot,
326 const std::string& interface,
327 const std::string& match,
328 ObjectTree& objectTree);
329
330// default std::string{} for match
331static inline boost::system::error_code
332 getAllDbusObjects(Context::ptr ctx, const std::string& serviceRoot,
333 const std::string& interface, ObjectTree& objectTree)
334{
335 return getAllDbusObjects(ctx, serviceRoot, interface, {}, objectTree);
336}
337
338/** @brief Deletes all the D-Bus objects from the given service root
339 which matches the object identifier.
340 * @param[in] ctx - ipmi::Context::ptr
341 * @param[out] ec - boost error code object
342 * @param[in] serviceRoot - Service root path.
343 * @param[in] interface - D-Bus interface.
344 * @param[in] match - Identifier for object.
345 */
346boost::system::error_code deleteAllDbusObjects(Context::ptr ctx,
347 const std::string& serviceRoot,
348 const std::string& interface,
349 const std::string& match = {});
350
351/** @brief Gets all managed objects associated with the given object
352 * path and service.
353 * @param[in] ctx - ipmi::Context::ptr
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700354 * @param[in] service - D-Bus service name.
355 * @param[in] objPath - D-Bus object path.
Vernon Maueryfe39ec92020-03-02 13:58:41 -0800356 * @param[out] objects - map of name value pair.
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700357 * @return - boost error code object
358 */
359boost::system::error_code getManagedObjects(Context::ptr ctx,
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700360 const std::string& service,
Vernon Maueryfe39ec92020-03-02 13:58:41 -0800361 const std::string& objPath,
362 ObjectValueTree& objects);
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700363
364/** @brief Gets the ancestor objects of the given object
365 which implements the given interface.
366 * @param[in] ctx - ipmi::Context::ptr
367 * @param[in] path - Child D-Bus object path.
368 * @param[in] interfaces - D-Bus interface list.
369 * @param[out] ObjectTree - map of object path and service info.
370 * @return - boost error code object
371 */
372boost::system::error_code getAllAncestors(Context::ptr ctx,
373 const std::string& path,
374 const InterfaceList& interfaces,
375 ObjectTree& objectTree);
376
377/********* End co-routine yielding alternatives ***************/
378
Vernon Mauerye7e8b812019-10-28 16:00:34 -0700379/** @brief Retrieve the value from map of variants,
380 * returning a default if the key does not exist or the
381 * type of the value does not match the expected type
382 *
383 * @tparam T - type of expected value to return
384 * @param[in] props - D-Bus propery map (Map of variants)
385 * @param[in] name - key name of property to fetch
386 * @param[in] defaultValue - default value to return on error
387 * @return - value from propery map at name, or defaultValue
388 */
389template <typename T>
390T mappedVariant(const ipmi::PropertyMap& props, const std::string& name,
391 const T& defaultValue)
392{
393 auto item = props.find(name);
394 if (item == props.end())
395 {
396 return defaultValue;
397 }
398 const T* prop = std::get_if<T>(&item->second);
399 if (!prop)
400 {
401 return defaultValue;
402 }
403 return *prop;
404}
405
James Feist1e121122018-07-31 11:44:09 -0700406/** @struct VariantToDoubleVisitor
407 * @brief Visitor to convert variants to doubles
408 * @details Performs a static cast on the underlying type
409 */
410struct VariantToDoubleVisitor
411{
412 template <typename T>
413 std::enable_if_t<std::is_arithmetic<T>::value, double>
Patrick Venture0b02be92018-08-31 11:55:55 -0700414 operator()(const T& t) const
James Feist1e121122018-07-31 11:44:09 -0700415 {
416 return static_cast<double>(t);
417 }
418
419 template <typename T>
420 std::enable_if_t<!std::is_arithmetic<T>::value, double>
Patrick Venture0b02be92018-08-31 11:55:55 -0700421 operator()(const T& t) const
James Feist1e121122018-07-31 11:44:09 -0700422 {
423 throw std::invalid_argument("Cannot translate type to double");
424 }
425};
426
Ratan Guptab8e99552017-07-27 07:07:48 +0530427namespace method_no_args
428{
429
430/** @brief Calls the Dbus method which waits for response.
431 * @param[in] bus - DBUS Bus Object.
432 * @param[in] service - Dbus service name.
433 * @param[in] objPath - Dbus object path.
434 * @param[in] interface - Dbus interface.
435 * @param[in] method - Dbus method.
436 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700437void callDbusMethod(sdbusplus::bus::bus& bus, const std::string& service,
438 const std::string& objPath, const std::string& interface,
Ratan Guptab8e99552017-07-27 07:07:48 +0530439 const std::string& method);
440
Patrick Venture0b02be92018-08-31 11:55:55 -0700441} // namespace method_no_args
Ratan Guptab8e99552017-07-27 07:07:48 +0530442
Yong Li7dc4ac02019-08-23 17:44:32 +0800443/** @brief Perform the low-level i2c bus write-read.
444 * @param[in] i2cBus - i2c bus device node name, such as /dev/i2c-2.
445 * @param[in] slaveAddr - i2c device slave address.
446 * @param[in] writeData - The data written to i2c device.
447 * @param[out] readBuf - Data read from the i2c device.
448 */
449ipmi::Cc i2cWriteRead(std::string i2cBus, const uint8_t slaveAddr,
450 std::vector<uint8_t> writeData,
451 std::vector<uint8_t>& readBuf);
Tom Josephbe703f72017-03-09 12:34:35 +0530452} // namespace ipmi