blob: 45e38351322d48cf71bb40d7d8d7d0eebdef53e9 [file] [log] [blame]
Patrick Venture3a5071a2018-09-12 13:27:42 -07001#include "sensordatahandler.hpp"
2
3#include "sensorhandler.hpp"
Patrick Venture3a5071a2018-09-12 13:27:42 -07004
Vernon Mauery33250242019-03-12 16:49:26 -07005#include <ipmid/types.hpp>
Vernon Mauery6a98fe72019-03-11 15:57:48 -07006#include <ipmid/utils.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -07007#include <sdbusplus/message/types.hpp>
Patrick Venture3a5071a2018-09-12 13:27:42 -07008#include <xyz/openbmc_project/Common/error.hpp>
9
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050010#include <bitset>
11#include <filesystem>
12#include <optional>
13
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050014namespace ipmi
15{
16namespace sensor
17{
18
19using namespace phosphor::logging;
20using InternalFailure =
Willy Tu523e2d12023-09-05 11:36:48 -070021 sdbusplus::error::xyz::openbmc_project::common::InternalFailure;
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050022
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050023AssertionSet getAssertionSet(const SetSensorReadingReq& cmdData)
24{
25 Assertion assertionStates =
26 (static_cast<Assertion>(cmdData.assertOffset8_14)) << 8 |
27 cmdData.assertOffset0_7;
28 Deassertion deassertionStates =
29 (static_cast<Deassertion>(cmdData.deassertOffset8_14)) << 8 |
30 cmdData.deassertOffset0_7;
31 return std::make_pair(assertionStates, deassertionStates);
32}
33
34ipmi_ret_t updateToDbus(IpmiUpdateData& msg)
35{
Patrick Williams5d82f472022-07-22 19:26:53 -050036 sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050037 try
38 {
39 auto serviceResponseMsg = bus.call(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050040 }
Patrick Williamsa2ad2da2021-10-06 12:21:46 -050041 catch (const InternalFailure& e)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050042 {
George Liu9b745a82024-07-19 09:09:36 +080043 lg2::error("Error in D-Bus call: {ERROR}", "ERROR", e);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050044 commit<InternalFailure>();
45 return IPMI_CC_UNSPECIFIED_ERROR;
46 }
47 return IPMI_CC_OK;
48}
49
Tom Joseph816e92b2017-09-06 19:23:00 +053050namespace get
51{
52
Tom Josephb0adbcd2018-01-24 11:51:29 +053053SensorName nameParentLeaf(const Info& sensorInfo)
54{
55 const auto pos = sensorInfo.sensorPath.find_last_of('/');
56 const auto leaf = sensorInfo.sensorPath.substr(pos + 1);
57
58 const auto remaining = sensorInfo.sensorPath.substr(0, pos);
59
60 const auto parentPos = remaining.find_last_of('/');
61 auto parent = remaining.substr(parentPos + 1);
62
63 parent += "_" + leaf;
64 return parent;
65}
66
Tom Joseph816e92b2017-09-06 19:23:00 +053067GetSensorResponse mapDbusToAssertion(const Info& sensorInfo,
68 const InstancePath& path,
69 const DbusInterface& interface)
70{
Patrick Williams5d82f472022-07-22 19:26:53 -050071 sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
Patrick Venture0b02be92018-08-31 11:55:55 -070072 GetSensorResponse response{};
Tom Joseph816e92b2017-09-06 19:23:00 +053073
Jeremy Kerr3dc35582020-05-17 15:47:07 +080074 enableScanning(&response);
75
Tom Joseph816e92b2017-09-06 19:23:00 +053076 auto service = ipmi::getService(bus, interface, path);
77
78 const auto& interfaceList = sensorInfo.propertyInterfaces;
79
80 for (const auto& interface : interfaceList)
81 {
82 for (const auto& property : interface.second)
83 {
Patrick Venture0b02be92018-08-31 11:55:55 -070084 auto propValue = ipmi::getDbusProperty(
85 bus, service, path, interface.first, property.first);
Tom Joseph816e92b2017-09-06 19:23:00 +053086
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -050087 for (const auto& value : std::get<OffsetValueMap>(property.second))
Tom Joseph816e92b2017-09-06 19:23:00 +053088 {
89 if (propValue == value.second.assert)
90 {
Sui Chen4cc42552019-09-11 10:28:35 -070091 setOffset(value.first, &response);
Tom Joseph816e92b2017-09-06 19:23:00 +053092 break;
93 }
Tom Joseph816e92b2017-09-06 19:23:00 +053094 }
95 }
96 }
97
98 return response;
99}
100
Lei YUa8dc09b2021-10-13 18:06:46 +0800101GetSensorResponse mapDbusToEventdata2(const Info& sensorInfo)
Tom Josephe4014fc2017-09-06 23:57:36 +0530102{
Patrick Williams5d82f472022-07-22 19:26:53 -0500103 sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
Patrick Venture0b02be92018-08-31 11:55:55 -0700104 GetSensorResponse response{};
Tom Josephe4014fc2017-09-06 23:57:36 +0530105
Jeremy Kerr3dc35582020-05-17 15:47:07 +0800106 enableScanning(&response);
107
Patrick Venture0b02be92018-08-31 11:55:55 -0700108 auto service = ipmi::getService(bus, sensorInfo.sensorInterface,
Tom Josephe4014fc2017-09-06 23:57:36 +0530109 sensorInfo.sensorPath);
110
111 const auto& interfaceList = sensorInfo.propertyInterfaces;
112
113 for (const auto& interface : interfaceList)
114 {
115 for (const auto& property : interface.second)
116 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700117 auto propValue =
118 ipmi::getDbusProperty(bus, service, sensorInfo.sensorPath,
119 interface.first, property.first);
Tom Josephe4014fc2017-09-06 23:57:36 +0530120
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500121 for (const auto& value : std::get<OffsetValueMap>(property.second))
Tom Josephe4014fc2017-09-06 23:57:36 +0530122 {
123 if (propValue == value.second.assert)
124 {
Sui Chen4cc42552019-09-11 10:28:35 -0700125 setReading(value.first, &response);
Tom Josephe4014fc2017-09-06 23:57:36 +0530126 break;
127 }
128 }
129 }
130 }
131
132 return response;
133}
Lei YUa8dc09b2021-10-13 18:06:46 +0800134
135#ifndef FEATURE_SENSORS_CACHE
136GetSensorResponse assertion(const Info& sensorInfo)
137{
138 return mapDbusToAssertion(sensorInfo, sensorInfo.sensorPath,
139 sensorInfo.sensorInterface);
140}
141
142GetSensorResponse eventdata2(const Info& sensorInfo)
143{
144 return mapDbusToEventdata2(sensorInfo);
145}
Lei YU8c2c0482021-09-16 17:28:28 +0800146#else
147std::optional<GetSensorResponse> assertion(uint8_t id, const Info& sensorInfo,
Lei YU8e8152c2021-12-06 20:11:08 +0800148 const PropertyMap& /*properties*/)
Lei YU8c2c0482021-09-16 17:28:28 +0800149{
Lei YUef960c02021-10-13 17:54:59 +0800150 // The assertion may contain multiple properties
151 // So we have to get the properties from DBus anyway
152 auto response = mapDbusToAssertion(sensorInfo, sensorInfo.sensorPath,
153 sensorInfo.sensorInterface);
154
155 if (!sensorCacheMap[id].has_value())
156 {
157 sensorCacheMap[id] = SensorData{};
158 }
159 sensorCacheMap[id]->response = response;
160 return response;
Lei YU8c2c0482021-09-16 17:28:28 +0800161}
162
163std::optional<GetSensorResponse> eventdata2(uint8_t id, const Info& sensorInfo,
Lei YU8e8152c2021-12-06 20:11:08 +0800164 const PropertyMap& /*properties*/)
Lei YU8c2c0482021-09-16 17:28:28 +0800165{
Lei YUa8dc09b2021-10-13 18:06:46 +0800166 // The eventdata2 may contain multiple properties
167 // So we have to get the properties from DBus anyway
168 auto response = mapDbusToEventdata2(sensorInfo);
169
170 if (!sensorCacheMap[id].has_value())
171 {
172 sensorCacheMap[id] = SensorData{};
173 }
174 sensorCacheMap[id]->response = response;
175 return response;
Lei YU8c2c0482021-09-16 17:28:28 +0800176}
177
178#endif // FEATURE_SENSORS_CACHE
Tom Josephe4014fc2017-09-06 23:57:36 +0530179
Patrick Venture0b02be92018-08-31 11:55:55 -0700180} // namespace get
Tom Joseph816e92b2017-09-06 19:23:00 +0530181
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500182namespace set
183{
184
185IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
186 const std::string& sensorPath,
187 const std::string& command,
188 const std::string& sensorInterface)
189{
Patrick Williams5d82f472022-07-22 19:26:53 -0500190 sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500191 using namespace std::string_literals;
192
Patrick Venture0b02be92018-08-31 11:55:55 -0700193 auto dbusService = getService(bus, sensorInterface, sensorPath);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500194
Patrick Venture0b02be92018-08-31 11:55:55 -0700195 return bus.new_method_call(dbusService.c_str(), sensorPath.c_str(),
196 updateInterface.c_str(), command.c_str());
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500197}
198
Willy Tu11d68892022-01-20 10:37:34 -0800199ipmi_ret_t eventdata(const SetSensorReadingReq&, const Info& sensorInfo,
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500200 uint8_t data)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500201{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500202 auto msg = makeDbusMsg("org.freedesktop.DBus.Properties",
203 sensorInfo.sensorPath, "Set",
204 sensorInfo.sensorInterface);
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500205
206 const auto& interface = sensorInfo.propertyInterfaces.begin();
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500207 msg.append(interface->first);
208 for (const auto& property : interface->second)
209 {
210 msg.append(property.first);
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500211 const auto& iter = std::get<OffsetValueMap>(property.second).find(data);
212 if (iter == std::get<OffsetValueMap>(property.second).end())
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500213 {
George Liu9b745a82024-07-19 09:09:36 +0800214 lg2::error("Invalid event data");
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500215 return IPMI_CC_PARM_OUT_OF_RANGE;
216 }
217 msg.append(iter->second.assert);
218 }
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500219 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500220}
221
Patrick Venture0b02be92018-08-31 11:55:55 -0700222ipmi_ret_t assertion(const SetSensorReadingReq& cmdData, const Info& sensorInfo)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500223{
Brad Bishop06a0abf2018-02-26 20:46:00 -0500224 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
225 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
226 auto bothSet = assertionSet ^ deassertionSet;
227
228 const auto& interface = sensorInfo.propertyInterfaces.begin();
229
230 for (const auto& property : interface->second)
231 {
William A. Kennington III4c008022018-10-12 17:18:14 -0700232 std::optional<Value> tmp;
Brad Bishop06a0abf2018-02-26 20:46:00 -0500233 for (const auto& value : std::get<OffsetValueMap>(property.second))
234 {
235 if (bothSet.size() <= value.first || !bothSet.test(value.first))
236 {
237 // A BIOS shouldn't do this but ignore if they do.
238 continue;
239 }
240
241 if (assertionSet.test(value.first))
242 {
243 tmp = value.second.assert;
244 break;
245 }
246 if (deassertionSet.test(value.first))
247 {
248 tmp = value.second.deassert;
249 break;
250 }
251 }
252
William A. Kennington III4c008022018-10-12 17:18:14 -0700253 if (tmp)
Brad Bishop06a0abf2018-02-26 20:46:00 -0500254 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700255 auto msg = makeDbusMsg("org.freedesktop.DBus.Properties",
256 sensorInfo.sensorPath, "Set",
257 sensorInfo.sensorInterface);
Brad Bishop06a0abf2018-02-26 20:46:00 -0500258 msg.append(interface->first);
259 msg.append(property.first);
William A. Kennington III4c008022018-10-12 17:18:14 -0700260 msg.append(*tmp);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500261
Brad Bishop06a0abf2018-02-26 20:46:00 -0500262 auto rc = updateToDbus(msg);
263 if (rc)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500264 {
Brad Bishop06a0abf2018-02-26 20:46:00 -0500265 return rc;
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500266 }
267 }
268 }
Brad Bishop06a0abf2018-02-26 20:46:00 -0500269
270 return IPMI_CC_OK;
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500271}
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500272
Patrick Venture0b02be92018-08-31 11:55:55 -0700273} // namespace set
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500274
275namespace notify
276{
277
278IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
Willy Tu11d68892022-01-20 10:37:34 -0800279 const std::string&, const std::string& command,
280 const std::string&)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500281{
Patrick Williams5d82f472022-07-22 19:26:53 -0500282 sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500283 using namespace std::string_literals;
284
Dhruvaraj Subhashchandranf915f852017-09-14 07:01:48 -0500285 static const auto dbusPath = "/xyz/openbmc_project/inventory"s;
286 std::string dbusService = ipmi::getService(bus, updateInterface, dbusPath);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500287
Patrick Venture0b02be92018-08-31 11:55:55 -0700288 return bus.new_method_call(dbusService.c_str(), dbusPath.c_str(),
289 updateInterface.c_str(), command.c_str());
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500290}
291
Patrick Venture0b02be92018-08-31 11:55:55 -0700292ipmi_ret_t assertion(const SetSensorReadingReq& cmdData, const Info& sensorInfo)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500293{
Patrick Venture0b02be92018-08-31 11:55:55 -0700294 auto msg = makeDbusMsg(sensorInfo.sensorInterface, sensorInfo.sensorPath,
295 "Notify", sensorInfo.sensorInterface);
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500296
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500297 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
298 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
299 ipmi::sensor::ObjectMap objects;
300 ipmi::sensor::InterfaceMap interfaces;
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500301 for (const auto& interface : sensorInfo.propertyInterfaces)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500302 {
Santosh Puranikbbf8bd62019-05-01 19:02:52 +0530303 // An interface with no properties - It is possible that the sensor
304 // object on DBUS implements a DBUS interface with no properties.
305 // Make sure we add the interface to the list if interfaces on the
306 // object with an empty property map.
307 if (interface.second.empty())
308 {
309 interfaces.emplace(interface.first, ipmi::sensor::PropertyMap{});
310 continue;
311 }
Patrick Venture0b02be92018-08-31 11:55:55 -0700312 // For a property like functional state the result will be
313 // calculated based on the true value of all conditions.
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500314 for (const auto& property : interface.second)
315 {
316 ipmi::sensor::PropertyMap props;
317 bool valid = false;
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500318 auto result = true;
319 for (const auto& value : std::get<OffsetValueMap>(property.second))
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500320 {
321 if (assertionSet.test(value.first))
322 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700323 // Skip update if skipOn is ASSERT
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500324 if (SkipAssertion::ASSERT == value.second.skip)
325 {
326 return IPMI_CC_OK;
327 }
Vernon Maueryf442e112019-04-09 11:44:36 -0700328 result = result && std::get<bool>(value.second.assert);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500329 valid = true;
330 }
331 else if (deassertionSet.test(value.first))
332 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700333 // Skip update if skipOn is DEASSERT
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500334 if (SkipAssertion::DEASSERT == value.second.skip)
335 {
336 return IPMI_CC_OK;
337 }
Vernon Maueryf442e112019-04-09 11:44:36 -0700338 result = result && std::get<bool>(value.second.deassert);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500339 valid = true;
340 }
341 }
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500342 for (const auto& value :
Patrick Venture0b02be92018-08-31 11:55:55 -0700343 std::get<PreReqOffsetValueMap>(property.second))
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500344 {
345 if (assertionSet.test(value.first))
346 {
Vernon Maueryf442e112019-04-09 11:44:36 -0700347 result = result && std::get<bool>(value.second.assert);
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500348 }
349 else if (deassertionSet.test(value.first))
350 {
Vernon Maueryf442e112019-04-09 11:44:36 -0700351 result = result && std::get<bool>(value.second.deassert);
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500352 }
353 }
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500354 if (valid)
355 {
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500356 props.emplace(property.first, result);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500357 interfaces.emplace(interface.first, std::move(props));
358 }
359 }
360 }
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500361
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500362 objects.emplace(sensorInfo.sensorPath, std::move(interfaces));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500363 msg.append(std::move(objects));
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500364 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500365}
Tom Joseph816e92b2017-09-06 19:23:00 +0530366
Patrick Venture0b02be92018-08-31 11:55:55 -0700367} // namespace notify
Tom Joseph816e92b2017-09-06 19:23:00 +0530368
369namespace inventory
370{
371
372namespace get
373{
374
Lei YUff8c9b42021-10-15 14:20:57 +0800375#ifndef FEATURE_SENSORS_CACHE
376
Tom Joseph816e92b2017-09-06 19:23:00 +0530377GetSensorResponse assertion(const Info& sensorInfo)
378{
Vernon Mauery185b9f82018-07-20 10:52:36 -0700379 namespace fs = std::filesystem;
Tom Joseph816e92b2017-09-06 19:23:00 +0530380
381 fs::path path{ipmi::sensor::inventoryRoot};
382 path += sensorInfo.sensorPath;
383
384 return ipmi::sensor::get::mapDbusToAssertion(
Patrick Venture0b02be92018-08-31 11:55:55 -0700385 sensorInfo, path.string(),
386 sensorInfo.propertyInterfaces.begin()->first);
Tom Joseph816e92b2017-09-06 19:23:00 +0530387}
388
Lei YUff8c9b42021-10-15 14:20:57 +0800389#else
390
391std::optional<GetSensorResponse> assertion(uint8_t id, const Info& sensorInfo,
Lei YU8e8152c2021-12-06 20:11:08 +0800392 const PropertyMap& /*properties*/)
Lei YUff8c9b42021-10-15 14:20:57 +0800393{
Lei YUff8c9b42021-10-15 14:20:57 +0800394 // The assertion may contain multiple properties
395 // So we have to get the properties from DBus anyway
396 namespace fs = std::filesystem;
397
398 fs::path path{ipmi::sensor::inventoryRoot};
399 path += sensorInfo.sensorPath;
400
401 auto response = ipmi::sensor::get::mapDbusToAssertion(
402 sensorInfo, path.string(),
403 sensorInfo.propertyInterfaces.begin()->first);
404
405 if (!sensorCacheMap[id].has_value())
406 {
407 sensorCacheMap[id] = SensorData{};
408 }
409 sensorCacheMap[id]->response = response;
410 return response;
411}
412
413#endif
414
Patrick Venture0b02be92018-08-31 11:55:55 -0700415} // namespace get
Tom Joseph816e92b2017-09-06 19:23:00 +0530416
417} // namespace inventory
Patrick Venture0b02be92018-08-31 11:55:55 -0700418} // namespace sensor
419} // namespace ipmi