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