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