xref: /openbmc/pldm/common/utils.hpp (revision 70a47baf)
1 #pragma once
2 
3 #include "libpldm/base.h"
4 #include "libpldm/bios.h"
5 #include "libpldm/platform.h"
6 #include "libpldm/utils.h"
7 
8 #include "types.hpp"
9 
10 #include <stdint.h>
11 #include <systemd/sd-bus.h>
12 #include <unistd.h>
13 
14 #include <nlohmann/json.hpp>
15 #include <sdbusplus/server.hpp>
16 #include <xyz/openbmc_project/Logging/Entry/server.hpp>
17 
18 #include <exception>
19 #include <filesystem>
20 #include <iostream>
21 #include <string>
22 #include <variant>
23 #include <vector>
24 
25 namespace pldm
26 {
27 namespace utils
28 {
29 
30 namespace fs = std::filesystem;
31 using Json = nlohmann::json;
32 
33 /** @struct CustomFD
34  *
35  *  RAII wrapper for file descriptor.
36  */
37 struct CustomFD
38 {
39     CustomFD(const CustomFD&) = delete;
40     CustomFD& operator=(const CustomFD&) = delete;
41     CustomFD(CustomFD&&) = delete;
42     CustomFD& operator=(CustomFD&&) = delete;
43 
44     CustomFD(int fd) : fd(fd)
45     {}
46 
47     ~CustomFD()
48     {
49         if (fd >= 0)
50         {
51             close(fd);
52         }
53     }
54 
55     int operator()() const
56     {
57         return fd;
58     }
59 
60   private:
61     int fd = -1;
62 };
63 
64 /** @brief Calculate the pad for PLDM data
65  *
66  *  @param[in] data - Length of the data
67  *  @return - uint8_t - number of pad bytes
68  */
69 uint8_t getNumPadBytes(uint32_t data);
70 
71 /** @brief Convert uint64 to date
72  *
73  *  @param[in] data - time date of uint64
74  *  @param[out] year - year number in dec
75  *  @param[out] month - month number in dec
76  *  @param[out] day - day of the month in dec
77  *  @param[out] hour - number of hours in dec
78  *  @param[out] min - number of minutes in dec
79  *  @param[out] sec - number of seconds in dec
80  *  @return true if decode success, false if decode faild
81  */
82 bool uintToDate(uint64_t data, uint16_t* year, uint8_t* month, uint8_t* day,
83                 uint8_t* hour, uint8_t* min, uint8_t* sec);
84 
85 /** @brief Convert effecter data to structure of set_effecter_state_field
86  *
87  *  @param[in] effecterData - the date of effecter
88  *  @param[in] effecterCount - the number of individual sets of effecter
89  *                              information
90  *  @return[out] parse success and get a valid set_effecter_state_field
91  *               structure, return nullopt means parse failed
92  */
93 std::optional<std::vector<set_effecter_state_field>>
94     parseEffecterData(const std::vector<uint8_t>& effecterData,
95                       uint8_t effecterCount);
96 
97 /**
98  *  @brief creates an error log
99  *  @param[in] errorMsg - the error message
100  */
101 void reportError(const char* errorMsg);
102 
103 /** @brief Convert any Decimal number to BCD
104  *
105  *  @tparam[in] decimal - Decimal number
106  *  @return Corresponding BCD number
107  */
108 template <typename T>
109 T decimalToBcd(T decimal)
110 {
111     T bcd = 0;
112     T rem = 0;
113     auto cnt = 0;
114 
115     while (decimal)
116     {
117         rem = decimal % 10;
118         bcd = bcd + (rem << cnt);
119         decimal = decimal / 10;
120         cnt += 4;
121     }
122 
123     return bcd;
124 }
125 
126 constexpr auto dbusProperties = "org.freedesktop.DBus.Properties";
127 constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper";
128 
129 struct DBusMapping
130 {
131     std::string objectPath;   //!< D-Bus object path
132     std::string interface;    //!< D-Bus interface
133     std::string propertyName; //!< D-Bus property name
134     std::string propertyType; //!< D-Bus property type
135 };
136 
137 using PropertyValue =
138     std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t,
139                  uint64_t, double, std::string>;
140 using DbusProp = std::string;
141 using DbusChangedProps = std::map<DbusProp, PropertyValue>;
142 using DBusInterfaceAdded = std::vector<
143     std::pair<pldm::dbus::Interface,
144               std::vector<std::pair<pldm::dbus::Property,
145                                     std::variant<pldm::dbus::Property>>>>>;
146 
147 /**
148  * @brief The interface for DBusHandler
149  */
150 class DBusHandlerInterface
151 {
152   public:
153     virtual ~DBusHandlerInterface() = default;
154 
155     virtual std::string getService(const char* path,
156                                    const char* interface) const = 0;
157 
158     virtual void setDbusProperty(const DBusMapping& dBusMap,
159                                  const PropertyValue& value) const = 0;
160 
161     virtual PropertyValue
162         getDbusPropertyVariant(const char* objPath, const char* dbusProp,
163                                const char* dbusInterface) const = 0;
164 };
165 
166 /**
167  *  @class DBusHandler
168  *
169  *  Wrapper class to handle the D-Bus calls
170  *
171  *  This class contains the APIs to handle the D-Bus calls
172  *  to cater the request from pldm requester.
173  *  A class is created to mock the apis in the test cases
174  */
175 class DBusHandler : public DBusHandlerInterface
176 {
177   public:
178     /** @brief Get the bus connection. */
179     static auto& getBus()
180     {
181         static auto bus = sdbusplus::bus::new_default();
182         return bus;
183     }
184 
185     /**
186      *  @brief Get the DBUS Service name for the input dbus path
187      *
188      *  @param[in] path - DBUS object path
189      *  @param[in] interface - DBUS Interface
190      *
191      *  @return std::string - the dbus service name
192      *
193      *  @throw sdbusplus::exception::SdBusError when it fails
194      */
195     std::string getService(const char* path,
196                            const char* interface) const override;
197 
198     /** @brief Get property(type: variant) from the requested dbus
199      *
200      *  @param[in] objPath - The Dbus object path
201      *  @param[in] dbusProp - The property name to get
202      *  @param[in] dbusInterface - The Dbus interface
203      *
204      *  @return The value of the property(type: variant)
205      *
206      *  @throw sdbusplus::exception::SdBusError when it fails
207      */
208     PropertyValue
209         getDbusPropertyVariant(const char* objPath, const char* dbusProp,
210                                const char* dbusInterface) const override;
211 
212     /** @brief The template function to get property from the requested dbus
213      *         path
214      *
215      *  @tparam Property - Excepted type of the property on dbus
216      *
217      *  @param[in] objPath - The Dbus object path
218      *  @param[in] dbusProp - The property name to get
219      *  @param[in] dbusInterface - The Dbus interface
220      *
221      *  @return The value of the property
222      *
223      *  @throw sdbusplus::exception::SdBusError when dbus request fails
224      *         std::bad_variant_access when \p Property and property on dbus do
225      *         not match
226      */
227     template <typename Property>
228     auto getDbusProperty(const char* objPath, const char* dbusProp,
229                          const char* dbusInterface)
230     {
231         auto VariantValue =
232             getDbusPropertyVariant(objPath, dbusProp, dbusInterface);
233         return std::get<Property>(VariantValue);
234     }
235 
236     /** @brief Set Dbus property
237      *
238      *  @param[in] dBusMap - Object path, property name, interface and property
239      *                       type for the D-Bus object
240      *  @param[in] value - The value to be set
241      *
242      *  @throw sdbusplus::exception::SdBusError when it fails
243      */
244     void setDbusProperty(const DBusMapping& dBusMap,
245                          const PropertyValue& value) const override;
246 };
247 
248 /** @brief Fetch parent D-Bus object based on pathname
249  *
250  *  @param[in] dbusObj - child D-Bus object
251  *
252  *  @return std::string - the parent D-Bus object path
253  */
254 inline std::string findParent(const std::string& dbusObj)
255 {
256     fs::path p(dbusObj);
257     return p.parent_path().string();
258 }
259 
260 /** @brief Read (static) MCTP EID of host firmware from a file
261  *
262  *  @return uint8_t - MCTP EID
263  */
264 uint8_t readHostEID();
265 
266 /** @brief Convert a value in the JSON to a D-Bus property value
267  *
268  *  @param[in] type - type of the D-Bus property
269  *  @param[in] value - value in the JSON file
270  *
271  *  @return PropertyValue - the D-Bus property value
272  */
273 PropertyValue jsonEntryToDbusVal(std::string_view type,
274                                  const nlohmann::json& value);
275 
276 /** @brief Find State Effecter PDR
277  *  @param[in] tid - PLDM terminus ID.
278  *  @param[in] entityID - entity that can be associated with PLDM State set.
279  *  @param[in] stateSetId - value that identifies PLDM State set.
280  *  @param[in] repo - pointer to BMC's primary PDR repo.
281  *  @return array[array[uint8_t]] - StateEffecterPDRs
282  */
283 std::vector<std::vector<uint8_t>> findStateEffecterPDR(uint8_t tid,
284                                                        uint16_t entityID,
285                                                        uint16_t stateSetId,
286                                                        const pldm_pdr* repo);
287 /** @brief Find State Sensor PDR
288  *  @param[in] tid - PLDM terminus ID.
289  *  @param[in] entityID - entity that can be associated with PLDM State set.
290  *  @param[in] stateSetId - value that identifies PLDM State set.
291  *  @param[in] repo - pointer to BMC's primary PDR repo.
292  *  @return array[array[uint8_t]] - StateSensorPDRs
293  */
294 std::vector<std::vector<uint8_t>> findStateSensorPDR(uint8_t tid,
295                                                      uint16_t entityID,
296                                                      uint16_t stateSetId,
297                                                      const pldm_pdr* repo);
298 
299 /** @brief Find sensor id from a state sensor PDR
300  *
301  *  @param[in] pdrRepo - PDR repository
302  *  @param[in] tid - terminus id
303  *  @param[in] entityType - entity type
304  *  @param[in] entityInstance - entity instance number
305  *  @param[in] containerId - container id
306  *  @param[in] stateSetId - state set id
307  *
308  *  @return uint16_t - the sensor id
309  */
310 uint16_t findStateSensorId(const pldm_pdr* pdrRepo, uint8_t tid,
311                            uint16_t entityType, uint16_t entityInstance,
312                            uint16_t containerId, uint16_t stateSetId);
313 
314 /** @brief Find effecter id from a state effecter pdr
315  *  @param[in] pdrRepo - PDR repository
316  *  @param[in] entityType - entity type
317  *  @param[in] entityInstance - entity instance number
318  *  @param[in] containerId - container id
319  *  @param[in] stateSetId - state set id
320  *  @param[in] localOrRemote - true for checking local repo and false for remote
321  *                             repo
322  *
323  *  @return uint16_t - the effecter id
324  */
325 uint16_t findStateEffecterId(const pldm_pdr* pdrRepo, uint16_t entityType,
326                              uint16_t entityInstance, uint16_t containerId,
327                              uint16_t stateSetId, bool localOrRemote);
328 
329 /** @brief Emit the sensor event signal
330  *
331  *	@param[in] tid - the terminus id
332  *  @param[in] sensorId - sensorID value of the sensor
333  *  @param[in] sensorOffset - Identifies which state sensor within a
334  * composite state sensor the event is being returned for
335  *  @param[in] eventState - The event state value from the state change that
336  * triggered the event message
337  *  @param[in] previousEventState - The event state value for the state from
338  * which the present event state was entered.
339  *  @return PLDM completion code
340  */
341 int emitStateSensorEventSignal(uint8_t tid, uint16_t sensorId,
342                                uint8_t sensorOffset, uint8_t eventState,
343                                uint8_t previousEventState);
344 
345 /** @brief Print the buffer
346  *
347  *  @param[in]  buffer  - Buffer to print
348  *  @param[in]  pldmVerbose -verbosity flag - true/false
349  *
350  *  @return - None
351  */
352 void printBuffer(const std::vector<uint8_t>& buffer, bool pldmVerbose);
353 
354 /** @brief Convert the buffer to std::string
355  *
356  *  If there are characters that are not printable characters, it is replaced
357  *  with space(0x20).
358  *
359  *  @param[in] var - pointer to data and length of the data
360  *
361  *  @return std::string equivalent of variable field
362  */
363 std::string toString(const struct variable_field& var);
364 
365 } // namespace utils
366 } // namespace pldm
367