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