blob: ebd97e09d8391857ae9c3885dcef0363574e9206 [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 */
Patrick Williams5d82f472022-07-22 19:26:53 -050060 const std::string& getService(sdbusplus::bus_t& 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 */
Patrick Williams5d82f472022-07-22 19:26:53 -050072 sdbusplus::message_t newMethodCall(sdbusplus::bus_t& bus, const char* intf,
73 const char* method);
William A. Kennington III82c173a2018-05-11 16:10:12 -070074
Patrick Venture0b02be92018-08-31 11:55:55 -070075 /** @brief Check to see if the current cache is valid
76 *
77 * @param[in] bus - The bus used for the service lookup
78 * @return True if the cache is valid false otherwise.
79 */
Patrick Williams5d82f472022-07-22 19:26:53 -050080 bool isValid(sdbusplus::bus_t& bus) const;
Patrick Venture0b02be92018-08-31 11:55:55 -070081
82 private:
83 /** @brief DBUS interface provided by the service */
84 const std::string intf;
85 /** @brief DBUS path provided by the service */
86 const std::string path;
87 /** @brief The name of the service if valid */
Vernon Mauery54012502018-11-07 10:17:31 -080088 std::optional<std::string> cachedService;
Patrick Venture0b02be92018-08-31 11:55:55 -070089 /** @brief The name of the bus used in the service lookup */
Vernon Mauery54012502018-11-07 10:17:31 -080090 std::optional<std::string> cachedBusName;
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -070091};
92
Tom Josephbe703f72017-03-09 12:34:35 +053093/**
94 * @brief Get the DBUS Service name for the input dbus path
95 *
96 * @param[in] bus - DBUS Bus Object
97 * @param[in] intf - DBUS Interface
98 * @param[in] path - DBUS Object Path
99 *
100 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500101std::string getService(sdbusplus::bus_t& bus, const std::string& intf,
Tom Josephbe703f72017-03-09 12:34:35 +0530102 const std::string& path);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530103
104/** @brief Gets the dbus object info implementing the given interface
105 * from the given subtree.
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530106 * @param[in] bus - DBUS Bus Object.
Ratan Guptacc8feb42017-07-25 21:52:10 +0530107 * @param[in] interface - Dbus interface.
108 * @param[in] subtreePath - subtree from where the search should start.
109 * @param[in] match - identifier for object.
110 * @return On success returns the object having objectpath and servicename.
111 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500112DbusObjectInfo getDbusObject(sdbusplus::bus_t& bus,
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530113 const std::string& interface,
Ratan Guptacc8feb42017-07-25 21:52:10 +0530114 const std::string& subtreePath = ROOT,
115 const std::string& match = {});
116
117/** @brief Gets the value associated with the given object
118 * and the interface.
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530119 * @param[in] bus - DBUS Bus Object.
Ratan Guptacc8feb42017-07-25 21:52:10 +0530120 * @param[in] service - Dbus service name.
121 * @param[in] objPath - Dbus object path.
122 * @param[in] interface - Dbus interface.
123 * @param[in] property - name of the property.
124 * @return On success returns the value of the property.
125 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500126Value getDbusProperty(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -0700127 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800128 const std::string& property,
129 std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530130
131/** @brief Gets all the properties associated with the given object
132 * and the interface.
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530133 * @param[in] bus - DBUS Bus Object.
Ratan Guptacc8feb42017-07-25 21:52:10 +0530134 * @param[in] service - Dbus service name.
135 * @param[in] objPath - Dbus object path.
136 * @param[in] interface - Dbus interface.
137 * @return On success returns the map of name value pair.
138 */
Kun Yi5dcf41e2019-03-05 14:02:51 -0800139PropertyMap
Patrick Williams5d82f472022-07-22 19:26:53 -0500140 getAllDbusProperties(sdbusplus::bus_t& bus, const std::string& service,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800141 const std::string& objPath,
142 const std::string& interface,
143 std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530144
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600145/** @brief Gets all managed objects associated with the given object
146 * path and service.
147 * @param[in] bus - D-Bus Bus Object.
148 * @param[in] service - D-Bus service name.
149 * @param[in] objPath - D-Bus object path.
150 * @return On success returns the map of name value pair.
151 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500152ObjectValueTree getManagedObjects(sdbusplus::bus_t& bus,
Patrick Venture0b02be92018-08-31 11:55:55 -0700153 const std::string& service,
154 const std::string& objPath);
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600155
Ratan Guptacc8feb42017-07-25 21:52:10 +0530156/** @brief Sets the property value of the given object.
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530157 * @param[in] bus - DBUS Bus Object.
Ratan Guptacc8feb42017-07-25 21:52:10 +0530158 * @param[in] service - Dbus service name.
159 * @param[in] objPath - Dbus object path.
160 * @param[in] interface - Dbus interface.
161 * @param[in] property - name of the property.
162 * @param[in] value - value which needs to be set.
163 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500164void setDbusProperty(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -0700165 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800166 const std::string& property, const Value& value,
167 std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530168
Ratan Guptab8e99552017-07-27 07:07:48 +0530169/** @brief Gets all the dbus objects from the given service root
170 * which matches the object identifier.
171 * @param[in] bus - DBUS Bus Object.
172 * @param[in] serviceRoot - Service root path.
173 * @param[in] interface - Dbus interface.
174 * @param[in] match - Identifier for a path.
175 * @returns map of object path and service info.
176 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500177ObjectTree getAllDbusObjects(sdbusplus::bus_t& bus,
Ratan Guptab8e99552017-07-27 07:07:48 +0530178 const std::string& serviceRoot,
179 const std::string& interface,
Vernon Mauery6f2c8cd2018-07-28 06:40:39 -0700180 const std::string& match = {});
Ratan Guptab8e99552017-07-27 07:07:48 +0530181
182/** @brief Deletes all the dbus objects from the given service root
183 which matches the object identifier.
184 * @param[in] bus - DBUS Bus Object.
185 * @param[in] serviceRoot - Service root path.
186 * @param[in] interface - Dbus interface.
187 * @param[in] match - Identifier for object.
188 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500189void deleteAllDbusObjects(sdbusplus::bus_t& bus, const std::string& serviceRoot,
Ratan Guptab8e99552017-07-27 07:07:48 +0530190 const std::string& interface,
191 const std::string& match = {});
192
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530193/** @brief Gets the ancestor objects of the given object
194 which implements the given interface.
195 * @param[in] bus - Dbus bus object.
196 * @param[in] path - Child Dbus object path.
197 * @param[in] interfaces - Dbus interface list.
198 * @return map of object path and service info.
199 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500200ObjectTree getAllAncestors(sdbusplus::bus_t& bus, const std::string& path,
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530201 InterfaceList&& interfaces);
202
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700203/********* Begin co-routine yielding alternatives ***************/
204
205/** @brief Get the D-Bus Service name for the input D-Bus path
206 *
207 * @param[in] ctx - ipmi::Context::ptr
208 * @param[in] intf - D-Bus Interface
209 * @param[in] path - D-Bus Object Path
210 * @param[out] service - requested service name
211 * @return boost error code
212 *
213 */
214boost::system::error_code getService(Context::ptr ctx, const std::string& intf,
215 const std::string& path,
216 std::string& service);
217
218/** @brief Gets the D-Bus object info implementing the given interface
219 * from the given subtree.
220 * @param[in] ctx - ipmi::Context::ptr
221 * @param[in] interface - D-Bus interface.
222 * @param[in][optional] subtreePath - subtree from where the search starts.
223 * @param[in][optional] match - identifier for object.
224 * @param[out] D-Bus object with path and service name
225 * @return - boost error code object
226 */
227boost::system::error_code getDbusObject(Context::ptr ctx,
228 const std::string& interface,
229 const std::string& subtreePath,
230 const std::string& match,
231 DbusObjectInfo& dbusObject);
232
233// default for ROOT for subtreePath and std::string{} for match
234static inline boost::system::error_code
235 getDbusObject(Context::ptr ctx, const std::string& interface,
236 DbusObjectInfo& dbusObject)
237{
238 return getDbusObject(ctx, interface, ROOT, {}, dbusObject);
239}
240
241// default std::string{} for match
242static inline boost::system::error_code
243 getDbusObject(Context::ptr ctx, const std::string& interface,
244 const std::string& subtreePath, DbusObjectInfo& dbusObject)
245{
246 return getDbusObject(ctx, interface, subtreePath, {}, dbusObject);
247}
248
249/** @brief Gets the value associated with the given object
250 * and the interface.
251 * @param[in] ctx - ipmi::Context::ptr
252 * @param[in] service - D-Bus service name.
253 * @param[in] objPath - D-Bus object path.
254 * @param[in] interface - D-Bus interface.
255 * @param[in] property - name of the property.
256 * @param[out] propertyValue - value of the D-Bus property.
257 * @return - boost error code object
258 */
259template <typename Type>
260boost::system::error_code
261 getDbusProperty(Context::ptr ctx, const std::string& service,
262 const std::string& objPath, const std::string& interface,
263 const std::string& property, Type& propertyValue)
264{
265 boost::system::error_code ec;
266 auto variant = ctx->bus->yield_method_call<std::variant<Type>>(
267 ctx->yield, ec, service.c_str(), objPath.c_str(), PROP_INTF, METHOD_GET,
268 interface, property);
269 if (!ec)
270 {
271 Type* tmp = std::get_if<Type>(&variant);
272 if (tmp)
273 {
274 propertyValue = *tmp;
275 return ec;
276 }
277 // user requested incorrect type; make an error code for them
278 ec = boost::system::errc::make_error_code(
279 boost::system::errc::invalid_argument);
280 }
281 return ec;
282}
283
284/** @brief Gets all the properties associated with the given object
285 * and the interface.
286 * @param[in] ctx - ipmi::Context::ptr
287 * @param[in] service - D-Bus service name.
288 * @param[in] objPath - D-Bus object path.
289 * @param[in] interface - D-Bus interface.
290 * @param[out] properties - map of name value pair.
291 * @return - boost error code object
292 */
293boost::system::error_code getAllDbusProperties(Context::ptr ctx,
294 const std::string& service,
295 const std::string& objPath,
296 const std::string& interface,
297 PropertyMap& properties);
298
299/** @brief Sets the property value of the given object.
300 * @param[in] ctx - ipmi::Context::ptr
301 * @param[in] service - D-Bus service name.
302 * @param[in] objPath - D-Bus object path.
303 * @param[in] interface - D-Bus interface.
304 * @param[in] property - name of the property.
305 * @param[in] value - value which needs to be set.
306 * @return - boost error code object
307 */
308boost::system::error_code
309 setDbusProperty(Context::ptr ctx, const std::string& service,
310 const std::string& objPath, const std::string& interface,
311 const std::string& property, const Value& value);
312
313/** @brief Gets all the D-Bus objects from the given service root
314 * which matches the object identifier.
315 * @param[in] ctx - ipmi::Context::ptr
316 * @param[in] serviceRoot - Service root path.
317 * @param[in] interface - D-Bus interface.
318 * @param[in][optional] match - Identifier for a path.
319 * @param[out] objectree - map of object path and service info.
320 * @return - boost error code object
321 */
322boost::system::error_code getAllDbusObjects(Context::ptr ctx,
323 const std::string& serviceRoot,
324 const std::string& interface,
325 const std::string& match,
326 ObjectTree& objectTree);
327
328// default std::string{} for match
329static inline boost::system::error_code
330 getAllDbusObjects(Context::ptr ctx, const std::string& serviceRoot,
331 const std::string& interface, ObjectTree& objectTree)
332{
333 return getAllDbusObjects(ctx, serviceRoot, interface, {}, objectTree);
334}
335
336/** @brief Deletes all the D-Bus objects from the given service root
337 which matches the object identifier.
338 * @param[in] ctx - ipmi::Context::ptr
339 * @param[out] ec - boost error code object
340 * @param[in] serviceRoot - Service root path.
341 * @param[in] interface - D-Bus interface.
342 * @param[in] match - Identifier for object.
343 */
344boost::system::error_code deleteAllDbusObjects(Context::ptr ctx,
345 const std::string& serviceRoot,
346 const std::string& interface,
347 const std::string& match = {});
348
349/** @brief Gets all managed objects associated with the given object
350 * path and service.
351 * @param[in] ctx - ipmi::Context::ptr
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700352 * @param[in] service - D-Bus service name.
353 * @param[in] objPath - D-Bus object path.
Vernon Maueryfe39ec92020-03-02 13:58:41 -0800354 * @param[out] objects - map of name value pair.
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700355 * @return - boost error code object
356 */
357boost::system::error_code getManagedObjects(Context::ptr ctx,
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700358 const std::string& service,
Vernon Maueryfe39ec92020-03-02 13:58:41 -0800359 const std::string& objPath,
360 ObjectValueTree& objects);
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700361
362/** @brief Gets the ancestor objects of the given object
363 which implements the given interface.
364 * @param[in] ctx - ipmi::Context::ptr
365 * @param[in] path - Child D-Bus object path.
366 * @param[in] interfaces - D-Bus interface list.
367 * @param[out] ObjectTree - map of object path and service info.
368 * @return - boost error code object
369 */
370boost::system::error_code getAllAncestors(Context::ptr ctx,
371 const std::string& path,
372 const InterfaceList& interfaces,
373 ObjectTree& objectTree);
374
Albert Zhangb53049e2022-04-02 15:39:51 +0800375/** @brief Gets the value associated with the given object
376 * and the interface.
377 * @param[in] ctx - ipmi::Context::ptr
378 * @param[in] service - D-Bus service name.
379 * @param[in] objPath - D-Bus object path.
380 * @param[in] interface - D-Bus interface.
381 * @param[in] method - name of the method.
382 * @return - boost error code object
383 */
384
385boost::system::error_code callDbusMethod(Context::ptr ctx,
386 const std::string& service,
387 const std::string& objPath,
388 const std::string& interface,
389 const std::string& method);
390
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700391/********* End co-routine yielding alternatives ***************/
392
Vernon Mauerye7e8b812019-10-28 16:00:34 -0700393/** @brief Retrieve the value from map of variants,
394 * returning a default if the key does not exist or the
395 * type of the value does not match the expected type
396 *
397 * @tparam T - type of expected value to return
398 * @param[in] props - D-Bus propery map (Map of variants)
399 * @param[in] name - key name of property to fetch
400 * @param[in] defaultValue - default value to return on error
401 * @return - value from propery map at name, or defaultValue
402 */
403template <typename T>
404T mappedVariant(const ipmi::PropertyMap& props, const std::string& name,
405 const T& defaultValue)
406{
407 auto item = props.find(name);
408 if (item == props.end())
409 {
410 return defaultValue;
411 }
412 const T* prop = std::get_if<T>(&item->second);
413 if (!prop)
414 {
415 return defaultValue;
416 }
417 return *prop;
418}
419
James Feist1e121122018-07-31 11:44:09 -0700420/** @struct VariantToDoubleVisitor
421 * @brief Visitor to convert variants to doubles
422 * @details Performs a static cast on the underlying type
423 */
424struct VariantToDoubleVisitor
425{
426 template <typename T>
427 std::enable_if_t<std::is_arithmetic<T>::value, double>
Patrick Venture0b02be92018-08-31 11:55:55 -0700428 operator()(const T& t) const
James Feist1e121122018-07-31 11:44:09 -0700429 {
430 return static_cast<double>(t);
431 }
432
433 template <typename T>
434 std::enable_if_t<!std::is_arithmetic<T>::value, double>
Willy Tu11d68892022-01-20 10:37:34 -0800435 operator()(const T&) const
James Feist1e121122018-07-31 11:44:09 -0700436 {
437 throw std::invalid_argument("Cannot translate type to double");
438 }
439};
440
Ratan Guptab8e99552017-07-27 07:07:48 +0530441namespace method_no_args
442{
443
444/** @brief Calls the Dbus method which waits for response.
445 * @param[in] bus - DBUS Bus Object.
446 * @param[in] service - Dbus service name.
447 * @param[in] objPath - Dbus object path.
448 * @param[in] interface - Dbus interface.
449 * @param[in] method - Dbus method.
450 */
Patrick Williams5d82f472022-07-22 19:26:53 -0500451void callDbusMethod(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -0700452 const std::string& objPath, const std::string& interface,
Ratan Guptab8e99552017-07-27 07:07:48 +0530453 const std::string& method);
454
Patrick Venture0b02be92018-08-31 11:55:55 -0700455} // namespace method_no_args
Ratan Guptab8e99552017-07-27 07:07:48 +0530456
Yong Li7dc4ac02019-08-23 17:44:32 +0800457/** @brief Perform the low-level i2c bus write-read.
458 * @param[in] i2cBus - i2c bus device node name, such as /dev/i2c-2.
459 * @param[in] slaveAddr - i2c device slave address.
460 * @param[in] writeData - The data written to i2c device.
461 * @param[out] readBuf - Data read from the i2c device.
462 */
463ipmi::Cc i2cWriteRead(std::string i2cBus, const uint8_t slaveAddr,
464 std::vector<uint8_t> writeData,
465 std::vector<uint8_t>& readBuf);
Tom Josephbe703f72017-03-09 12:34:35 +0530466} // namespace ipmi