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