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