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