blob: 8240108ab7062e9c32809026d1d69c997513e2ba [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
206 std::string dbusService;
207 std::string dbusPath;
208
209 std::tie(dbusPath, dbusService) = getServiceAndPath(bus,
210 sensorInterface,
211 sensorPath);
212 return bus.new_method_call(dbusService.c_str(),
213 dbusPath.c_str(),
214 updateInterface.c_str(),
215 command.c_str());
216}
217
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500218ipmi_ret_t eventdata(const SetSensorReadingReq& cmdData,
219 const Info& sensorInfo,
220 uint8_t data)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500221{
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500222 auto msg = makeDbusMsg(
223 "org.freedesktop.DBus.Properties",
224 sensorInfo.sensorPath,
225 "Set",
226 sensorInfo.sensorInterface);
227
228 const auto& interface = sensorInfo.propertyInterfaces.begin();
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500229 msg.append(interface->first);
230 for (const auto& property : interface->second)
231 {
232 msg.append(property.first);
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500233 const auto& iter = std::get<OffsetValueMap>(property.second).find(data);
234 if (iter == std::get<OffsetValueMap>(property.second).end())
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500235 {
236 log<level::ERR>("Invalid event data");
237 return IPMI_CC_PARM_OUT_OF_RANGE;
238 }
239 msg.append(iter->second.assert);
240 }
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500241 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500242}
243
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500244ipmi_ret_t assertion(const SetSensorReadingReq& cmdData,
245 const Info& sensorInfo)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500246{
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500247 auto msg = makeDbusMsg(
248 "org.freedesktop.DBus.Properties",
249 sensorInfo.sensorPath,
250 "Set",
251 sensorInfo.sensorInterface);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500252
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500253 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
254 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
255
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500256 const auto& interface = sensorInfo.propertyInterfaces.begin();
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500257 msg.append(interface->first);
258 for (const auto& property : interface->second)
259 {
260 msg.append(property.first);
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500261 for (const auto& value : std::get<OffsetValueMap>(property.second))
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500262 {
263 if (assertionSet.test(value.first))
264 {
265 msg.append(value.second.assert);
266 }
267 if (deassertionSet.test(value.first))
268 {
269 msg.append(value.second.deassert);
270 }
271 }
272 }
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500273 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500274}
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500275
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500276}//namespace set
277
278namespace notify
279{
280
281IpmiUpdateData makeDbusMsg(const std::string& updateInterface,
282 const std::string& sensorPath,
283 const std::string& command,
284 const std::string& sensorInterface)
285{
286 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
287 using namespace std::string_literals;
288
Dhruvaraj Subhashchandranf915f852017-09-14 07:01:48 -0500289 static const auto dbusPath = "/xyz/openbmc_project/inventory"s;
290 std::string dbusService = ipmi::getService(bus, updateInterface, dbusPath);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500291
292 return bus.new_method_call(dbusService.c_str(),
293 dbusPath.c_str(),
294 updateInterface.c_str(),
295 command.c_str());
296}
297
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500298ipmi_ret_t assertion(const SetSensorReadingReq& cmdData,
299 const Info& sensorInfo)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500300{
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500301 auto msg = makeDbusMsg(
302 sensorInfo.sensorInterface,
303 sensorInfo.sensorPath,
304 "Notify",
305 sensorInfo.sensorInterface);
306
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500307 std::bitset<16> assertionSet(getAssertionSet(cmdData).first);
308 std::bitset<16> deassertionSet(getAssertionSet(cmdData).second);
309 ipmi::sensor::ObjectMap objects;
310 ipmi::sensor::InterfaceMap interfaces;
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500311 for (const auto& interface : sensorInfo.propertyInterfaces)
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500312 {
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500313 //For a property like functional state the result will be
314 //calculated based on the true value of all conditions.
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500315 for (const auto& property : interface.second)
316 {
317 ipmi::sensor::PropertyMap props;
318 bool valid = false;
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500319 auto result = true;
320 for (const auto& value : std::get<OffsetValueMap>(property.second))
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500321 {
322 if (assertionSet.test(value.first))
323 {
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500324 //Skip update if skipOn is ASSERT
325 if (SkipAssertion::ASSERT == value.second.skip)
326 {
327 return IPMI_CC_OK;
328 }
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500329 result = result && value.second.assert.get<bool>();
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500330 valid = true;
331 }
332 else if (deassertionSet.test(value.first))
333 {
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500334 //Skip update if skipOn is DEASSERT
335 if (SkipAssertion::DEASSERT == value.second.skip)
336 {
337 return IPMI_CC_OK;
338 }
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500339 result = result && value.second.deassert.get<bool>();
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500340 valid = true;
341 }
342 }
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500343 for (const auto& value :
344 std::get<PreReqOffsetValueMap>(property.second))
345 {
346 if (assertionSet.test(value.first))
347 {
348 result = result && value.second.assert.get<bool>();
349 }
350 else if (deassertionSet.test(value.first))
351 {
352 result = result && value.second.deassert.get<bool>();
353 }
354 }
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500355 if (valid)
356 {
Dhruvaraj Subhashchandrane245e4e2017-10-03 03:58:05 -0500357 props.emplace(property.first, result);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500358 interfaces.emplace(interface.first, std::move(props));
359 }
360 }
361 }
Dhruvaraj Subhashchandrane84841c2017-08-22 07:40:27 -0500362
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500363 objects.emplace(sensorInfo.sensorPath, std::move(interfaces));
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500364 msg.append(std::move(objects));
Deepak Kodihalli1bb0d382017-08-12 02:01:27 -0500365 return updateToDbus(msg);
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500366}
Tom Joseph816e92b2017-09-06 19:23:00 +0530367
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500368}//namespace notify
Tom Joseph816e92b2017-09-06 19:23:00 +0530369
370namespace inventory
371{
372
373namespace get
374{
375
376GetSensorResponse assertion(const Info& sensorInfo)
377{
378 namespace fs = std::experimental::filesystem;
379
380 fs::path path{ipmi::sensor::inventoryRoot};
381 path += sensorInfo.sensorPath;
382
383 return ipmi::sensor::get::mapDbusToAssertion(
384 sensorInfo,
385 path.string(),
386 sensorInfo.propertyInterfaces.begin()->first);
387}
388
389} //namespace get
390
391} // namespace inventory
Dhruvaraj Subhashchandrane0af7202017-07-12 06:35:20 -0500392}//namespace sensor
393}//namespace ipmi