blob: 1de1540e335ebf9c74c5af8121c4334a4c4fdbbb [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
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -05005#include <bitset>
Vernon Mauerybdda8002019-02-26 10:18:51 -08006#include <filesystem>
Vernon Mauery33250242019-03-12 16:49:26 -07007#include <ipmid/types.hpp>
Vernon Mauery6a98fe72019-03-11 15:57:48 -07008#include <ipmid/utils.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -07009#include <optional>
Patrick Venture3a5071a2018-09-12 13:27:42 -070010#include <phosphor-logging/elog-errors.hpp>
11#include <phosphor-logging/log.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070012#include <sdbusplus/message/types.hpp>
Patrick Venture3a5071a2018-09-12 13:27:42 -070013#include <xyz/openbmc_project/Common/error.hpp>
14
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050015namespace ipmi
16{
17namespace sensor
18{
19
William A. Kennington III4c008022018-10-12 17:18:14 -070020namespace variant_ns = sdbusplus::message::variant_ns;
21
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050022using namespace phosphor::logging;
23using InternalFailure =
24 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
25
26static constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
27static constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
28static constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
29
30/** @brief get the D-Bus service and service path
31 * @param[in] bus - The Dbus bus object
32 * @param[in] interface - interface to the service
33 * @param[in] path - interested path in the list of objects
34 * @return pair of service path and service
35 */
36ServicePath getServiceAndPath(sdbusplus::bus::bus& bus,
37 const std::string& interface,
38 const std::string& path)
39{
40 auto depth = 0;
Patrick Venture0b02be92018-08-31 11:55:55 -070041 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
42 MAPPER_INTERFACE, "GetSubTree");
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050043 mapperCall.append("/");
44 mapperCall.append(depth);
45 mapperCall.append(std::vector<Interface>({interface}));
46
47 auto mapperResponseMsg = bus.call(mapperCall);
48 if (mapperResponseMsg.is_method_error())
49 {
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -050050 log<level::ERR>("Mapper GetSubTree failed",
Joseph Reynolds510eb9c2018-05-30 11:51:28 -050051 entry("PATH=%s", path.c_str()),
52 entry("INTERFACE=%s", interface.c_str()));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050053 elog<InternalFailure>();
54 }
55
56 MapperResponseType mapperResponse;
57 mapperResponseMsg.read(mapperResponse);
58 if (mapperResponse.empty())
59 {
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -050060 log<level::ERR>("Invalid mapper response",
Joseph Reynolds510eb9c2018-05-30 11:51:28 -050061 entry("PATH=%s", path.c_str()),
62 entry("INTERFACE=%s", interface.c_str()));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050063 elog<InternalFailure>();
64 }
65
66 if (path.empty())
67 {
Patrick Venture0b02be92018-08-31 11:55:55 -070068 // Get the first one if the path is not in list.
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050069 return std::make_pair(mapperResponse.begin()->first,
70 mapperResponse.begin()->second.begin()->first);
71 }
72 const auto& iter = mapperResponse.find(path);
73 if (iter == mapperResponse.end())
74 {
Gunnar Millsc9fa69e2018-04-08 16:35:25 -050075 log<level::ERR>("Couldn't find D-Bus path",
Joseph Reynolds510eb9c2018-05-30 11:51:28 -050076 entry("PATH=%s", path.c_str()),
77 entry("INTERFACE=%s", interface.c_str()));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050078 elog<InternalFailure>();
79 }
80 return std::make_pair(iter->first, iter->second.begin()->first);
81}
82
83AssertionSet getAssertionSet(const SetSensorReadingReq& cmdData)
84{
85 Assertion assertionStates =
86 (static_cast<Assertion>(cmdData.assertOffset8_14)) << 8 |
87 cmdData.assertOffset0_7;
88 Deassertion deassertionStates =
89 (static_cast<Deassertion>(cmdData.deassertOffset8_14)) << 8 |
90 cmdData.deassertOffset0_7;
91 return std::make_pair(assertionStates, deassertionStates);
92}
93
94ipmi_ret_t updateToDbus(IpmiUpdateData& msg)
95{
96 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
97 try
98 {
99 auto serviceResponseMsg = bus.call(msg);
100 if (serviceResponseMsg.is_method_error())
101 {
102 log<level::ERR>("Error in D-Bus call");
103 return IPMI_CC_UNSPECIFIED_ERROR;
104 }
105 }
106 catch (InternalFailure& e)
107 {
108 commit<InternalFailure>();
109 return IPMI_CC_UNSPECIFIED_ERROR;
110 }
111 return IPMI_CC_OK;
112}
113
Tom Joseph816e92b2017-09-06 19:23:00 +0530114namespace get
115{
116
Tom Josephb0adbcd2018-01-24 11:51:29 +0530117SensorName nameParentLeaf(const Info& sensorInfo)
118{
119 const auto pos = sensorInfo.sensorPath.find_last_of('/');
120 const auto leaf = sensorInfo.sensorPath.substr(pos + 1);
121
122 const auto remaining = sensorInfo.sensorPath.substr(0, pos);
123
124 const auto parentPos = remaining.find_last_of('/');
125 auto parent = remaining.substr(parentPos + 1);
126
127 parent += "_" + leaf;
128 return parent;
129}
130
Tom Joseph816e92b2017-09-06 19:23:00 +0530131GetSensorResponse mapDbusToAssertion(const Info& sensorInfo,
132 const InstancePath& path,
133 const DbusInterface& interface)
134{
135 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Patrick Venture0b02be92018-08-31 11:55:55 -0700136 GetSensorResponse response{};
Tom Joseph816e92b2017-09-06 19:23:00 +0530137 auto responseData = reinterpret_cast<GetReadingResponse*>(response.data());
138
139 auto service = ipmi::getService(bus, interface, path);
140
141 const auto& interfaceList = sensorInfo.propertyInterfaces;
142
143 for (const auto& interface : interfaceList)
144 {
145 for (const auto& property : interface.second)
146 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700147 auto propValue = ipmi::getDbusProperty(
148 bus, service, path, interface.first, property.first);
Tom Joseph816e92b2017-09-06 19:23:00 +0530149
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500150 for (const auto& value : std::get<OffsetValueMap>(property.second))
Tom Joseph816e92b2017-09-06 19:23:00 +0530151 {
152 if (propValue == value.second.assert)
153 {
154 setOffset(value.first, responseData);
155 break;
156 }
Tom Joseph816e92b2017-09-06 19:23:00 +0530157 }
158 }
159 }
160
161 return response;
162}
163
164GetSensorResponse assertion(const Info& sensorInfo)
165{
Patrick Venture0b02be92018-08-31 11:55:55 -0700166 return mapDbusToAssertion(sensorInfo, sensorInfo.sensorPath,
Tom Joseph816e92b2017-09-06 19:23:00 +0530167 sensorInfo.sensorInterface);
168}
169
Tom Josephe4014fc2017-09-06 23:57:36 +0530170GetSensorResponse eventdata2(const Info& sensorInfo)
171{
172 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Patrick Venture0b02be92018-08-31 11:55:55 -0700173 GetSensorResponse response{};
Tom Josephe4014fc2017-09-06 23:57:36 +0530174 auto responseData = reinterpret_cast<GetReadingResponse*>(response.data());
175
Patrick Venture0b02be92018-08-31 11:55:55 -0700176 auto service = ipmi::getService(bus, sensorInfo.sensorInterface,
Tom Josephe4014fc2017-09-06 23:57:36 +0530177 sensorInfo.sensorPath);
178
179 const auto& interfaceList = sensorInfo.propertyInterfaces;
180
181 for (const auto& interface : interfaceList)
182 {
183 for (const auto& property : interface.second)
184 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700185 auto propValue =
186 ipmi::getDbusProperty(bus, service, sensorInfo.sensorPath,
187 interface.first, property.first);
Tom Josephe4014fc2017-09-06 23:57:36 +0530188
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500189 for (const auto& value : std::get<OffsetValueMap>(property.second))
Tom Josephe4014fc2017-09-06 23:57:36 +0530190 {
191 if (propValue == value.second.assert)
192 {
193 setReading(value.first, responseData);
194 break;
195 }
196 }
197 }
198 }
199
200 return response;
201}
202
Patrick Venture0b02be92018-08-31 11:55:55 -0700203} // namespace get
Tom Joseph816e92b2017-09-06 19:23:00 +0530204
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500205namespace set
206{
207
208IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
209 const std::string& sensorPath,
210 const std::string& command,
211 const std::string& sensorInterface)
212{
213 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
214 using namespace std::string_literals;
215
Patrick Venture0b02be92018-08-31 11:55:55 -0700216 auto dbusService = getService(bus, sensorInterface, sensorPath);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500217
Patrick Venture0b02be92018-08-31 11:55:55 -0700218 return bus.new_method_call(dbusService.c_str(), sensorPath.c_str(),
219 updateInterface.c_str(), command.c_str());
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500220}
221
Patrick Venture0b02be92018-08-31 11:55:55 -0700222ipmi_ret_t eventdata(const SetSensorReadingReq& cmdData, const Info& sensorInfo,
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500223 uint8_t data)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500224{
Patrick Venture0b02be92018-08-31 11:55:55 -0700225 auto msg =
226 makeDbusMsg("org.freedesktop.DBus.Properties", sensorInfo.sensorPath,
227 "Set", sensorInfo.sensorInterface);
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500228
229 const auto& interface = sensorInfo.propertyInterfaces.begin();
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500230 msg.append(interface->first);
231 for (const auto& property : interface->second)
232 {
233 msg.append(property.first);
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500234 const auto& iter = std::get<OffsetValueMap>(property.second).find(data);
235 if (iter == std::get<OffsetValueMap>(property.second).end())
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500236 {
237 log<level::ERR>("Invalid event data");
238 return IPMI_CC_PARM_OUT_OF_RANGE;
239 }
240 msg.append(iter->second.assert);
241 }
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500242 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500243}
244
Patrick Venture0b02be92018-08-31 11:55:55 -0700245ipmi_ret_t assertion(const SetSensorReadingReq& cmdData, const Info& sensorInfo)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500246{
Brad Bishop06a0abf2018-02-26 20:46:00 -0500247 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
248 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
249 auto bothSet = assertionSet ^ deassertionSet;
250
251 const auto& interface = sensorInfo.propertyInterfaces.begin();
252
253 for (const auto& property : interface->second)
254 {
William A. Kennington III4c008022018-10-12 17:18:14 -0700255 std::optional<Value> tmp;
Brad Bishop06a0abf2018-02-26 20:46:00 -0500256 for (const auto& value : std::get<OffsetValueMap>(property.second))
257 {
258 if (bothSet.size() <= value.first || !bothSet.test(value.first))
259 {
260 // A BIOS shouldn't do this but ignore if they do.
261 continue;
262 }
263
264 if (assertionSet.test(value.first))
265 {
266 tmp = value.second.assert;
267 break;
268 }
269 if (deassertionSet.test(value.first))
270 {
271 tmp = value.second.deassert;
272 break;
273 }
274 }
275
William A. Kennington III4c008022018-10-12 17:18:14 -0700276 if (tmp)
Brad Bishop06a0abf2018-02-26 20:46:00 -0500277 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700278 auto msg = makeDbusMsg("org.freedesktop.DBus.Properties",
279 sensorInfo.sensorPath, "Set",
280 sensorInfo.sensorInterface);
Brad Bishop06a0abf2018-02-26 20:46:00 -0500281 msg.append(interface->first);
282 msg.append(property.first);
William A. Kennington III4c008022018-10-12 17:18:14 -0700283 msg.append(*tmp);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500284
Brad Bishop06a0abf2018-02-26 20:46:00 -0500285 auto rc = updateToDbus(msg);
286 if (rc)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500287 {
Brad Bishop06a0abf2018-02-26 20:46:00 -0500288 return rc;
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500289 }
290 }
291 }
Brad Bishop06a0abf2018-02-26 20:46:00 -0500292
293 return IPMI_CC_OK;
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500294}
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500295
Patrick Venture0b02be92018-08-31 11:55:55 -0700296} // namespace set
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500297
298namespace notify
299{
300
301IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
302 const std::string& sensorPath,
303 const std::string& command,
304 const std::string& sensorInterface)
305{
306 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
307 using namespace std::string_literals;
308
Dhruvaraj Subhashchandranf915f852017-09-14 07:01:48 -0500309 static const auto dbusPath = "/xyz/openbmc_project/inventory"s;
310 std::string dbusService = ipmi::getService(bus, updateInterface, dbusPath);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500311
Patrick Venture0b02be92018-08-31 11:55:55 -0700312 return bus.new_method_call(dbusService.c_str(), dbusPath.c_str(),
313 updateInterface.c_str(), command.c_str());
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500314}
315
Patrick Venture0b02be92018-08-31 11:55:55 -0700316ipmi_ret_t assertion(const SetSensorReadingReq& cmdData, const Info& sensorInfo)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500317{
Patrick Venture0b02be92018-08-31 11:55:55 -0700318 auto msg = makeDbusMsg(sensorInfo.sensorInterface, sensorInfo.sensorPath,
319 "Notify", sensorInfo.sensorInterface);
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500320
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500321 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
322 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
323 ipmi::sensor::ObjectMap objects;
324 ipmi::sensor::InterfaceMap interfaces;
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500325 for (const auto& interface : sensorInfo.propertyInterfaces)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500326 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700327 // For a property like functional state the result will be
328 // calculated based on the true value of all conditions.
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500329 for (const auto& property : interface.second)
330 {
331 ipmi::sensor::PropertyMap props;
332 bool valid = false;
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500333 auto result = true;
334 for (const auto& value : std::get<OffsetValueMap>(property.second))
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500335 {
336 if (assertionSet.test(value.first))
337 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700338 // Skip update if skipOn is ASSERT
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500339 if (SkipAssertion::ASSERT == value.second.skip)
340 {
341 return IPMI_CC_OK;
342 }
William A. Kennington III4c008022018-10-12 17:18:14 -0700343 result =
344 result && variant_ns::get<bool>(value.second.assert);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500345 valid = true;
346 }
347 else if (deassertionSet.test(value.first))
348 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700349 // Skip update if skipOn is DEASSERT
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500350 if (SkipAssertion::DEASSERT == value.second.skip)
351 {
352 return IPMI_CC_OK;
353 }
William A. Kennington III4c008022018-10-12 17:18:14 -0700354 result =
355 result && variant_ns::get<bool>(value.second.deassert);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500356 valid = true;
357 }
358 }
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500359 for (const auto& value :
Patrick Venture0b02be92018-08-31 11:55:55 -0700360 std::get<PreReqOffsetValueMap>(property.second))
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500361 {
362 if (assertionSet.test(value.first))
363 {
William A. Kennington III4c008022018-10-12 17:18:14 -0700364 result =
365 result && variant_ns::get<bool>(value.second.assert);
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500366 }
367 else if (deassertionSet.test(value.first))
368 {
William A. Kennington III4c008022018-10-12 17:18:14 -0700369 result =
370 result && variant_ns::get<bool>(value.second.deassert);
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500371 }
372 }
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500373 if (valid)
374 {
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500375 props.emplace(property.first, result);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500376 interfaces.emplace(interface.first, std::move(props));
377 }
378 }
379 }
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500380
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500381 objects.emplace(sensorInfo.sensorPath, std::move(interfaces));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500382 msg.append(std::move(objects));
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500383 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500384}
Tom Joseph816e92b2017-09-06 19:23:00 +0530385
Patrick Venture0b02be92018-08-31 11:55:55 -0700386} // namespace notify
Tom Joseph816e92b2017-09-06 19:23:00 +0530387
388namespace inventory
389{
390
391namespace get
392{
393
394GetSensorResponse assertion(const Info& sensorInfo)
395{
Vernon Mauery185b9f82018-07-20 10:52:36 -0700396 namespace fs = std::filesystem;
Tom Joseph816e92b2017-09-06 19:23:00 +0530397
398 fs::path path{ipmi::sensor::inventoryRoot};
399 path += sensorInfo.sensorPath;
400
401 return ipmi::sensor::get::mapDbusToAssertion(
Patrick Venture0b02be92018-08-31 11:55:55 -0700402 sensorInfo, path.string(),
403 sensorInfo.propertyInterfaces.begin()->first);
Tom Joseph816e92b2017-09-06 19:23:00 +0530404}
405
Patrick Venture0b02be92018-08-31 11:55:55 -0700406} // namespace get
Tom Joseph816e92b2017-09-06 19:23:00 +0530407
408} // namespace inventory
Patrick Venture0b02be92018-08-31 11:55:55 -0700409} // namespace sensor
410} // namespace ipmi