blob: 3aba53f54b135887fd24f0e34cb2c0883e44a230 [file] [log] [blame]
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -05001#include <bitset>
Tom Joseph816e92b2017-09-06 19:23:00 +05302#include <experimental/filesystem>
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -05003#include <phosphor-logging/elog-errors.hpp>
4#include <phosphor-logging/log.hpp>
5#include "xyz/openbmc_project/Common/error.hpp"
6#include "types.hpp"
Tom Joseph816e92b2017-09-06 19:23:00 +05307#include "sensorhandler.h"
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -05008#include "sensordatahandler.hpp"
Tom Joseph816e92b2017-09-06 19:23:00 +05309#include "utils.hpp"
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050010
11namespace ipmi
12{
13namespace sensor
14{
15
16using namespace phosphor::logging;
17using InternalFailure =
18 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
19
20static constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
21static constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
22static constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
23
24/** @brief get the D-Bus service and service path
25 * @param[in] bus - The Dbus bus object
26 * @param[in] interface - interface to the service
27 * @param[in] path - interested path in the list of objects
28 * @return pair of service path and service
29 */
30ServicePath getServiceAndPath(sdbusplus::bus::bus& bus,
31 const std::string& interface,
32 const std::string& path)
33{
34 auto depth = 0;
35 auto mapperCall = bus.new_method_call(MAPPER_BUSNAME,
36 MAPPER_PATH,
37 MAPPER_INTERFACE,
38 "GetSubTree");
39 mapperCall.append("/");
40 mapperCall.append(depth);
41 mapperCall.append(std::vector<Interface>({interface}));
42
43 auto mapperResponseMsg = bus.call(mapperCall);
44 if (mapperResponseMsg.is_method_error())
45 {
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -050046 log<level::ERR>("Mapper GetSubTree failed",
47 entry("PATH=%s", path),
48 entry("INTERFACE=%s", interface));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050049 elog<InternalFailure>();
50 }
51
52 MapperResponseType mapperResponse;
53 mapperResponseMsg.read(mapperResponse);
54 if (mapperResponse.empty())
55 {
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -050056 log<level::ERR>("Invalid mapper response",
57 entry("PATH=%s", path),
58 entry("INTERFACE=%s", interface));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050059 elog<InternalFailure>();
60 }
61
62 if (path.empty())
63 {
64 //Get the first one if the path is not in list.
65 return std::make_pair(mapperResponse.begin()->first,
66 mapperResponse.begin()->second.begin()->first);
67 }
68 const auto& iter = mapperResponse.find(path);
69 if (iter == mapperResponse.end())
70 {
Dhruvaraj Subhashchandran18e99992017-08-09 09:10:47 -050071 log<level::ERR>("Coudn't find d-bus path",
72 entry("PATH=%s", path),
73 entry("INTERFACE=%s", interface));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -050074 elog<InternalFailure>();
75 }
76 return std::make_pair(iter->first, iter->second.begin()->first);
77}
78
79AssertionSet getAssertionSet(const SetSensorReadingReq& cmdData)
80{
81 Assertion assertionStates =
82 (static_cast<Assertion>(cmdData.assertOffset8_14)) << 8 |
83 cmdData.assertOffset0_7;
84 Deassertion deassertionStates =
85 (static_cast<Deassertion>(cmdData.deassertOffset8_14)) << 8 |
86 cmdData.deassertOffset0_7;
87 return std::make_pair(assertionStates, deassertionStates);
88}
89
90ipmi_ret_t updateToDbus(IpmiUpdateData& msg)
91{
92 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
93 try
94 {
95 auto serviceResponseMsg = bus.call(msg);
96 if (serviceResponseMsg.is_method_error())
97 {
98 log<level::ERR>("Error in D-Bus call");
99 return IPMI_CC_UNSPECIFIED_ERROR;
100 }
101 }
102 catch (InternalFailure& e)
103 {
104 commit<InternalFailure>();
105 return IPMI_CC_UNSPECIFIED_ERROR;
106 }
107 return IPMI_CC_OK;
108}
109
Tom Joseph816e92b2017-09-06 19:23:00 +0530110namespace get
111{
112
113GetSensorResponse mapDbusToAssertion(const Info& sensorInfo,
114 const InstancePath& path,
115 const DbusInterface& interface)
116{
117 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
118 GetSensorResponse response {};
119 auto responseData = reinterpret_cast<GetReadingResponse*>(response.data());
120
121 auto service = ipmi::getService(bus, interface, path);
122
123 const auto& interfaceList = sensorInfo.propertyInterfaces;
124
125 for (const auto& interface : interfaceList)
126 {
127 for (const auto& property : interface.second)
128 {
129 auto propValue = ipmi::getDbusProperty(bus,
130 service,
131 path,
132 interface.first,
133 property.first);
134
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500135 for (const auto& value : std::get<OffsetValueMap>(property.second))
Tom Joseph816e92b2017-09-06 19:23:00 +0530136 {
137 if (propValue == value.second.assert)
138 {
139 setOffset(value.first, responseData);
140 break;
141 }
142
143 }
144 }
145 }
146
147 return response;
148}
149
150GetSensorResponse assertion(const Info& sensorInfo)
151{
152 return mapDbusToAssertion(sensorInfo,
153 sensorInfo.sensorPath,
154 sensorInfo.sensorInterface);
155}
156
Tom Josephe4014fc2017-09-06 23:57:36 +0530157GetSensorResponse eventdata2(const Info& sensorInfo)
158{
159 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
160 GetSensorResponse response {};
161 auto responseData = reinterpret_cast<GetReadingResponse*>(response.data());
162
163 auto service = ipmi::getService(bus,
164 sensorInfo.sensorInterface,
165 sensorInfo.sensorPath);
166
167 const auto& interfaceList = sensorInfo.propertyInterfaces;
168
169 for (const auto& interface : interfaceList)
170 {
171 for (const auto& property : interface.second)
172 {
173 auto propValue = ipmi::getDbusProperty(bus,
174 service,
175 sensorInfo.sensorPath,
176 interface.first,
177 property.first);
178
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500179 for (const auto& value : std::get<OffsetValueMap>(property.second))
Tom Josephe4014fc2017-09-06 23:57:36 +0530180 {
181 if (propValue == value.second.assert)
182 {
183 setReading(value.first, responseData);
184 break;
185 }
186 }
187 }
188 }
189
190 return response;
191}
192
Tom Joseph816e92b2017-09-06 19:23:00 +0530193} //namespace get
194
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500195namespace set
196{
197
198IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
199 const std::string& sensorPath,
200 const std::string& command,
201 const std::string& sensorInterface)
202{
203 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
204 using namespace std::string_literals;
205
Tom Josephc6a571a2017-11-28 16:46:22 +0530206 auto dbusService = getService(bus,
207 sensorInterface,
208 sensorPath);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500209
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500210 return bus.new_method_call(dbusService.c_str(),
Tom Josephc6a571a2017-11-28 16:46:22 +0530211 sensorPath.c_str(),
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500212 updateInterface.c_str(),
213 command.c_str());
214}
215
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500216ipmi_ret_t eventdata(const SetSensorReadingReq& cmdData,
217 const Info& sensorInfo,
218 uint8_t data)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500219{
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500220 auto msg = makeDbusMsg(
221 "org.freedesktop.DBus.Properties",
222 sensorInfo.sensorPath,
223 "Set",
224 sensorInfo.sensorInterface);
225
226 const auto& interface = sensorInfo.propertyInterfaces.begin();
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500227 msg.append(interface->first);
228 for (const auto& property : interface->second)
229 {
230 msg.append(property.first);
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500231 const auto& iter = std::get<OffsetValueMap>(property.second).find(data);
232 if (iter == std::get<OffsetValueMap>(property.second).end())
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500233 {
234 log<level::ERR>("Invalid event data");
235 return IPMI_CC_PARM_OUT_OF_RANGE;
236 }
237 msg.append(iter->second.assert);
238 }
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500239 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500240}
241
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500242ipmi_ret_t assertion(const SetSensorReadingReq& cmdData,
243 const Info& sensorInfo)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500244{
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500245 auto msg = makeDbusMsg(
246 "org.freedesktop.DBus.Properties",
247 sensorInfo.sensorPath,
248 "Set",
249 sensorInfo.sensorInterface);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500250
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500251 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
252 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
253
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500254 const auto& interface = sensorInfo.propertyInterfaces.begin();
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500255 msg.append(interface->first);
256 for (const auto& property : interface->second)
257 {
258 msg.append(property.first);
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500259 for (const auto& value : std::get<OffsetValueMap>(property.second))
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500260 {
261 if (assertionSet.test(value.first))
262 {
263 msg.append(value.second.assert);
264 }
265 if (deassertionSet.test(value.first))
266 {
267 msg.append(value.second.deassert);
268 }
269 }
270 }
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500271 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500272}
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500273
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500274}//namespace set
275
276namespace notify
277{
278
279IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
280 const std::string& sensorPath,
281 const std::string& command,
282 const std::string& sensorInterface)
283{
284 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
285 using namespace std::string_literals;
286
Dhruvaraj Subhashchandranf915f852017-09-14 07:01:48 -0500287 static const auto dbusPath = "/xyz/openbmc_project/inventory"s;
288 std::string dbusService = ipmi::getService(bus, updateInterface, dbusPath);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500289
290 return bus.new_method_call(dbusService.c_str(),
291 dbusPath.c_str(),
292 updateInterface.c_str(),
293 command.c_str());
294}
295
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500296ipmi_ret_t assertion(const SetSensorReadingReq& cmdData,
297 const Info& sensorInfo)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500298{
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500299 auto msg = makeDbusMsg(
300 sensorInfo.sensorInterface,
301 sensorInfo.sensorPath,
302 "Notify",
303 sensorInfo.sensorInterface);
304
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500305 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
306 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
307 ipmi::sensor::ObjectMap objects;
308 ipmi::sensor::InterfaceMap interfaces;
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500309 for (const auto& interface : sensorInfo.propertyInterfaces)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500310 {
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500311 //For a property like functional state the result will be
312 //calculated based on the true value of all conditions.
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500313 for (const auto& property : interface.second)
314 {
315 ipmi::sensor::PropertyMap props;
316 bool valid = false;
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500317 auto result = true;
318 for (const auto& value : std::get<OffsetValueMap>(property.second))
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500319 {
320 if (assertionSet.test(value.first))
321 {
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500322 //Skip update if skipOn is ASSERT
323 if (SkipAssertion::ASSERT == value.second.skip)
324 {
325 return IPMI_CC_OK;
326 }
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500327 result = result && value.second.assert.get<bool>();
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500328 valid = true;
329 }
330 else if (deassertionSet.test(value.first))
331 {
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500332 //Skip update if skipOn is DEASSERT
333 if (SkipAssertion::DEASSERT == value.second.skip)
334 {
335 return IPMI_CC_OK;
336 }
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500337 result = result && value.second.deassert.get<bool>();
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500338 valid = true;
339 }
340 }
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500341 for (const auto& value :
342 std::get<PreReqOffsetValueMap>(property.second))
343 {
344 if (assertionSet.test(value.first))
345 {
346 result = result && value.second.assert.get<bool>();
347 }
348 else if (deassertionSet.test(value.first))
349 {
350 result = result && value.second.deassert.get<bool>();
351 }
352 }
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500353 if (valid)
354 {
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500355 props.emplace(property.first, result);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500356 interfaces.emplace(interface.first, std::move(props));
357 }
358 }
359 }
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500360
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500361 objects.emplace(sensorInfo.sensorPath, std::move(interfaces));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500362 msg.append(std::move(objects));
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500363 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500364}
Tom Joseph816e92b2017-09-06 19:23:00 +0530365
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500366}//namespace notify
Tom Joseph816e92b2017-09-06 19:23:00 +0530367
368namespace inventory
369{
370
371namespace get
372{
373
374GetSensorResponse assertion(const Info& sensorInfo)
375{
376 namespace fs = std::experimental::filesystem;
377
378 fs::path path{ipmi::sensor::inventoryRoot};
379 path += sensorInfo.sensorPath;
380
381 return ipmi::sensor::get::mapDbusToAssertion(
382 sensorInfo,
383 path.string(),
384 sensorInfo.propertyInterfaces.begin()->first);
385}
386
387} //namespace get
388
389} // namespace inventory
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500390}//namespace sensor
391}//namespace ipmi