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