blob: 4f552a3383383bcdcc2f48d7ee057fee80257bf1 [file] [log] [blame]
Patrick Venture3a5071a2018-09-12 13:27:42 -07001#include "sensordatahandler.hpp"
2
3#include "sensorhandler.hpp"
4#include "types.hpp"
5#include "utils.hpp"
6
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -05007#include <bitset>
William A. Kennington III4c008022018-10-12 17:18:14 -07008#include <optional>
Patrick Venture3a5071a2018-09-12 13:27:42 -07009#include <phosphor-logging/elog-errors.hpp>
10#include <phosphor-logging/log.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070011#include <sdbusplus/message/types.hpp>
Patrick Venture3a5071a2018-09-12 13:27:42 -070012#include <xyz/openbmc_project/Common/error.hpp>
13
Vernon Mauery185b9f82018-07-20 10:52:36 -070014#if __has_include(<filesystem>)
15#include <filesystem>
16#elif __has_include(<experimental/filesystem>)
Tom Joseph816e92b2017-09-06 19:23:00 +053017#include <experimental/filesystem>
Patrick Venture0b02be92018-08-31 11:55:55 -070018namespace std
19{
20// splice experimental::filesystem into std
21namespace filesystem = std::experimental::filesystem;
22} // namespace std
Vernon Mauery185b9f82018-07-20 10:52:36 -070023#else
Patrick Venture0b02be92018-08-31 11:55:55 -070024#error filesystem not available
Vernon Mauery185b9f82018-07-20 10:52:36 -070025#endif
Patrick Venture0b02be92018-08-31 11:55:55 -070026
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050027namespace ipmi
28{
29namespace sensor
30{
31
William A. Kennington III4c008022018-10-12 17:18:14 -070032namespace variant_ns = sdbusplus::message::variant_ns;
33
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050034using namespace phosphor::logging;
35using InternalFailure =
36 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
37
38static constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
39static constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
40static constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
41
42/** @brief get the D-Bus service and service path
43 * @param[in] bus - The Dbus bus object
44 * @param[in] interface - interface to the service
45 * @param[in] path - interested path in the list of objects
46 * @return pair of service path and service
47 */
48ServicePath getServiceAndPath(sdbusplus::bus::bus& bus,
49 const std::string& interface,
50 const std::string& path)
51{
52 auto depth = 0;
Patrick Venture0b02be92018-08-31 11:55:55 -070053 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
54 MAPPER_INTERFACE, "GetSubTree");
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050055 mapperCall.append("/");
56 mapperCall.append(depth);
57 mapperCall.append(std::vector<Interface>({interface}));
58
59 auto mapperResponseMsg = bus.call(mapperCall);
60 if (mapperResponseMsg.is_method_error())
61 {
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -050062 log<level::ERR>("Mapper GetSubTree failed",
Joseph Reynolds510eb9c2018-05-30 11:51:28 -050063 entry("PATH=%s", path.c_str()),
64 entry("INTERFACE=%s", interface.c_str()));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050065 elog<InternalFailure>();
66 }
67
68 MapperResponseType mapperResponse;
69 mapperResponseMsg.read(mapperResponse);
70 if (mapperResponse.empty())
71 {
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -050072 log<level::ERR>("Invalid mapper response",
Joseph Reynolds510eb9c2018-05-30 11:51:28 -050073 entry("PATH=%s", path.c_str()),
74 entry("INTERFACE=%s", interface.c_str()));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050075 elog<InternalFailure>();
76 }
77
78 if (path.empty())
79 {
Patrick Venture0b02be92018-08-31 11:55:55 -070080 // Get the first one if the path is not in list.
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050081 return std::make_pair(mapperResponse.begin()->first,
82 mapperResponse.begin()->second.begin()->first);
83 }
84 const auto& iter = mapperResponse.find(path);
85 if (iter == mapperResponse.end())
86 {
Gunnar Millsc9fa69e2018-04-08 16:35:25 -050087 log<level::ERR>("Couldn't find D-Bus path",
Joseph Reynolds510eb9c2018-05-30 11:51:28 -050088 entry("PATH=%s", path.c_str()),
89 entry("INTERFACE=%s", interface.c_str()));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050090 elog<InternalFailure>();
91 }
92 return std::make_pair(iter->first, iter->second.begin()->first);
93}
94
95AssertionSet getAssertionSet(const SetSensorReadingReq& cmdData)
96{
97 Assertion assertionStates =
98 (static_cast<Assertion>(cmdData.assertOffset8_14)) << 8 |
99 cmdData.assertOffset0_7;
100 Deassertion deassertionStates =
101 (static_cast<Deassertion>(cmdData.deassertOffset8_14)) << 8 |
102 cmdData.deassertOffset0_7;
103 return std::make_pair(assertionStates, deassertionStates);
104}
105
106ipmi_ret_t updateToDbus(IpmiUpdateData& msg)
107{
108 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
109 try
110 {
111 auto serviceResponseMsg = bus.call(msg);
112 if (serviceResponseMsg.is_method_error())
113 {
114 log<level::ERR>("Error in D-Bus call");
115 return IPMI_CC_UNSPECIFIED_ERROR;
116 }
117 }
118 catch (InternalFailure& e)
119 {
120 commit<InternalFailure>();
121 return IPMI_CC_UNSPECIFIED_ERROR;
122 }
123 return IPMI_CC_OK;
124}
125
Tom Joseph816e92b2017-09-06 19:23:00 +0530126namespace get
127{
128
Tom Josephb0adbcd2018-01-24 11:51:29 +0530129SensorName nameParentLeaf(const Info& sensorInfo)
130{
131 const auto pos = sensorInfo.sensorPath.find_last_of('/');
132 const auto leaf = sensorInfo.sensorPath.substr(pos + 1);
133
134 const auto remaining = sensorInfo.sensorPath.substr(0, pos);
135
136 const auto parentPos = remaining.find_last_of('/');
137 auto parent = remaining.substr(parentPos + 1);
138
139 parent += "_" + leaf;
140 return parent;
141}
142
Tom Joseph816e92b2017-09-06 19:23:00 +0530143GetSensorResponse mapDbusToAssertion(const Info& sensorInfo,
144 const InstancePath& path,
145 const DbusInterface& interface)
146{
147 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Patrick Venture0b02be92018-08-31 11:55:55 -0700148 GetSensorResponse response{};
Tom Joseph816e92b2017-09-06 19:23:00 +0530149 auto responseData = reinterpret_cast<GetReadingResponse*>(response.data());
150
151 auto service = ipmi::getService(bus, interface, path);
152
153 const auto& interfaceList = sensorInfo.propertyInterfaces;
154
155 for (const auto& interface : interfaceList)
156 {
157 for (const auto& property : interface.second)
158 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700159 auto propValue = ipmi::getDbusProperty(
160 bus, service, path, interface.first, property.first);
Tom Joseph816e92b2017-09-06 19:23:00 +0530161
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500162 for (const auto& value : std::get<OffsetValueMap>(property.second))
Tom Joseph816e92b2017-09-06 19:23:00 +0530163 {
164 if (propValue == value.second.assert)
165 {
166 setOffset(value.first, responseData);
167 break;
168 }
Tom Joseph816e92b2017-09-06 19:23:00 +0530169 }
170 }
171 }
172
173 return response;
174}
175
176GetSensorResponse assertion(const Info& sensorInfo)
177{
Patrick Venture0b02be92018-08-31 11:55:55 -0700178 return mapDbusToAssertion(sensorInfo, sensorInfo.sensorPath,
Tom Joseph816e92b2017-09-06 19:23:00 +0530179 sensorInfo.sensorInterface);
180}
181
Tom Josephe4014fc2017-09-06 23:57:36 +0530182GetSensorResponse eventdata2(const Info& sensorInfo)
183{
184 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Patrick Venture0b02be92018-08-31 11:55:55 -0700185 GetSensorResponse response{};
Tom Josephe4014fc2017-09-06 23:57:36 +0530186 auto responseData = reinterpret_cast<GetReadingResponse*>(response.data());
187
Patrick Venture0b02be92018-08-31 11:55:55 -0700188 auto service = ipmi::getService(bus, sensorInfo.sensorInterface,
Tom Josephe4014fc2017-09-06 23:57:36 +0530189 sensorInfo.sensorPath);
190
191 const auto& interfaceList = sensorInfo.propertyInterfaces;
192
193 for (const auto& interface : interfaceList)
194 {
195 for (const auto& property : interface.second)
196 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700197 auto propValue =
198 ipmi::getDbusProperty(bus, service, sensorInfo.sensorPath,
199 interface.first, property.first);
Tom Josephe4014fc2017-09-06 23:57:36 +0530200
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500201 for (const auto& value : std::get<OffsetValueMap>(property.second))
Tom Josephe4014fc2017-09-06 23:57:36 +0530202 {
203 if (propValue == value.second.assert)
204 {
205 setReading(value.first, responseData);
206 break;
207 }
208 }
209 }
210 }
211
212 return response;
213}
214
Patrick Venture0b02be92018-08-31 11:55:55 -0700215} // namespace get
Tom Joseph816e92b2017-09-06 19:23:00 +0530216
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500217namespace set
218{
219
220IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
221 const std::string& sensorPath,
222 const std::string& command,
223 const std::string& sensorInterface)
224{
225 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
226 using namespace std::string_literals;
227
Patrick Venture0b02be92018-08-31 11:55:55 -0700228 auto dbusService = getService(bus, sensorInterface, sensorPath);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500229
Patrick Venture0b02be92018-08-31 11:55:55 -0700230 return bus.new_method_call(dbusService.c_str(), sensorPath.c_str(),
231 updateInterface.c_str(), command.c_str());
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500232}
233
Patrick Venture0b02be92018-08-31 11:55:55 -0700234ipmi_ret_t eventdata(const SetSensorReadingReq& cmdData, const Info& sensorInfo,
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500235 uint8_t data)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500236{
Patrick Venture0b02be92018-08-31 11:55:55 -0700237 auto msg =
238 makeDbusMsg("org.freedesktop.DBus.Properties", sensorInfo.sensorPath,
239 "Set", sensorInfo.sensorInterface);
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500240
241 const auto& interface = sensorInfo.propertyInterfaces.begin();
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500242 msg.append(interface->first);
243 for (const auto& property : interface->second)
244 {
245 msg.append(property.first);
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500246 const auto& iter = std::get<OffsetValueMap>(property.second).find(data);
247 if (iter == std::get<OffsetValueMap>(property.second).end())
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500248 {
249 log<level::ERR>("Invalid event data");
250 return IPMI_CC_PARM_OUT_OF_RANGE;
251 }
252 msg.append(iter->second.assert);
253 }
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500254 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500255}
256
Patrick Venture0b02be92018-08-31 11:55:55 -0700257ipmi_ret_t assertion(const SetSensorReadingReq& cmdData, const Info& sensorInfo)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500258{
Brad Bishop06a0abf2018-02-26 20:46:00 -0500259 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
260 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
261 auto bothSet = assertionSet ^ deassertionSet;
262
263 const auto& interface = sensorInfo.propertyInterfaces.begin();
264
265 for (const auto& property : interface->second)
266 {
William A. Kennington III4c008022018-10-12 17:18:14 -0700267 std::optional<Value> tmp;
Brad Bishop06a0abf2018-02-26 20:46:00 -0500268 for (const auto& value : std::get<OffsetValueMap>(property.second))
269 {
270 if (bothSet.size() <= value.first || !bothSet.test(value.first))
271 {
272 // A BIOS shouldn't do this but ignore if they do.
273 continue;
274 }
275
276 if (assertionSet.test(value.first))
277 {
278 tmp = value.second.assert;
279 break;
280 }
281 if (deassertionSet.test(value.first))
282 {
283 tmp = value.second.deassert;
284 break;
285 }
286 }
287
William A. Kennington III4c008022018-10-12 17:18:14 -0700288 if (tmp)
Brad Bishop06a0abf2018-02-26 20:46:00 -0500289 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700290 auto msg = makeDbusMsg("org.freedesktop.DBus.Properties",
291 sensorInfo.sensorPath, "Set",
292 sensorInfo.sensorInterface);
Brad Bishop06a0abf2018-02-26 20:46:00 -0500293 msg.append(interface->first);
294 msg.append(property.first);
William A. Kennington III4c008022018-10-12 17:18:14 -0700295 msg.append(*tmp);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500296
Brad Bishop06a0abf2018-02-26 20:46:00 -0500297 auto rc = updateToDbus(msg);
298 if (rc)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500299 {
Brad Bishop06a0abf2018-02-26 20:46:00 -0500300 return rc;
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500301 }
302 }
303 }
Brad Bishop06a0abf2018-02-26 20:46:00 -0500304
305 return IPMI_CC_OK;
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500306}
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500307
Patrick Venture0b02be92018-08-31 11:55:55 -0700308} // namespace set
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500309
310namespace notify
311{
312
313IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
314 const std::string& sensorPath,
315 const std::string& command,
316 const std::string& sensorInterface)
317{
318 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
319 using namespace std::string_literals;
320
Dhruvaraj Subhashchandranf915f852017-09-14 07:01:48 -0500321 static const auto dbusPath = "/xyz/openbmc_project/inventory"s;
322 std::string dbusService = ipmi::getService(bus, updateInterface, dbusPath);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500323
Patrick Venture0b02be92018-08-31 11:55:55 -0700324 return bus.new_method_call(dbusService.c_str(), dbusPath.c_str(),
325 updateInterface.c_str(), command.c_str());
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500326}
327
Patrick Venture0b02be92018-08-31 11:55:55 -0700328ipmi_ret_t assertion(const SetSensorReadingReq& cmdData, const Info& sensorInfo)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500329{
Patrick Venture0b02be92018-08-31 11:55:55 -0700330 auto msg = makeDbusMsg(sensorInfo.sensorInterface, sensorInfo.sensorPath,
331 "Notify", sensorInfo.sensorInterface);
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500332
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500333 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
334 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
335 ipmi::sensor::ObjectMap objects;
336 ipmi::sensor::InterfaceMap interfaces;
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500337 for (const auto& interface : sensorInfo.propertyInterfaces)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500338 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700339 // For a property like functional state the result will be
340 // calculated based on the true value of all conditions.
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500341 for (const auto& property : interface.second)
342 {
343 ipmi::sensor::PropertyMap props;
344 bool valid = false;
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500345 auto result = true;
346 for (const auto& value : std::get<OffsetValueMap>(property.second))
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500347 {
348 if (assertionSet.test(value.first))
349 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700350 // Skip update if skipOn is ASSERT
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500351 if (SkipAssertion::ASSERT == value.second.skip)
352 {
353 return IPMI_CC_OK;
354 }
William A. Kennington III4c008022018-10-12 17:18:14 -0700355 result =
356 result && variant_ns::get<bool>(value.second.assert);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500357 valid = true;
358 }
359 else if (deassertionSet.test(value.first))
360 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700361 // Skip update if skipOn is DEASSERT
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500362 if (SkipAssertion::DEASSERT == value.second.skip)
363 {
364 return IPMI_CC_OK;
365 }
William A. Kennington III4c008022018-10-12 17:18:14 -0700366 result =
367 result && variant_ns::get<bool>(value.second.deassert);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500368 valid = true;
369 }
370 }
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500371 for (const auto& value :
Patrick Venture0b02be92018-08-31 11:55:55 -0700372 std::get<PreReqOffsetValueMap>(property.second))
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500373 {
374 if (assertionSet.test(value.first))
375 {
William A. Kennington III4c008022018-10-12 17:18:14 -0700376 result =
377 result && variant_ns::get<bool>(value.second.assert);
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500378 }
379 else if (deassertionSet.test(value.first))
380 {
William A. Kennington III4c008022018-10-12 17:18:14 -0700381 result =
382 result && variant_ns::get<bool>(value.second.deassert);
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500383 }
384 }
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500385 if (valid)
386 {
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500387 props.emplace(property.first, result);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500388 interfaces.emplace(interface.first, std::move(props));
389 }
390 }
391 }
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500392
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500393 objects.emplace(sensorInfo.sensorPath, std::move(interfaces));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500394 msg.append(std::move(objects));
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500395 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500396}
Tom Joseph816e92b2017-09-06 19:23:00 +0530397
Patrick Venture0b02be92018-08-31 11:55:55 -0700398} // namespace notify
Tom Joseph816e92b2017-09-06 19:23:00 +0530399
400namespace inventory
401{
402
403namespace get
404{
405
406GetSensorResponse assertion(const Info& sensorInfo)
407{
Vernon Mauery185b9f82018-07-20 10:52:36 -0700408 namespace fs = std::filesystem;
Tom Joseph816e92b2017-09-06 19:23:00 +0530409
410 fs::path path{ipmi::sensor::inventoryRoot};
411 path += sensorInfo.sensorPath;
412
413 return ipmi::sensor::get::mapDbusToAssertion(
Patrick Venture0b02be92018-08-31 11:55:55 -0700414 sensorInfo, path.string(),
415 sensorInfo.propertyInterfaces.begin()->first);
Tom Joseph816e92b2017-09-06 19:23:00 +0530416}
417
Patrick Venture0b02be92018-08-31 11:55:55 -0700418} // namespace get
Tom Joseph816e92b2017-09-06 19:23:00 +0530419
420} // namespace inventory
Patrick Venture0b02be92018-08-31 11:55:55 -0700421} // namespace sensor
422} // namespace ipmi