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