blob: f263636ae9b23dadcd886f4b0539857e84866f60 [file] [log] [blame]
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -05001#pragma once
2
Brandon Kim9cf85622019-06-19 12:05:08 -07003#include "config.h"
4
Patrick Venture46470a32018-09-07 19:26:25 -07005#include "sensorhandler.hpp"
Patrick Venture0b02be92018-08-31 11:55:55 -07006
Patrick Venture586d35b2018-09-07 19:56:18 -07007#include <cmath>
Vernon Mauerye08fbff2019-04-03 09:19:34 -07008#include <ipmid/api.hpp>
Vernon Mauery33250242019-03-12 16:49:26 -07009#include <ipmid/types.hpp>
Vernon Mauery6a98fe72019-03-11 15:57:48 -070010#include <ipmid/utils.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070011#include <sdbusplus/message/types.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070012
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050013namespace ipmi
14{
15namespace sensor
16{
17
18using Assertion = uint16_t;
19using Deassertion = uint16_t;
20using AssertionSet = std::pair<Assertion, Deassertion>;
21
22using Service = std::string;
23using Path = std::string;
24using Interface = std::string;
25
26using ServicePath = std::pair<Path, Service>;
27
28using Interfaces = std::vector<Interface>;
29
30using MapperResponseType = std::map<Path, std::map<Service, Interfaces>>;
31
32/** @brief get the D-Bus service and service path
33 * @param[in] bus - The Dbus bus object
34 * @param[in] interface - interface to the service
35 * @param[in] path - interested path in the list of objects
36 * @return pair of service path and service
37 */
38ServicePath getServiceAndPath(sdbusplus::bus::bus& bus,
39 const std::string& interface,
40 const std::string& path = std::string());
41
42/** @brief Make assertion set from input data
43 * @param[in] cmdData - Input sensor data
44 * @return pair of assertion and deassertion set
45 */
46AssertionSet getAssertionSet(const SetSensorReadingReq& cmdData);
47
48/** @brief send the message to DBus
49 * @param[in] msg - message to send
50 * @return failure status in IPMI error code
51 */
Dhruvaraj Subhashchandran2a444d02017-08-07 01:45:14 -050052ipmi_ret_t updateToDbus(IpmiUpdateData& msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050053
Tom Joseph816e92b2017-09-06 19:23:00 +053054namespace get
55{
56
Tom Josephb0adbcd2018-01-24 11:51:29 +053057/** @brief Populate sensor name from the D-Bus property associated with the
58 * sensor. In the example entry from the yaml, the name of the D-bus
59 * property "AttemptsLeft" is the sensor name.
60 *
61 * 0x07:
62 * sensorType: 195
63 * path: /xyz/openbmc_project/state/host0
64 * sensorReadingType: 0x6F
65 * serviceInterface: org.freedesktop.DBus.Properties
66 * readingType: readingAssertion
67 * sensorNamePattern: nameProperty
68 * interfaces:
69 * xyz.openbmc_project.Control.Boot.RebootAttempts:
70 * AttemptsLeft:
71 * Offsets:
72 * 0xFF:
73 * type: uint32_t
74 *
75 *
76 * @param[in] sensorInfo - Dbus info related to sensor.
77 *
78 * @return On success return the sensor name for the sensor.
79 */
80inline SensorName nameProperty(const Info& sensorInfo)
81{
82 return sensorInfo.propertyInterfaces.begin()->second.begin()->first;
83}
84
85/** @brief Populate sensor name from the D-Bus object associated with the
86 * sensor. If the object path is /system/chassis/motherboard/dimm0 then
87 * the leaf dimm0 is considered as the sensor name.
88 *
89 * @param[in] sensorInfo - Dbus info related to sensor.
90 *
91 * @return On success return the sensor name for the sensor.
92 */
93inline SensorName nameLeaf(const Info& sensorInfo)
94{
95 return sensorInfo.sensorPath.substr(
Patrick Venture0b02be92018-08-31 11:55:55 -070096 sensorInfo.sensorPath.find_last_of('/') + 1,
97 sensorInfo.sensorPath.length());
Tom Josephb0adbcd2018-01-24 11:51:29 +053098}
99
100/** @brief Populate sensor name from the D-Bus object associated with the
101 * sensor. If the object path is /system/chassis/motherboard/cpu0/core0
102 * then the sensor name is cpu0_core0. The leaf and the parent is put
103 * together to get the sensor name.
104 *
105 * @param[in] sensorInfo - Dbus info related to sensor.
106 *
107 * @return On success return the sensor name for the sensor.
108 */
109SensorName nameParentLeaf(const Info& sensorInfo);
110
Tom Joseph816e92b2017-09-06 19:23:00 +0530111/**
112 * @brief Helper function to map the dbus info to sensor's assertion status
113 * for the get sensor reading command.
114 *
115 * @param[in] sensorInfo - Dbus info related to sensor.
116 * @param[in] path - Dbus object path.
117 * @param[in] interface - Dbus interface.
118 *
119 * @return Response for get sensor reading command.
120 */
121GetSensorResponse mapDbusToAssertion(const Info& sensorInfo,
122 const InstancePath& path,
123 const DbusInterface& interface);
124
125/**
126 * @brief Map the Dbus info to sensor's assertion status in the Get sensor
127 * reading command response.
128 *
129 * @param[in] sensorInfo - Dbus info related to sensor.
130 *
131 * @return Response for get sensor reading command.
132 */
133GetSensorResponse assertion(const Info& sensorInfo);
134
Tom Josephe4014fc2017-09-06 23:57:36 +0530135/**
136 * @brief Maps the Dbus info to the reading field in the Get sensor reading
137 * command response.
138 *
139 * @param[in] sensorInfo - Dbus info related to sensor.
140 *
141 * @return Response for get sensor reading command.
142 */
143GetSensorResponse eventdata2(const Info& sensorInfo);
144
Tom Joseph295f17e2017-09-07 00:09:46 +0530145/**
146 * @brief readingAssertion is a case where the entire assertion state field
147 * serves as the sensor value.
148 *
149 * @tparam T - type of the dbus property related to sensor.
150 * @param[in] sensorInfo - Dbus info related to sensor.
151 *
152 * @return Response for get sensor reading command.
153 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700154template <typename T>
Tom Joseph295f17e2017-09-07 00:09:46 +0530155GetSensorResponse readingAssertion(const Info& sensorInfo)
156{
157 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Patrick Venture0b02be92018-08-31 11:55:55 -0700158 GetSensorResponse response{};
Tom Joseph295f17e2017-09-07 00:09:46 +0530159
Jeremy Kerr3dc35582020-05-17 15:47:07 +0800160 enableScanning(&response);
161
Patrick Venture0b02be92018-08-31 11:55:55 -0700162 auto service = ipmi::getService(bus, sensorInfo.sensorInterface,
Tom Joseph295f17e2017-09-07 00:09:46 +0530163 sensorInfo.sensorPath);
164
165 auto propValue = ipmi::getDbusProperty(
Patrick Venture0b02be92018-08-31 11:55:55 -0700166 bus, service, sensorInfo.sensorPath,
167 sensorInfo.propertyInterfaces.begin()->first,
168 sensorInfo.propertyInterfaces.begin()->second.begin()->first);
Tom Joseph295f17e2017-09-07 00:09:46 +0530169
Sui Chen4cc42552019-09-11 10:28:35 -0700170 setAssertionBytes(static_cast<uint16_t>(std::get<T>(propValue)), &response);
Tom Joseph295f17e2017-09-07 00:09:46 +0530171
172 return response;
173}
174
Tom Josephe05b2922017-09-07 00:43:16 +0530175/** @brief Map the Dbus info to the reading field in the Get sensor reading
176 * command response
177 *
178 * @tparam T - type of the dbus property related to sensor.
179 * @param[in] sensorInfo - Dbus info related to sensor.
180 *
181 * @return Response for get sensor reading command.
182 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700183template <typename T>
Tom Josephe05b2922017-09-07 00:43:16 +0530184GetSensorResponse readingData(const Info& sensorInfo)
185{
186 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Tom Josephe05b2922017-09-07 00:43:16 +0530187
Sui Chen4cc42552019-09-11 10:28:35 -0700188 GetSensorResponse response{};
189
190 enableScanning(&response);
Tom Josephe05b2922017-09-07 00:43:16 +0530191
Patrick Venture0b02be92018-08-31 11:55:55 -0700192 auto service = ipmi::getService(bus, sensorInfo.sensorInterface,
Tom Josephe05b2922017-09-07 00:43:16 +0530193 sensorInfo.sensorPath);
194
Brandon Kim9cf85622019-06-19 12:05:08 -0700195#ifdef UPDATE_FUNCTIONAL_ON_FAIL
196 // Check the OperationalStatus interface for functional property
197 if (sensorInfo.propertyInterfaces.begin()->first ==
198 "xyz.openbmc_project.Sensor.Value")
199 {
200 bool functional = true;
201 try
202 {
203 auto funcValue = ipmi::getDbusProperty(
204 bus, service, sensorInfo.sensorPath,
205 "xyz.openbmc_project.State.Decorator.OperationalStatus",
206 "Functional");
207 functional = std::get<bool>(funcValue);
208 }
209 catch (...)
210 {
211 // No-op if Functional property could not be found since this
212 // check is only valid for Sensor.Value read for hwmonio
213 }
214 if (!functional)
215 {
216 throw SensorFunctionalError();
217 }
218 }
219#endif
220
Tom Josephe05b2922017-09-07 00:43:16 +0530221 auto propValue = ipmi::getDbusProperty(
Patrick Venture0b02be92018-08-31 11:55:55 -0700222 bus, service, sensorInfo.sensorPath,
223 sensorInfo.propertyInterfaces.begin()->first,
224 sensorInfo.propertyInterfaces.begin()->second.begin()->first);
Tom Josephe05b2922017-09-07 00:43:16 +0530225
Vernon Maueryf442e112019-04-09 11:44:36 -0700226 double value = std::get<T>(propValue) *
Patrick Venture586d35b2018-09-07 19:56:18 -0700227 std::pow(10, sensorInfo.scale - sensorInfo.exponentR);
Tom Josephe05b2922017-09-07 00:43:16 +0530228
Patrick Venture0b02be92018-08-31 11:55:55 -0700229 auto rawData = static_cast<uint8_t>((value - sensorInfo.scaledOffset) /
230 sensorInfo.coefficientM);
Sui Chen4cc42552019-09-11 10:28:35 -0700231 setReading(rawData, &response);
Tom Josephe05b2922017-09-07 00:43:16 +0530232
Konstantin Aladyshevf93b29c2021-05-05 14:49:14 +0300233 if (!std::isfinite(value))
234 {
235 response.readingOrStateUnavailable = 1;
236 }
237
Tom Josephe05b2922017-09-07 00:43:16 +0530238 return response;
239}
240
Patrick Venture0b02be92018-08-31 11:55:55 -0700241} // namespace get
Tom Joseph816e92b2017-09-06 19:23:00 +0530242
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500243namespace set
244{
245
246/** @brief Make a DBus message for a Dbus call
247 * @param[in] updateInterface - Interface name
248 * @param[in] sensorPath - Path of the sensor
249 * @param[in] command - command to be executed
250 * @param[in] sensorInterface - DBus interface of sensor
251 * @return a dbus message
252 */
253IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
254 const std::string& sensorPath,
255 const std::string& command,
256 const std::string& sensorInterface);
257
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500258/** @brief Update d-bus based on assertion type sensor data
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500259 * @param[in] cmdData - input sensor data
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500260 * @param[in] sensorInfo - sensor d-bus info
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500261 * @return a IPMI error code
262 */
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500263ipmi_ret_t assertion(const SetSensorReadingReq& cmdData,
264 const Info& sensorInfo);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500265
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500266/** @brief Update d-bus based on a reading assertion
267 * @tparam T - type of d-bus property mapping this sensor
268 * @param[in] cmdData - input sensor data
269 * @param[in] sensorInfo - sensor d-bus info
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500270 * @return a IPMI error code
271 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700272template <typename T>
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500273ipmi_ret_t readingAssertion(const SetSensorReadingReq& cmdData,
274 const Info& sensorInfo)
275{
Patrick Venture0b02be92018-08-31 11:55:55 -0700276 auto msg =
277 makeDbusMsg("org.freedesktop.DBus.Properties", sensorInfo.sensorPath,
278 "Set", sensorInfo.sensorInterface);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500279
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500280 const auto& interface = sensorInfo.propertyInterfaces.begin();
281 msg.append(interface->first);
282 for (const auto& property : interface->second)
283 {
284 msg.append(property.first);
Andrew Geissler6467ed22020-05-16 16:03:53 -0500285 std::variant<T> value = static_cast<T>((cmdData.assertOffset8_14 << 8) |
286 cmdData.assertOffset0_7);
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500287 msg.append(value);
288 }
289 return updateToDbus(msg);
290}
291
Emily Shaffercc941e12017-06-14 13:06:26 -0700292/** @brief Update d-bus based on a discrete reading
293 * @param[in] cmdData - input sensor data
294 * @param[in] sensorInfo - sensor d-bus info
295 * @return an IPMI error code
296 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700297template <typename T>
Emily Shaffercc941e12017-06-14 13:06:26 -0700298ipmi_ret_t readingData(const SetSensorReadingReq& cmdData,
299 const Info& sensorInfo)
300{
Patrick Venture0b02be92018-08-31 11:55:55 -0700301 T raw_value =
302 (sensorInfo.coefficientM * cmdData.reading) + sensorInfo.scaledOffset;
Tom Joseph22102152018-03-02 18:46:39 +0530303
Patrick Venture586d35b2018-09-07 19:56:18 -0700304 raw_value *= std::pow(10, sensorInfo.exponentR - sensorInfo.scale);
Tom Joseph22102152018-03-02 18:46:39 +0530305
Patrick Venture0b02be92018-08-31 11:55:55 -0700306 auto msg =
307 makeDbusMsg("org.freedesktop.DBus.Properties", sensorInfo.sensorPath,
308 "Set", sensorInfo.sensorInterface);
Emily Shaffercc941e12017-06-14 13:06:26 -0700309
310 const auto& interface = sensorInfo.propertyInterfaces.begin();
311 msg.append(interface->first);
312
Emily Shaffercc941e12017-06-14 13:06:26 -0700313 for (const auto& property : interface->second)
314 {
315 msg.append(property.first);
Vernon Mauery16b86932019-05-01 08:36:11 -0700316 std::variant<T> value = raw_value;
Emily Shaffercc941e12017-06-14 13:06:26 -0700317 msg.append(value);
318 }
319 return updateToDbus(msg);
320}
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500321
322/** @brief Update d-bus based on eventdata type sensor data
323 * @param[in] cmdData - input sensor data
324 * @param[in] sensorInfo - sensor d-bus info
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500325 * @return a IPMI error code
326 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700327ipmi_ret_t eventdata(const SetSensorReadingReq& cmdData, const Info& sensorInfo,
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500328 uint8_t data);
329
330/** @brief Update d-bus based on eventdata1 type sensor data
331 * @param[in] cmdData - input sensor data
332 * @param[in] sensorInfo - sensor d-bus info
333 * @return a IPMI error code
334 */
335inline ipmi_ret_t eventdata1(const SetSensorReadingReq& cmdData,
336 const Info& sensorInfo)
337{
338 return eventdata(cmdData, sensorInfo, cmdData.eventData1);
339}
340
341/** @brief Update d-bus based on eventdata2 type sensor data
342 * @param[in] cmdData - input sensor data
343 * @param[in] sensorInfo - sensor d-bus info
344 * @return a IPMI error code
345 */
346inline ipmi_ret_t eventdata2(const SetSensorReadingReq& cmdData,
347 const Info& sensorInfo)
348{
349 return eventdata(cmdData, sensorInfo, cmdData.eventData2);
350}
351
352/** @brief Update d-bus based on eventdata3 type sensor data
353 * @param[in] cmdData - input sensor data
354 * @param[in] sensorInfo - sensor d-bus info
355 * @return a IPMI error code
356 */
357inline ipmi_ret_t eventdata3(const SetSensorReadingReq& cmdData,
358 const Info& sensorInfo)
359{
360 return eventdata(cmdData, sensorInfo, cmdData.eventData3);
361}
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500362
Patrick Venture0b02be92018-08-31 11:55:55 -0700363} // namespace set
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500364
365namespace notify
366{
367
368/** @brief Make a DBus message for a Dbus call
369 * @param[in] updateInterface - Interface name
370 * @param[in] sensorPath - Path of the sensor
371 * @param[in] command - command to be executed
372 * @param[in] sensorInterface - DBus interface of sensor
373 * @return a dbus message
374 */
375IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
376 const std::string& sensorPath,
377 const std::string& command,
378 const std::string& sensorInterface);
379
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500380/** @brief Update d-bus based on assertion type sensor data
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500381 * @param[in] interfaceMap - sensor interface
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500382 * @param[in] cmdData - input sensor data
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500383 * @param[in] sensorInfo - sensor d-bus info
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500384 * @return a IPMI error code
385 */
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500386ipmi_ret_t assertion(const SetSensorReadingReq& cmdData,
387 const Info& sensorInfo);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500388
Patrick Venture0b02be92018-08-31 11:55:55 -0700389} // namespace notify
Tom Joseph816e92b2017-09-06 19:23:00 +0530390
391namespace inventory
392{
393
394namespace get
395{
396
397/**
398 * @brief Map the Dbus info to sensor's assertion status in the Get sensor
399 * reading command response.
400 *
401 * @param[in] sensorInfo - Dbus info related to sensor.
402 *
403 * @return Response for get sensor reading command.
404 */
405GetSensorResponse assertion(const Info& sensorInfo);
406
407} // namespace get
408
409} // namespace inventory
Patrick Venture0b02be92018-08-31 11:55:55 -0700410} // namespace sensor
411} // namespace ipmi