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 void setDbusProperty(const DBusMapping& dBusMap, 148 const PropertyValue& value) const = 0; 149 150 virtual PropertyValue 151 getDbusPropertyVariant(const char* objPath, const char* dbusProp, 152 const char* dbusInterface) const = 0; 153 }; 154 155 /** 156 * @class DBusHandler 157 * 158 * Wrapper class to handle the D-Bus calls 159 * 160 * This class contains the APIs to handle the D-Bus calls 161 * to cater the request from pldm requester. 162 * A class is created to mock the apis in the test cases 163 */ 164 class DBusHandler : public DBusHandlerInterface 165 { 166 public: 167 /** @brief Get the bus connection. */ 168 static auto& getBus() 169 { 170 static auto bus = sdbusplus::bus::new_default(); 171 return bus; 172 } 173 174 /** 175 * @brief Get the DBUS Service name for the input dbus path 176 * 177 * @param[in] path - DBUS object path 178 * @param[in] interface - DBUS Interface 179 * 180 * @return std::string - the dbus service name 181 * 182 * @throw sdbusplus::exception::SdBusError when it fails 183 */ 184 std::string getService(const char* path, const char* interface) const; 185 186 /** @brief Get property(type: variant) from the requested dbus 187 * 188 * @param[in] objPath - The Dbus object path 189 * @param[in] dbusProp - The property name to get 190 * @param[in] dbusInterface - The Dbus interface 191 * 192 * @return The value of the property(type: variant) 193 * 194 * @throw sdbusplus::exception::SdBusError when it fails 195 */ 196 PropertyValue 197 getDbusPropertyVariant(const char* objPath, const char* dbusProp, 198 const char* dbusInterface) const override; 199 200 /** @brief The template function to get property from the requested dbus 201 * path 202 * 203 * @tparam Property - Excepted type of the property on dbus 204 * 205 * @param[in] objPath - The Dbus object path 206 * @param[in] dbusProp - The property name to get 207 * @param[in] dbusInterface - The Dbus interface 208 * 209 * @return The value of the property 210 * 211 * @throw sdbusplus::exception::SdBusError when dbus request fails 212 * std::bad_variant_access when \p Property and property on dbus do 213 * not match 214 */ 215 template <typename Property> 216 auto getDbusProperty(const char* objPath, const char* dbusProp, 217 const char* dbusInterface) 218 { 219 auto VariantValue = 220 getDbusPropertyVariant(objPath, dbusProp, dbusInterface); 221 return std::get<Property>(VariantValue); 222 } 223 224 /** @brief Set Dbus property 225 * 226 * @param[in] dBusMap - Object path, property name, interface and property 227 * type for the D-Bus object 228 * @param[in] value - The value to be set 229 * 230 * @throw sdbusplus::exception::SdBusError when it fails 231 */ 232 void setDbusProperty(const DBusMapping& dBusMap, 233 const PropertyValue& value) const override; 234 }; 235 236 /** @brief Fetch parent D-Bus object based on pathname 237 * 238 * @param[in] dbusObj - child D-Bus object 239 * 240 * @return std::string - the parent D-Bus object path 241 */ 242 inline std::string findParent(const std::string& dbusObj) 243 { 244 fs::path p(dbusObj); 245 return p.parent_path().string(); 246 } 247 248 /** @brief Read (static) MCTP EID of host firmware from a file 249 * 250 * @return uint8_t - MCTP EID 251 */ 252 uint8_t readHostEID(); 253 254 /** @brief Convert a value in the JSON to a D-Bus property value 255 * 256 * @param[in] type - type of the D-Bus property 257 * @param[in] value - value in the JSON file 258 * 259 * @return PropertyValue - the D-Bus property value 260 */ 261 PropertyValue jsonEntryToDbusVal(std::string_view type, 262 const nlohmann::json& value); 263 264 /** @brief Find State Effecter PDR 265 * @param[in] tid - PLDM terminus ID. 266 * @param[in] entityID - entity that can be associated with PLDM State set. 267 * @param[in] stateSetId - value that identifies PLDM State set. 268 * @param[in] repo - pointer to BMC's primary PDR repo. 269 * @return array[array[uint8_t]] - StateEffecterPDRs 270 */ 271 std::vector<std::vector<uint8_t>> findStateEffecterPDR(uint8_t tid, 272 uint16_t entityID, 273 uint16_t stateSetId, 274 const pldm_pdr* repo); 275 /** @brief Find State Sensor PDR 276 * @param[in] tid - PLDM terminus ID. 277 * @param[in] entityID - entity that can be associated with PLDM State set. 278 * @param[in] stateSetId - value that identifies PLDM State set. 279 * @param[in] repo - pointer to BMC's primary PDR repo. 280 * @return array[array[uint8_t]] - StateSensorPDRs 281 */ 282 std::vector<std::vector<uint8_t>> findStateSensorPDR(uint8_t tid, 283 uint16_t entityID, 284 uint16_t stateSetId, 285 const pldm_pdr* repo); 286 287 /** @brief Find effecter id from a state effecter pdr 288 * @param[in] pdrRepo - PDR repository 289 * @param[in] entityType - entity type 290 * @param[in] entityInstance - entity instance number 291 * @param[in] containerId - container id 292 * @param[in] stateSetId - state set id 293 * 294 * @return uint16_t - the effecter id 295 */ 296 uint16_t findStateEffecterId(const pldm_pdr* pdrRepo, uint16_t entityType, 297 uint16_t entityInstance, uint16_t containerId, 298 uint16_t stateSetId); 299 300 } // namespace utils 301 } // namespace pldm 302