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