blob: d4f12512c7fd2a4a6290f7aef8dd662e91cb2817 [file] [log] [blame]
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -05001#include <bitset>
Vernon Mauery185b9f82018-07-20 10:52:36 -07002#if __has_include(<filesystem>)
3#include <filesystem>
4#elif __has_include(<experimental/filesystem>)
Tom Joseph816e92b2017-09-06 19:23:00 +05305#include <experimental/filesystem>
Patrick Venture0b02be92018-08-31 11:55:55 -07006namespace std
7{
8// splice experimental::filesystem into std
9namespace filesystem = std::experimental::filesystem;
10} // namespace std
Vernon Mauery185b9f82018-07-20 10:52:36 -070011#else
Patrick Venture0b02be92018-08-31 11:55:55 -070012#error filesystem not available
Vernon Mauery185b9f82018-07-20 10:52:36 -070013#endif
Patrick Venture0b02be92018-08-31 11:55:55 -070014#include "sensordatahandler.hpp"
15#include "types.hpp"
16#include "utils.hpp"
17
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050018#include <phosphor-logging/elog-errors.hpp>
19#include <phosphor-logging/log.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070020#include <xyz/openbmc_project/Common/error.hpp>
21
Tom Joseph816e92b2017-09-06 19:23:00 +053022#include "sensorhandler.h"
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050023
24namespace ipmi
25{
26namespace sensor
27{
28
29using namespace phosphor::logging;
30using InternalFailure =
31 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
32
33static constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
34static constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
35static constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
36
37/** @brief get the D-Bus service and service path
38 * @param[in] bus - The Dbus bus object
39 * @param[in] interface - interface to the service
40 * @param[in] path - interested path in the list of objects
41 * @return pair of service path and service
42 */
43ServicePath getServiceAndPath(sdbusplus::bus::bus& bus,
44 const std::string& interface,
45 const std::string& path)
46{
47 auto depth = 0;
Patrick Venture0b02be92018-08-31 11:55:55 -070048 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
49 MAPPER_INTERFACE, "GetSubTree");
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050050 mapperCall.append("/");
51 mapperCall.append(depth);
52 mapperCall.append(std::vector<Interface>({interface}));
53
54 auto mapperResponseMsg = bus.call(mapperCall);
55 if (mapperResponseMsg.is_method_error())
56 {
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -050057 log<level::ERR>("Mapper GetSubTree failed",
Joseph Reynolds510eb9c2018-05-30 11:51:28 -050058 entry("PATH=%s", path.c_str()),
59 entry("INTERFACE=%s", interface.c_str()));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050060 elog<InternalFailure>();
61 }
62
63 MapperResponseType mapperResponse;
64 mapperResponseMsg.read(mapperResponse);
65 if (mapperResponse.empty())
66 {
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -050067 log<level::ERR>("Invalid mapper response",
Joseph Reynolds510eb9c2018-05-30 11:51:28 -050068 entry("PATH=%s", path.c_str()),
69 entry("INTERFACE=%s", interface.c_str()));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050070 elog<InternalFailure>();
71 }
72
73 if (path.empty())
74 {
Patrick Venture0b02be92018-08-31 11:55:55 -070075 // Get the first one if the path is not in list.
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050076 return std::make_pair(mapperResponse.begin()->first,
77 mapperResponse.begin()->second.begin()->first);
78 }
79 const auto& iter = mapperResponse.find(path);
80 if (iter == mapperResponse.end())
81 {
Gunnar Millsc9fa69e2018-04-08 16:35:25 -050082 log<level::ERR>("Couldn't find D-Bus path",
Joseph Reynolds510eb9c2018-05-30 11:51:28 -050083 entry("PATH=%s", path.c_str()),
84 entry("INTERFACE=%s", interface.c_str()));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050085 elog<InternalFailure>();
86 }
87 return std::make_pair(iter->first, iter->second.begin()->first);
88}
89
90AssertionSet getAssertionSet(const SetSensorReadingReq& cmdData)
91{
92 Assertion assertionStates =
93 (static_cast<Assertion>(cmdData.assertOffset8_14)) << 8 |
94 cmdData.assertOffset0_7;
95 Deassertion deassertionStates =
96 (static_cast<Deassertion>(cmdData.deassertOffset8_14)) << 8 |
97 cmdData.deassertOffset0_7;
98 return std::make_pair(assertionStates, deassertionStates);
99}
100
101ipmi_ret_t updateToDbus(IpmiUpdateData& msg)
102{
103 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
104 try
105 {
106 auto serviceResponseMsg = bus.call(msg);
107 if (serviceResponseMsg.is_method_error())
108 {
109 log<level::ERR>("Error in D-Bus call");
110 return IPMI_CC_UNSPECIFIED_ERROR;
111 }
112 }
113 catch (InternalFailure& e)
114 {
115 commit<InternalFailure>();
116 return IPMI_CC_UNSPECIFIED_ERROR;
117 }
118 return IPMI_CC_OK;
119}
120
Tom Joseph816e92b2017-09-06 19:23:00 +0530121namespace get
122{
123
Tom Josephb0adbcd2018-01-24 11:51:29 +0530124SensorName nameParentLeaf(const Info& sensorInfo)
125{
126 const auto pos = sensorInfo.sensorPath.find_last_of('/');
127 const auto leaf = sensorInfo.sensorPath.substr(pos + 1);
128
129 const auto remaining = sensorInfo.sensorPath.substr(0, pos);
130
131 const auto parentPos = remaining.find_last_of('/');
132 auto parent = remaining.substr(parentPos + 1);
133
134 parent += "_" + leaf;
135 return parent;
136}
137
Tom Joseph816e92b2017-09-06 19:23:00 +0530138GetSensorResponse mapDbusToAssertion(const Info& sensorInfo,
139 const InstancePath& path,
140 const DbusInterface& interface)
141{
142 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Patrick Venture0b02be92018-08-31 11:55:55 -0700143 GetSensorResponse response{};
Tom Joseph816e92b2017-09-06 19:23:00 +0530144 auto responseData = reinterpret_cast<GetReadingResponse*>(response.data());
145
146 auto service = ipmi::getService(bus, interface, path);
147
148 const auto& interfaceList = sensorInfo.propertyInterfaces;
149
150 for (const auto& interface : interfaceList)
151 {
152 for (const auto& property : interface.second)
153 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700154 auto propValue = ipmi::getDbusProperty(
155 bus, service, path, interface.first, property.first);
Tom Joseph816e92b2017-09-06 19:23:00 +0530156
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500157 for (const auto& value : std::get<OffsetValueMap>(property.second))
Tom Joseph816e92b2017-09-06 19:23:00 +0530158 {
159 if (propValue == value.second.assert)
160 {
161 setOffset(value.first, responseData);
162 break;
163 }
Tom Joseph816e92b2017-09-06 19:23:00 +0530164 }
165 }
166 }
167
168 return response;
169}
170
171GetSensorResponse assertion(const Info& sensorInfo)
172{
Patrick Venture0b02be92018-08-31 11:55:55 -0700173 return mapDbusToAssertion(sensorInfo, sensorInfo.sensorPath,
Tom Joseph816e92b2017-09-06 19:23:00 +0530174 sensorInfo.sensorInterface);
175}
176
Tom Josephe4014fc2017-09-06 23:57:36 +0530177GetSensorResponse eventdata2(const Info& sensorInfo)
178{
179 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Patrick Venture0b02be92018-08-31 11:55:55 -0700180 GetSensorResponse response{};
Tom Josephe4014fc2017-09-06 23:57:36 +0530181 auto responseData = reinterpret_cast<GetReadingResponse*>(response.data());
182
Patrick Venture0b02be92018-08-31 11:55:55 -0700183 auto service = ipmi::getService(bus, sensorInfo.sensorInterface,
Tom Josephe4014fc2017-09-06 23:57:36 +0530184 sensorInfo.sensorPath);
185
186 const auto& interfaceList = sensorInfo.propertyInterfaces;
187
188 for (const auto& interface : interfaceList)
189 {
190 for (const auto& property : interface.second)
191 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700192 auto propValue =
193 ipmi::getDbusProperty(bus, service, sensorInfo.sensorPath,
194 interface.first, property.first);
Tom Josephe4014fc2017-09-06 23:57:36 +0530195
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500196 for (const auto& value : std::get<OffsetValueMap>(property.second))
Tom Josephe4014fc2017-09-06 23:57:36 +0530197 {
198 if (propValue == value.second.assert)
199 {
200 setReading(value.first, responseData);
201 break;
202 }
203 }
204 }
205 }
206
207 return response;
208}
209
Patrick Venture0b02be92018-08-31 11:55:55 -0700210} // namespace get
Tom Joseph816e92b2017-09-06 19:23:00 +0530211
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500212namespace set
213{
214
215IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
216 const std::string& sensorPath,
217 const std::string& command,
218 const std::string& sensorInterface)
219{
220 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
221 using namespace std::string_literals;
222
Patrick Venture0b02be92018-08-31 11:55:55 -0700223 auto dbusService = getService(bus, sensorInterface, sensorPath);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500224
Patrick Venture0b02be92018-08-31 11:55:55 -0700225 return bus.new_method_call(dbusService.c_str(), sensorPath.c_str(),
226 updateInterface.c_str(), command.c_str());
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500227}
228
Patrick Venture0b02be92018-08-31 11:55:55 -0700229ipmi_ret_t eventdata(const SetSensorReadingReq& cmdData, const Info& sensorInfo,
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500230 uint8_t data)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500231{
Patrick Venture0b02be92018-08-31 11:55:55 -0700232 auto msg =
233 makeDbusMsg("org.freedesktop.DBus.Properties", sensorInfo.sensorPath,
234 "Set", sensorInfo.sensorInterface);
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500235
236 const auto& interface = sensorInfo.propertyInterfaces.begin();
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500237 msg.append(interface->first);
238 for (const auto& property : interface->second)
239 {
240 msg.append(property.first);
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500241 const auto& iter = std::get<OffsetValueMap>(property.second).find(data);
242 if (iter == std::get<OffsetValueMap>(property.second).end())
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500243 {
244 log<level::ERR>("Invalid event data");
245 return IPMI_CC_PARM_OUT_OF_RANGE;
246 }
247 msg.append(iter->second.assert);
248 }
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500249 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500250}
251
Patrick Venture0b02be92018-08-31 11:55:55 -0700252ipmi_ret_t assertion(const SetSensorReadingReq& cmdData, const Info& sensorInfo)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500253{
Brad Bishop06a0abf2018-02-26 20:46:00 -0500254 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
255 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
256 auto bothSet = assertionSet ^ deassertionSet;
257
258 const auto& interface = sensorInfo.propertyInterfaces.begin();
259
260 for (const auto& property : interface->second)
261 {
262 Value tmp{mapbox::util::no_init()};
263 for (const auto& value : std::get<OffsetValueMap>(property.second))
264 {
265 if (bothSet.size() <= value.first || !bothSet.test(value.first))
266 {
267 // A BIOS shouldn't do this but ignore if they do.
268 continue;
269 }
270
271 if (assertionSet.test(value.first))
272 {
273 tmp = value.second.assert;
274 break;
275 }
276 if (deassertionSet.test(value.first))
277 {
278 tmp = value.second.deassert;
279 break;
280 }
281 }
282
283 if (tmp.valid())
284 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700285 auto msg = makeDbusMsg("org.freedesktop.DBus.Properties",
286 sensorInfo.sensorPath, "Set",
287 sensorInfo.sensorInterface);
Brad Bishop06a0abf2018-02-26 20:46:00 -0500288 msg.append(interface->first);
289 msg.append(property.first);
290 msg.append(tmp);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500291
Brad Bishop06a0abf2018-02-26 20:46:00 -0500292 auto rc = updateToDbus(msg);
293 if (rc)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500294 {
Brad Bishop06a0abf2018-02-26 20:46:00 -0500295 return rc;
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500296 }
297 }
298 }
Brad Bishop06a0abf2018-02-26 20:46:00 -0500299
300 return IPMI_CC_OK;
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500301}
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500302
Patrick Venture0b02be92018-08-31 11:55:55 -0700303} // namespace set
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500304
305namespace notify
306{
307
308IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
309 const std::string& sensorPath,
310 const std::string& command,
311 const std::string& sensorInterface)
312{
313 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
314 using namespace std::string_literals;
315
Dhruvaraj Subhashchandranf915f852017-09-14 07:01:48 -0500316 static const auto dbusPath = "/xyz/openbmc_project/inventory"s;
317 std::string dbusService = ipmi::getService(bus, updateInterface, dbusPath);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500318
Patrick Venture0b02be92018-08-31 11:55:55 -0700319 return bus.new_method_call(dbusService.c_str(), dbusPath.c_str(),
320 updateInterface.c_str(), command.c_str());
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500321}
322
Patrick Venture0b02be92018-08-31 11:55:55 -0700323ipmi_ret_t assertion(const SetSensorReadingReq& cmdData, const Info& sensorInfo)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500324{
Patrick Venture0b02be92018-08-31 11:55:55 -0700325 auto msg = makeDbusMsg(sensorInfo.sensorInterface, sensorInfo.sensorPath,
326 "Notify", sensorInfo.sensorInterface);
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500327
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500328 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
329 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
330 ipmi::sensor::ObjectMap objects;
331 ipmi::sensor::InterfaceMap interfaces;
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500332 for (const auto& interface : sensorInfo.propertyInterfaces)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500333 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700334 // For a property like functional state the result will be
335 // calculated based on the true value of all conditions.
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500336 for (const auto& property : interface.second)
337 {
338 ipmi::sensor::PropertyMap props;
339 bool valid = false;
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500340 auto result = true;
341 for (const auto& value : std::get<OffsetValueMap>(property.second))
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500342 {
343 if (assertionSet.test(value.first))
344 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700345 // Skip update if skipOn is ASSERT
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500346 if (SkipAssertion::ASSERT == value.second.skip)
347 {
348 return IPMI_CC_OK;
349 }
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500350 result = result && value.second.assert.get<bool>();
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500351 valid = true;
352 }
353 else if (deassertionSet.test(value.first))
354 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700355 // Skip update if skipOn is DEASSERT
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500356 if (SkipAssertion::DEASSERT == value.second.skip)
357 {
358 return IPMI_CC_OK;
359 }
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500360 result = result && value.second.deassert.get<bool>();
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500361 valid = true;
362 }
363 }
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500364 for (const auto& value :
Patrick Venture0b02be92018-08-31 11:55:55 -0700365 std::get<PreReqOffsetValueMap>(property.second))
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500366 {
367 if (assertionSet.test(value.first))
368 {
369 result = result && value.second.assert.get<bool>();
370 }
371 else if (deassertionSet.test(value.first))
372 {
373 result = result && value.second.deassert.get<bool>();
374 }
375 }
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500376 if (valid)
377 {
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500378 props.emplace(property.first, result);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500379 interfaces.emplace(interface.first, std::move(props));
380 }
381 }
382 }
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500383
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500384 objects.emplace(sensorInfo.sensorPath, std::move(interfaces));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500385 msg.append(std::move(objects));
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500386 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500387}
Tom Joseph816e92b2017-09-06 19:23:00 +0530388
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
397GetSensorResponse assertion(const Info& sensorInfo)
398{
Vernon Mauery185b9f82018-07-20 10:52:36 -0700399 namespace fs = std::filesystem;
Tom Joseph816e92b2017-09-06 19:23:00 +0530400
401 fs::path path{ipmi::sensor::inventoryRoot};
402 path += sensorInfo.sensorPath;
403
404 return ipmi::sensor::get::mapDbusToAssertion(
Patrick Venture0b02be92018-08-31 11:55:55 -0700405 sensorInfo, path.string(),
406 sensorInfo.propertyInterfaces.begin()->first);
Tom Joseph816e92b2017-09-06 19:23:00 +0530407}
408
Patrick Venture0b02be92018-08-31 11:55:55 -0700409} // namespace get
Tom Joseph816e92b2017-09-06 19:23:00 +0530410
411} // namespace inventory
Patrick Venture0b02be92018-08-31 11:55:55 -0700412} // namespace sensor
413} // namespace ipmi