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 constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper"; 125 126 struct DBusMapping 127 { 128 std::string objectPath; //!< D-Bus object path 129 std::string interface; //!< D-Bus interface 130 std::string propertyName; //!< D-Bus property name 131 std::string propertyType; //!< D-Bus property type 132 }; 133 134 using PropertyValue = 135 std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, 136 uint64_t, double, std::string>; 137 using DbusProp = std::string; 138 using DbusChangedProps = std::map<DbusProp, PropertyValue>; 139 140 /** 141 * @brief The interface for DBusHandler 142 */ 143 class DBusHandlerInterface 144 { 145 public: 146 virtual ~DBusHandlerInterface() = default; 147 148 virtual std::string getService(const char* path, 149 const char* interface) const = 0; 150 151 virtual void setDbusProperty(const DBusMapping& dBusMap, 152 const PropertyValue& value) const = 0; 153 154 virtual PropertyValue 155 getDbusPropertyVariant(const char* objPath, const char* dbusProp, 156 const char* dbusInterface) const = 0; 157 }; 158 159 /** 160 * @class DBusHandler 161 * 162 * Wrapper class to handle the D-Bus calls 163 * 164 * This class contains the APIs to handle the D-Bus calls 165 * to cater the request from pldm requester. 166 * A class is created to mock the apis in the test cases 167 */ 168 class DBusHandler : public DBusHandlerInterface 169 { 170 public: 171 /** @brief Get the bus connection. */ 172 static auto& getBus() 173 { 174 static auto bus = sdbusplus::bus::new_default(); 175 return bus; 176 } 177 178 /** 179 * @brief Get the DBUS Service name for the input dbus path 180 * 181 * @param[in] path - DBUS object path 182 * @param[in] interface - DBUS Interface 183 * 184 * @return std::string - the dbus service name 185 * 186 * @throw sdbusplus::exception::SdBusError when it fails 187 */ 188 std::string getService(const char* path, 189 const char* interface) const override; 190 191 /** @brief Get property(type: variant) from the requested dbus 192 * 193 * @param[in] objPath - The Dbus object path 194 * @param[in] dbusProp - The property name to get 195 * @param[in] dbusInterface - The Dbus interface 196 * 197 * @return The value of the property(type: variant) 198 * 199 * @throw sdbusplus::exception::SdBusError when it fails 200 */ 201 PropertyValue 202 getDbusPropertyVariant(const char* objPath, const char* dbusProp, 203 const char* dbusInterface) const override; 204 205 /** @brief The template function to get property from the requested dbus 206 * path 207 * 208 * @tparam Property - Excepted type of the property on dbus 209 * 210 * @param[in] objPath - The Dbus object path 211 * @param[in] dbusProp - The property name to get 212 * @param[in] dbusInterface - The Dbus interface 213 * 214 * @return The value of the property 215 * 216 * @throw sdbusplus::exception::SdBusError when dbus request fails 217 * std::bad_variant_access when \p Property and property on dbus do 218 * not match 219 */ 220 template <typename Property> 221 auto getDbusProperty(const char* objPath, const char* dbusProp, 222 const char* dbusInterface) 223 { 224 auto VariantValue = 225 getDbusPropertyVariant(objPath, dbusProp, dbusInterface); 226 return std::get<Property>(VariantValue); 227 } 228 229 /** @brief Set Dbus property 230 * 231 * @param[in] dBusMap - Object path, property name, interface and property 232 * type for the D-Bus object 233 * @param[in] value - The value to be set 234 * 235 * @throw sdbusplus::exception::SdBusError when it fails 236 */ 237 void setDbusProperty(const DBusMapping& dBusMap, 238 const PropertyValue& value) const override; 239 }; 240 241 /** @brief Fetch parent D-Bus object based on pathname 242 * 243 * @param[in] dbusObj - child D-Bus object 244 * 245 * @return std::string - the parent D-Bus object path 246 */ 247 inline std::string findParent(const std::string& dbusObj) 248 { 249 fs::path p(dbusObj); 250 return p.parent_path().string(); 251 } 252 253 /** @brief Read (static) MCTP EID of host firmware from a file 254 * 255 * @return uint8_t - MCTP EID 256 */ 257 uint8_t readHostEID(); 258 259 /** @brief Convert a value in the JSON to a D-Bus property value 260 * 261 * @param[in] type - type of the D-Bus property 262 * @param[in] value - value in the JSON file 263 * 264 * @return PropertyValue - the D-Bus property value 265 */ 266 PropertyValue jsonEntryToDbusVal(std::string_view type, 267 const nlohmann::json& value); 268 269 /** @brief Find State Effecter PDR 270 * @param[in] tid - PLDM terminus ID. 271 * @param[in] entityID - entity that can be associated with PLDM State set. 272 * @param[in] stateSetId - value that identifies PLDM State set. 273 * @param[in] repo - pointer to BMC's primary PDR repo. 274 * @return array[array[uint8_t]] - StateEffecterPDRs 275 */ 276 std::vector<std::vector<uint8_t>> findStateEffecterPDR(uint8_t tid, 277 uint16_t entityID, 278 uint16_t stateSetId, 279 const pldm_pdr* repo); 280 /** @brief Find State Sensor PDR 281 * @param[in] tid - PLDM terminus ID. 282 * @param[in] entityID - entity that can be associated with PLDM State set. 283 * @param[in] stateSetId - value that identifies PLDM State set. 284 * @param[in] repo - pointer to BMC's primary PDR repo. 285 * @return array[array[uint8_t]] - StateSensorPDRs 286 */ 287 std::vector<std::vector<uint8_t>> findStateSensorPDR(uint8_t tid, 288 uint16_t entityID, 289 uint16_t stateSetId, 290 const pldm_pdr* repo); 291 292 /** @brief Find effecter id from a state effecter pdr 293 * @param[in] pdrRepo - PDR repository 294 * @param[in] entityType - entity type 295 * @param[in] entityInstance - entity instance number 296 * @param[in] containerId - container id 297 * @param[in] stateSetId - state set id 298 * @param[in] localOrRemote - true for checking local repo and false for remote 299 * repo 300 * 301 * @return uint16_t - the effecter id 302 */ 303 uint16_t findStateEffecterId(const pldm_pdr* pdrRepo, uint16_t entityType, 304 uint16_t entityInstance, uint16_t containerId, 305 uint16_t stateSetId, bool localOrRemote); 306 307 /** @brief Emit the sensor event signal 308 * 309 * @param[in] tid - the terminus id 310 * @param[in] sensorId - sensorID value of the sensor 311 * @param[in] sensorOffset - Identifies which state sensor within a 312 * composite state sensor the event is being returned for 313 * @param[in] eventState - The event state value from the state change that 314 * triggered the event message 315 * @param[in] previousEventState - The event state value for the state from 316 * which the present event state was entered. 317 * @return PLDM completion code 318 */ 319 int emitStateSensorEventSignal(uint8_t tid, uint16_t sensorId, 320 uint8_t sensorOffset, uint8_t eventState, 321 uint8_t previousEventState); 322 323 } // namespace utils 324 } // namespace pldm 325