1 #pragma once
2 
3 #include <chrono>
4 #include <ipmid/api-types.hpp>
5 #include <ipmid/types.hpp>
6 #include <optional>
7 #include <sdbusplus/server.hpp>
8 
9 namespace ipmi
10 {
11 
12 using namespace std::literals::chrono_literals;
13 
14 constexpr auto MAPPER_BUS_NAME = "xyz.openbmc_project.ObjectMapper";
15 constexpr auto MAPPER_OBJ = "/xyz/openbmc_project/object_mapper";
16 constexpr auto MAPPER_INTF = "xyz.openbmc_project.ObjectMapper";
17 
18 constexpr auto ROOT = "/";
19 constexpr auto HOST_MATCH = "host0";
20 
21 constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties";
22 constexpr auto DELETE_INTERFACE = "xyz.openbmc_project.Object.Delete";
23 
24 constexpr auto METHOD_GET = "Get";
25 constexpr auto METHOD_GET_ALL = "GetAll";
26 constexpr auto METHOD_SET = "Set";
27 
28 /* Use a value of 5s which aligns with BT/KCS bridged timeouts, rather
29  * than the default 25s D-Bus timeout. */
30 constexpr std::chrono::microseconds IPMI_DBUS_TIMEOUT = 5s;
31 
32 /** @class ServiceCache
33  *  @brief Caches lookups of service names from the object mapper.
34  *  @details Most ipmi commands need to talk to other dbus daemons to perform
35  *           their intended actions on the BMC. This usually means they will
36  *           first look up the service name providing the interface they
37  *           require. This class reduces the number of such calls by caching
38  *           the lookup for a specific service.
39  */
40 class ServiceCache
41 {
42   public:
43     /** @brief Creates a new service cache for the given interface
44      *         and path.
45      *
46      *  @param[in] intf - The interface used for each lookup
47      *  @param[in] path - The path used for each lookup
48      */
49     ServiceCache(const std::string& intf, const std::string& path);
50     ServiceCache(std::string&& intf, std::string&& path);
51 
52     /** @brief Gets the service name from the cache or does in a
53      *         lookup when invalid.
54      *
55      *  @param[in] bus - The bus associated with and used for looking
56      *                   up the service.
57      */
58     const std::string& getService(sdbusplus::bus::bus& bus);
59 
60     /** @brief Invalidates the current service name */
61     void invalidate();
62 
63     /** @brief A wrapper around sdbusplus bus.new_method_call
64      *
65      *  @param[in] bus - The bus used for calling the method
66      *  @param[in] intf - The interface containing the method
67      *  @param[in] method - The method name
68      *  @return The message containing the method call.
69      */
70     sdbusplus::message::message newMethodCall(sdbusplus::bus::bus& bus,
71                                               const char* intf,
72                                               const char* method);
73 
74     /** @brief Check to see if the current cache is valid
75      *
76      * @param[in] bus - The bus used for the service lookup
77      * @return True if the cache is valid false otherwise.
78      */
79     bool isValid(sdbusplus::bus::bus& bus) const;
80 
81   private:
82     /** @brief DBUS interface provided by the service */
83     const std::string intf;
84     /** @brief DBUS path provided by the service */
85     const std::string path;
86     /** @brief The name of the service if valid */
87     std::optional<std::string> cachedService;
88     /** @brief The name of the bus used in the service lookup */
89     std::optional<std::string> cachedBusName;
90 };
91 
92 /**
93  * @brief Get the DBUS Service name for the input dbus path
94  *
95  * @param[in] bus - DBUS Bus Object
96  * @param[in] intf - DBUS Interface
97  * @param[in] path - DBUS Object Path
98  *
99  */
100 std::string getService(sdbusplus::bus::bus& bus, const std::string& intf,
101                        const std::string& path);
102 
103 /** @brief Gets the dbus object info implementing the given interface
104  *         from the given subtree.
105  *  @param[in] bus - DBUS Bus Object.
106  *  @param[in] interface - Dbus interface.
107  *  @param[in] subtreePath - subtree from where the search should start.
108  *  @param[in] match - identifier for object.
109  *  @return On success returns the object having objectpath and servicename.
110  */
111 DbusObjectInfo getDbusObject(sdbusplus::bus::bus& bus,
112                              const std::string& interface,
113                              const std::string& subtreePath = ROOT,
114                              const std::string& match = {});
115 
116 /** @brief Gets the value associated with the given object
117  *         and the interface.
118  *  @param[in] bus - DBUS Bus Object.
119  *  @param[in] service - Dbus service name.
120  *  @param[in] objPath - Dbus object path.
121  *  @param[in] interface - Dbus interface.
122  *  @param[in] property - name of the property.
123  *  @return On success returns the value of the property.
124  */
125 Value getDbusProperty(sdbusplus::bus::bus& bus, const std::string& service,
126                       const std::string& objPath, const std::string& interface,
127                       const std::string& property,
128                       std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT);
129 
130 /** @brief Gets all the properties associated with the given object
131  *         and the interface.
132  *  @param[in] bus - DBUS Bus Object.
133  *  @param[in] service - Dbus service name.
134  *  @param[in] objPath - Dbus object path.
135  *  @param[in] interface - Dbus interface.
136  *  @return On success returns the map of name value pair.
137  */
138 PropertyMap
139     getAllDbusProperties(sdbusplus::bus::bus& bus, const std::string& service,
140                          const std::string& objPath,
141                          const std::string& interface,
142                          std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT);
143 
144 /** @brief Gets all managed objects associated with the given object
145  *         path and service.
146  *  @param[in] bus - D-Bus Bus Object.
147  *  @param[in] service - D-Bus service name.
148  *  @param[in] objPath - D-Bus object path.
149  *  @return On success returns the map of name value pair.
150  */
151 ObjectValueTree getManagedObjects(sdbusplus::bus::bus& bus,
152                                   const std::string& service,
153                                   const std::string& objPath);
154 
155 /** @brief Sets the property value of the given object.
156  *  @param[in] bus - DBUS Bus Object.
157  *  @param[in] service - Dbus service name.
158  *  @param[in] objPath - Dbus object path.
159  *  @param[in] interface - Dbus interface.
160  *  @param[in] property - name of the property.
161  *  @param[in] value - value which needs to be set.
162  */
163 void setDbusProperty(sdbusplus::bus::bus& bus, const std::string& service,
164                      const std::string& objPath, const std::string& interface,
165                      const std::string& property, const Value& value,
166                      std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT);
167 
168 /** @brief  Gets all the dbus objects from the given service root
169  *          which matches the object identifier.
170  *  @param[in] bus - DBUS Bus Object.
171  *  @param[in] serviceRoot - Service root path.
172  *  @param[in] interface - Dbus interface.
173  *  @param[in] match - Identifier for a path.
174  *  @returns map of object path and service info.
175  */
176 ObjectTree getAllDbusObjects(sdbusplus::bus::bus& bus,
177                              const std::string& serviceRoot,
178                              const std::string& interface,
179                              const std::string& match = {});
180 
181 /** @brief Deletes all the dbus objects from the given service root
182            which matches the object identifier.
183  *  @param[in] bus - DBUS Bus Object.
184  *  @param[in] serviceRoot - Service root path.
185  *  @param[in] interface - Dbus interface.
186  *  @param[in] match - Identifier for object.
187  */
188 void deleteAllDbusObjects(sdbusplus::bus::bus& bus,
189                           const std::string& serviceRoot,
190                           const std::string& interface,
191                           const std::string& match = {});
192 
193 /** @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  */
200 ObjectTree getAllAncestors(sdbusplus::bus::bus& bus, const std::string& path,
201                            InterfaceList&& interfaces);
202 
203 /** @struct VariantToDoubleVisitor
204  *  @brief Visitor to convert variants to doubles
205  *  @details Performs a static cast on the underlying type
206  */
207 struct VariantToDoubleVisitor
208 {
209     template <typename T>
210     std::enable_if_t<std::is_arithmetic<T>::value, double>
211         operator()(const T& t) const
212     {
213         return static_cast<double>(t);
214     }
215 
216     template <typename T>
217     std::enable_if_t<!std::is_arithmetic<T>::value, double>
218         operator()(const T& t) const
219     {
220         throw std::invalid_argument("Cannot translate type to double");
221     }
222 };
223 
224 namespace method_no_args
225 {
226 
227 /** @brief Calls the Dbus method which waits for response.
228  *  @param[in] bus - DBUS Bus Object.
229  *  @param[in] service - Dbus service name.
230  *  @param[in] objPath - Dbus object path.
231  *  @param[in] interface - Dbus interface.
232  *  @param[in] method - Dbus method.
233  */
234 void callDbusMethod(sdbusplus::bus::bus& bus, const std::string& service,
235                     const std::string& objPath, const std::string& interface,
236                     const std::string& method);
237 
238 } // namespace method_no_args
239 
240 /** @brief Perform the low-level i2c bus write-read.
241  *  @param[in] i2cBus - i2c bus device node name, such as /dev/i2c-2.
242  *  @param[in] slaveAddr - i2c device slave address.
243  *  @param[in] writeData - The data written to i2c device.
244  *  @param[out] readBuf - Data read from the i2c device.
245  */
246 ipmi::Cc i2cWriteRead(std::string i2cBus, const uint8_t slaveAddr,
247                       std::vector<uint8_t> writeData,
248                       std::vector<uint8_t>& readBuf);
249 } // namespace ipmi
250