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