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