1 #pragma once 2 3 #include "types.hpp" 4 #include "utils.hpp" 5 6 #include <math.h> 7 8 #include "host-ipmid/ipmid-api.h" 9 #include "sensorhandler.h" 10 11 namespace ipmi 12 { 13 namespace sensor 14 { 15 16 using Assertion = uint16_t; 17 using Deassertion = uint16_t; 18 using AssertionSet = std::pair<Assertion, Deassertion>; 19 20 using Service = std::string; 21 using Path = std::string; 22 using Interface = std::string; 23 24 using ServicePath = std::pair<Path, Service>; 25 26 using Interfaces = std::vector<Interface>; 27 28 using MapperResponseType = std::map<Path, std::map<Service, Interfaces>>; 29 30 /** @brief get the D-Bus service and service path 31 * @param[in] bus - The Dbus bus object 32 * @param[in] interface - interface to the service 33 * @param[in] path - interested path in the list of objects 34 * @return pair of service path and service 35 */ 36 ServicePath getServiceAndPath(sdbusplus::bus::bus& bus, 37 const std::string& interface, 38 const std::string& path = std::string()); 39 40 /** @brief Make assertion set from input data 41 * @param[in] cmdData - Input sensor data 42 * @return pair of assertion and deassertion set 43 */ 44 AssertionSet getAssertionSet(const SetSensorReadingReq& cmdData); 45 46 /** @brief send the message to DBus 47 * @param[in] msg - message to send 48 * @return failure status in IPMI error code 49 */ 50 ipmi_ret_t updateToDbus(IpmiUpdateData& msg); 51 52 namespace get 53 { 54 55 /** @brief Populate sensor name from the D-Bus property associated with the 56 * sensor. In the example entry from the yaml, the name of the D-bus 57 * property "AttemptsLeft" is the sensor name. 58 * 59 * 0x07: 60 * sensorType: 195 61 * path: /xyz/openbmc_project/state/host0 62 * sensorReadingType: 0x6F 63 * serviceInterface: org.freedesktop.DBus.Properties 64 * readingType: readingAssertion 65 * sensorNamePattern: nameProperty 66 * interfaces: 67 * xyz.openbmc_project.Control.Boot.RebootAttempts: 68 * AttemptsLeft: 69 * Offsets: 70 * 0xFF: 71 * type: uint32_t 72 * 73 * 74 * @param[in] sensorInfo - Dbus info related to sensor. 75 * 76 * @return On success return the sensor name for the sensor. 77 */ 78 inline SensorName nameProperty(const Info& sensorInfo) 79 { 80 return sensorInfo.propertyInterfaces.begin()->second.begin()->first; 81 } 82 83 /** @brief Populate sensor name from the D-Bus object associated with the 84 * sensor. If the object path is /system/chassis/motherboard/dimm0 then 85 * the leaf dimm0 is considered as the sensor name. 86 * 87 * @param[in] sensorInfo - Dbus info related to sensor. 88 * 89 * @return On success return the sensor name for the sensor. 90 */ 91 inline SensorName nameLeaf(const Info& sensorInfo) 92 { 93 return sensorInfo.sensorPath.substr( 94 sensorInfo.sensorPath.find_last_of('/') + 1, 95 sensorInfo.sensorPath.length()); 96 } 97 98 /** @brief Populate sensor name from the D-Bus object associated with the 99 * sensor. If the object path is /system/chassis/motherboard/cpu0/core0 100 * then the sensor name is cpu0_core0. The leaf and the parent is put 101 * together to get the sensor name. 102 * 103 * @param[in] sensorInfo - Dbus info related to sensor. 104 * 105 * @return On success return the sensor name for the sensor. 106 */ 107 SensorName nameParentLeaf(const Info& sensorInfo); 108 109 /** 110 * @brief Helper function to map the dbus info to sensor's assertion status 111 * for the get sensor reading command. 112 * 113 * @param[in] sensorInfo - Dbus info related to sensor. 114 * @param[in] path - Dbus object path. 115 * @param[in] interface - Dbus interface. 116 * 117 * @return Response for get sensor reading command. 118 */ 119 GetSensorResponse mapDbusToAssertion(const Info& sensorInfo, 120 const InstancePath& path, 121 const DbusInterface& interface); 122 123 /** 124 * @brief Map the Dbus info to sensor's assertion status in the Get sensor 125 * reading command response. 126 * 127 * @param[in] sensorInfo - Dbus info related to sensor. 128 * 129 * @return Response for get sensor reading command. 130 */ 131 GetSensorResponse assertion(const Info& sensorInfo); 132 133 /** 134 * @brief Maps the Dbus info to the reading field in the Get sensor reading 135 * command response. 136 * 137 * @param[in] sensorInfo - Dbus info related to sensor. 138 * 139 * @return Response for get sensor reading command. 140 */ 141 GetSensorResponse eventdata2(const Info& sensorInfo); 142 143 /** 144 * @brief readingAssertion is a case where the entire assertion state field 145 * serves as the sensor value. 146 * 147 * @tparam T - type of the dbus property related to sensor. 148 * @param[in] sensorInfo - Dbus info related to sensor. 149 * 150 * @return Response for get sensor reading command. 151 */ 152 template <typename T> 153 GetSensorResponse readingAssertion(const Info& sensorInfo) 154 { 155 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; 156 GetSensorResponse response{}; 157 auto responseData = reinterpret_cast<GetReadingResponse*>(response.data()); 158 159 auto service = ipmi::getService(bus, sensorInfo.sensorInterface, 160 sensorInfo.sensorPath); 161 162 auto propValue = ipmi::getDbusProperty( 163 bus, service, sensorInfo.sensorPath, 164 sensorInfo.propertyInterfaces.begin()->first, 165 sensorInfo.propertyInterfaces.begin()->second.begin()->first); 166 167 setAssertionBytes(static_cast<uint16_t>(propValue.get<T>()), responseData); 168 169 return response; 170 } 171 172 /** @brief Map the Dbus info to the reading field in the Get sensor reading 173 * command response 174 * 175 * @tparam T - type of the dbus property related to sensor. 176 * @param[in] sensorInfo - Dbus info related to sensor. 177 * 178 * @return Response for get sensor reading command. 179 */ 180 template <typename T> 181 GetSensorResponse readingData(const Info& sensorInfo) 182 { 183 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; 184 GetSensorResponse response{}; 185 auto responseData = reinterpret_cast<GetReadingResponse*>(response.data()); 186 187 enableScanning(responseData); 188 189 auto service = ipmi::getService(bus, sensorInfo.sensorInterface, 190 sensorInfo.sensorPath); 191 192 auto propValue = ipmi::getDbusProperty( 193 bus, service, sensorInfo.sensorPath, 194 sensorInfo.propertyInterfaces.begin()->first, 195 sensorInfo.propertyInterfaces.begin()->second.begin()->first); 196 197 double value = 198 propValue.get<T>() * pow(10, sensorInfo.scale - sensorInfo.exponentR); 199 200 auto rawData = static_cast<uint8_t>((value - sensorInfo.scaledOffset) / 201 sensorInfo.coefficientM); 202 203 setReading(rawData, responseData); 204 205 return response; 206 } 207 208 } // namespace get 209 210 namespace set 211 { 212 213 /** @brief Make a DBus message for a Dbus call 214 * @param[in] updateInterface - Interface name 215 * @param[in] sensorPath - Path of the sensor 216 * @param[in] command - command to be executed 217 * @param[in] sensorInterface - DBus interface of sensor 218 * @return a dbus message 219 */ 220 IpmiUpdateData makeDbusMsg(const std::string& updateInterface, 221 const std::string& sensorPath, 222 const std::string& command, 223 const std::string& sensorInterface); 224 225 /** @brief Update d-bus based on assertion type sensor data 226 * @param[in] cmdData - input sensor data 227 * @param[in] sensorInfo - sensor d-bus info 228 * @return a IPMI error code 229 */ 230 ipmi_ret_t assertion(const SetSensorReadingReq& cmdData, 231 const Info& sensorInfo); 232 233 /** @brief Update d-bus based on a reading assertion 234 * @tparam T - type of d-bus property mapping this sensor 235 * @param[in] cmdData - input sensor data 236 * @param[in] sensorInfo - sensor d-bus info 237 * @return a IPMI error code 238 */ 239 template <typename T> 240 ipmi_ret_t readingAssertion(const SetSensorReadingReq& cmdData, 241 const Info& sensorInfo) 242 { 243 auto msg = 244 makeDbusMsg("org.freedesktop.DBus.Properties", sensorInfo.sensorPath, 245 "Set", sensorInfo.sensorInterface); 246 247 const auto& interface = sensorInfo.propertyInterfaces.begin(); 248 msg.append(interface->first); 249 for (const auto& property : interface->second) 250 { 251 msg.append(property.first); 252 sdbusplus::message::variant<T> value = 253 (cmdData.assertOffset8_14 << 8) | cmdData.assertOffset0_7; 254 msg.append(value); 255 } 256 return updateToDbus(msg); 257 } 258 259 /** @brief Update d-bus based on a discrete reading 260 * @param[in] cmdData - input sensor data 261 * @param[in] sensorInfo - sensor d-bus info 262 * @return an IPMI error code 263 */ 264 template <typename T> 265 ipmi_ret_t readingData(const SetSensorReadingReq& cmdData, 266 const Info& sensorInfo) 267 { 268 T raw_value = 269 (sensorInfo.coefficientM * cmdData.reading) + sensorInfo.scaledOffset; 270 271 raw_value *= pow(10, sensorInfo.exponentR - sensorInfo.scale); 272 273 auto msg = 274 makeDbusMsg("org.freedesktop.DBus.Properties", sensorInfo.sensorPath, 275 "Set", sensorInfo.sensorInterface); 276 277 const auto& interface = sensorInfo.propertyInterfaces.begin(); 278 msg.append(interface->first); 279 280 for (const auto& property : interface->second) 281 { 282 msg.append(property.first); 283 sdbusplus::message::variant<T> value = raw_value; 284 msg.append(value); 285 } 286 return updateToDbus(msg); 287 } 288 289 /** @brief Update d-bus based on eventdata type sensor data 290 * @param[in] cmdData - input sensor data 291 * @param[in] sensorInfo - sensor d-bus info 292 * @return a IPMI error code 293 */ 294 ipmi_ret_t eventdata(const SetSensorReadingReq& cmdData, const Info& sensorInfo, 295 uint8_t data); 296 297 /** @brief Update d-bus based on eventdata1 type sensor data 298 * @param[in] cmdData - input sensor data 299 * @param[in] sensorInfo - sensor d-bus info 300 * @return a IPMI error code 301 */ 302 inline ipmi_ret_t eventdata1(const SetSensorReadingReq& cmdData, 303 const Info& sensorInfo) 304 { 305 return eventdata(cmdData, sensorInfo, cmdData.eventData1); 306 } 307 308 /** @brief Update d-bus based on eventdata2 type sensor data 309 * @param[in] cmdData - input sensor data 310 * @param[in] sensorInfo - sensor d-bus info 311 * @return a IPMI error code 312 */ 313 inline ipmi_ret_t eventdata2(const SetSensorReadingReq& cmdData, 314 const Info& sensorInfo) 315 { 316 return eventdata(cmdData, sensorInfo, cmdData.eventData2); 317 } 318 319 /** @brief Update d-bus based on eventdata3 type sensor data 320 * @param[in] cmdData - input sensor data 321 * @param[in] sensorInfo - sensor d-bus info 322 * @return a IPMI error code 323 */ 324 inline ipmi_ret_t eventdata3(const SetSensorReadingReq& cmdData, 325 const Info& sensorInfo) 326 { 327 return eventdata(cmdData, sensorInfo, cmdData.eventData3); 328 } 329 330 } // namespace set 331 332 namespace notify 333 { 334 335 /** @brief Make a DBus message for a Dbus call 336 * @param[in] updateInterface - Interface name 337 * @param[in] sensorPath - Path of the sensor 338 * @param[in] command - command to be executed 339 * @param[in] sensorInterface - DBus interface of sensor 340 * @return a dbus message 341 */ 342 IpmiUpdateData makeDbusMsg(const std::string& updateInterface, 343 const std::string& sensorPath, 344 const std::string& command, 345 const std::string& sensorInterface); 346 347 /** @brief Update d-bus based on assertion type sensor data 348 * @param[in] interfaceMap - sensor interface 349 * @param[in] cmdData - input sensor data 350 * @param[in] sensorInfo - sensor d-bus info 351 * @return a IPMI error code 352 */ 353 ipmi_ret_t assertion(const SetSensorReadingReq& cmdData, 354 const Info& sensorInfo); 355 356 } // namespace notify 357 358 namespace inventory 359 { 360 361 namespace get 362 { 363 364 /** 365 * @brief Map the Dbus info to sensor's assertion status in the Get sensor 366 * reading command response. 367 * 368 * @param[in] sensorInfo - Dbus info related to sensor. 369 * 370 * @return Response for get sensor reading command. 371 */ 372 GetSensorResponse assertion(const Info& sensorInfo); 373 374 } // namespace get 375 376 } // namespace inventory 377 } // namespace sensor 378 } // namespace ipmi 379