1 #pragma once 2 3 #include <chrono> 4 #include <ipmid/api-types.hpp> 5 #include <ipmid/types.hpp> 6 #include <optional> 7 #include <sdbusplus/server.hpp> 8 9 namespace ipmi 10 { 11 12 using namespace std::literals::chrono_literals; 13 14 constexpr auto MAPPER_BUS_NAME = "xyz.openbmc_project.ObjectMapper"; 15 constexpr auto MAPPER_OBJ = "/xyz/openbmc_project/object_mapper"; 16 constexpr auto MAPPER_INTF = "xyz.openbmc_project.ObjectMapper"; 17 18 constexpr auto ROOT = "/"; 19 constexpr auto HOST_MATCH = "host0"; 20 21 constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties"; 22 constexpr auto DELETE_INTERFACE = "xyz.openbmc_project.Object.Delete"; 23 24 constexpr auto METHOD_GET = "Get"; 25 constexpr auto METHOD_GET_ALL = "GetAll"; 26 constexpr auto METHOD_SET = "Set"; 27 28 /* Use a value of 5s which aligns with BT/KCS bridged timeouts, rather 29 * than the default 25s D-Bus timeout. */ 30 constexpr std::chrono::microseconds IPMI_DBUS_TIMEOUT = 5s; 31 32 /** @class ServiceCache 33 * @brief Caches lookups of service names from the object mapper. 34 * @details Most ipmi commands need to talk to other dbus daemons to perform 35 * their intended actions on the BMC. This usually means they will 36 * first look up the service name providing the interface they 37 * require. This class reduces the number of such calls by caching 38 * the lookup for a specific service. 39 */ 40 class ServiceCache 41 { 42 public: 43 /** @brief Creates a new service cache for the given interface 44 * and path. 45 * 46 * @param[in] intf - The interface used for each lookup 47 * @param[in] path - The path used for each lookup 48 */ 49 ServiceCache(const std::string& intf, const std::string& path); 50 ServiceCache(std::string&& intf, std::string&& path); 51 52 /** @brief Gets the service name from the cache or does in a 53 * lookup when invalid. 54 * 55 * @param[in] bus - The bus associated with and used for looking 56 * up the service. 57 */ 58 const std::string& getService(sdbusplus::bus::bus& bus); 59 60 /** @brief Invalidates the current service name */ 61 void invalidate(); 62 63 /** @brief A wrapper around sdbusplus bus.new_method_call 64 * 65 * @param[in] bus - The bus used for calling the method 66 * @param[in] intf - The interface containing the method 67 * @param[in] method - The method name 68 * @return The message containing the method call. 69 */ 70 sdbusplus::message::message newMethodCall(sdbusplus::bus::bus& bus, 71 const char* intf, 72 const char* method); 73 74 /** @brief Check to see if the current cache is valid 75 * 76 * @param[in] bus - The bus used for the service lookup 77 * @return True if the cache is valid false otherwise. 78 */ 79 bool isValid(sdbusplus::bus::bus& bus) const; 80 81 private: 82 /** @brief DBUS interface provided by the service */ 83 const std::string intf; 84 /** @brief DBUS path provided by the service */ 85 const std::string path; 86 /** @brief The name of the service if valid */ 87 std::optional<std::string> cachedService; 88 /** @brief The name of the bus used in the service lookup */ 89 std::optional<std::string> cachedBusName; 90 }; 91 92 /** 93 * @brief Get the DBUS Service name for the input dbus path 94 * 95 * @param[in] bus - DBUS Bus Object 96 * @param[in] intf - DBUS Interface 97 * @param[in] path - DBUS Object Path 98 * 99 */ 100 std::string getService(sdbusplus::bus::bus& bus, const std::string& intf, 101 const std::string& path); 102 103 /** @brief Gets the dbus object info implementing the given interface 104 * from the given subtree. 105 * @param[in] bus - DBUS Bus Object. 106 * @param[in] interface - Dbus interface. 107 * @param[in] subtreePath - subtree from where the search should start. 108 * @param[in] match - identifier for object. 109 * @return On success returns the object having objectpath and servicename. 110 */ 111 DbusObjectInfo getDbusObject(sdbusplus::bus::bus& bus, 112 const std::string& interface, 113 const std::string& subtreePath = ROOT, 114 const std::string& match = {}); 115 116 /** @brief Gets the value associated with the given object 117 * and the interface. 118 * @param[in] bus - DBUS Bus Object. 119 * @param[in] service - Dbus service name. 120 * @param[in] objPath - Dbus object path. 121 * @param[in] interface - Dbus interface. 122 * @param[in] property - name of the property. 123 * @return On success returns the value of the property. 124 */ 125 Value getDbusProperty(sdbusplus::bus::bus& bus, const std::string& service, 126 const std::string& objPath, const std::string& interface, 127 const std::string& property, 128 std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT); 129 130 /** @brief Gets all the properties associated with the given object 131 * and the interface. 132 * @param[in] bus - DBUS Bus Object. 133 * @param[in] service - Dbus service name. 134 * @param[in] objPath - Dbus object path. 135 * @param[in] interface - Dbus interface. 136 * @return On success returns the map of name value pair. 137 */ 138 PropertyMap 139 getAllDbusProperties(sdbusplus::bus::bus& bus, const std::string& service, 140 const std::string& objPath, 141 const std::string& interface, 142 std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT); 143 144 /** @brief Gets all managed objects associated with the given object 145 * path and service. 146 * @param[in] bus - D-Bus Bus Object. 147 * @param[in] service - D-Bus service name. 148 * @param[in] objPath - D-Bus object path. 149 * @return On success returns the map of name value pair. 150 */ 151 ObjectValueTree getManagedObjects(sdbusplus::bus::bus& bus, 152 const std::string& service, 153 const std::string& objPath); 154 155 /** @brief Sets the property value of the given object. 156 * @param[in] bus - DBUS Bus Object. 157 * @param[in] service - Dbus service name. 158 * @param[in] objPath - Dbus object path. 159 * @param[in] interface - Dbus interface. 160 * @param[in] property - name of the property. 161 * @param[in] value - value which needs to be set. 162 */ 163 void setDbusProperty(sdbusplus::bus::bus& bus, const std::string& service, 164 const std::string& objPath, const std::string& interface, 165 const std::string& property, const Value& value, 166 std::chrono::microseconds timeout = IPMI_DBUS_TIMEOUT); 167 168 /** @brief Gets all the dbus objects from the given service root 169 * which matches the object identifier. 170 * @param[in] bus - DBUS Bus Object. 171 * @param[in] serviceRoot - Service root path. 172 * @param[in] interface - Dbus interface. 173 * @param[in] match - Identifier for a path. 174 * @returns map of object path and service info. 175 */ 176 ObjectTree getAllDbusObjects(sdbusplus::bus::bus& bus, 177 const std::string& serviceRoot, 178 const std::string& interface, 179 const std::string& match = {}); 180 181 /** @brief Deletes all the dbus objects from the given service root 182 which matches the object identifier. 183 * @param[in] bus - DBUS Bus Object. 184 * @param[in] serviceRoot - Service root path. 185 * @param[in] interface - Dbus interface. 186 * @param[in] match - Identifier for object. 187 */ 188 void deleteAllDbusObjects(sdbusplus::bus::bus& bus, 189 const std::string& serviceRoot, 190 const std::string& interface, 191 const std::string& match = {}); 192 193 /** @brief Gets the ancestor objects of the given object 194 which implements the given interface. 195 * @param[in] bus - Dbus bus object. 196 * @param[in] path - Child Dbus object path. 197 * @param[in] interfaces - Dbus interface list. 198 * @return map of object path and service info. 199 */ 200 ObjectTree getAllAncestors(sdbusplus::bus::bus& bus, const std::string& path, 201 InterfaceList&& interfaces); 202 203 /** @struct VariantToDoubleVisitor 204 * @brief Visitor to convert variants to doubles 205 * @details Performs a static cast on the underlying type 206 */ 207 struct VariantToDoubleVisitor 208 { 209 template <typename T> 210 std::enable_if_t<std::is_arithmetic<T>::value, double> 211 operator()(const T& t) const 212 { 213 return static_cast<double>(t); 214 } 215 216 template <typename T> 217 std::enable_if_t<!std::is_arithmetic<T>::value, double> 218 operator()(const T& t) const 219 { 220 throw std::invalid_argument("Cannot translate type to double"); 221 } 222 }; 223 224 namespace method_no_args 225 { 226 227 /** @brief Calls the Dbus method which waits for response. 228 * @param[in] bus - DBUS Bus Object. 229 * @param[in] service - Dbus service name. 230 * @param[in] objPath - Dbus object path. 231 * @param[in] interface - Dbus interface. 232 * @param[in] method - Dbus method. 233 */ 234 void callDbusMethod(sdbusplus::bus::bus& bus, const std::string& service, 235 const std::string& objPath, const std::string& interface, 236 const std::string& method); 237 238 } // namespace method_no_args 239 240 /** @brief Perform the low-level i2c bus write-read. 241 * @param[in] i2cBus - i2c bus device node name, such as /dev/i2c-2. 242 * @param[in] slaveAddr - i2c device slave address. 243 * @param[in] writeData - The data written to i2c device. 244 * @param[out] readBuf - Data read from the i2c device. 245 */ 246 ipmi::Cc i2cWriteRead(std::string i2cBus, const uint8_t slaveAddr, 247 std::vector<uint8_t> writeData, 248 std::vector<uint8_t>& readBuf); 249 } // namespace ipmi 250