blob: 11ae15610827658a129829a473e2c2fec58581d6 [file] [log] [blame]
Ratan Guptab8e99552017-07-27 07:07:48 +05301#include <arpa/inet.h>
2#include <dirent.h>
Yong Li7dc4ac02019-08-23 17:44:32 +08003#include <fcntl.h>
4#include <linux/i2c-dev.h>
5#include <linux/i2c.h>
Ratan Guptab8e99552017-07-27 07:07:48 +05306#include <net/if.h>
Yong Li7dc4ac02019-08-23 17:44:32 +08007#include <sys/ioctl.h>
8#include <sys/types.h>
9#include <unistd.h>
Ratan Guptab8e99552017-07-27 07:07:48 +053010
Patrick Venture2e633522018-10-13 13:51:06 -070011#include <algorithm>
Kun Yi5dcf41e2019-03-05 14:02:51 -080012#include <chrono>
Vernon Mauery6a98fe72019-03-11 15:57:48 -070013#include <ipmid/utils.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070014#include <phosphor-logging/elog-errors.hpp>
15#include <phosphor-logging/log.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070016#include <sdbusplus/message/types.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070017#include <xyz/openbmc_project/Common/error.hpp>
18
Tom Josephbe703f72017-03-09 12:34:35 +053019namespace ipmi
20{
21
Ratan Guptacc8feb42017-07-25 21:52:10 +053022using namespace phosphor::logging;
23using namespace sdbusplus::xyz::openbmc_project::Common::Error;
24
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -050025namespace network
26{
27
28/** @brief checks if the given ip is Link Local Ip or not.
Patrick Venture0b02be92018-08-31 11:55:55 -070029 * @param[in] ipaddress - IPAddress.
30 */
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -050031bool isLinkLocalIP(const std::string& ipaddress);
32
Patrick Venture0b02be92018-08-31 11:55:55 -070033} // namespace network
Ratan Guptacc8feb42017-07-25 21:52:10 +053034
Patrick Venture0b02be92018-08-31 11:55:55 -070035// TODO There may be cases where an interface is implemented by multiple
Ratan Guptacc8feb42017-07-25 21:52:10 +053036// objects,to handle such cases we are interested on that object
37// which are on interested busname.
38// Currently mapper doesn't give the readable busname(gives busid) so we can't
39// use busname to find the object,will do later once the support is there.
40
Patrick Williams5d82f472022-07-22 19:26:53 -050041DbusObjectInfo getDbusObject(sdbusplus::bus_t& bus,
Ratan Gupta01d4bd12017-08-07 15:53:25 +053042 const std::string& interface,
Ratan Guptacc8feb42017-07-25 21:52:10 +053043 const std::string& serviceRoot,
44 const std::string& match)
45{
46 std::vector<DbusInterface> interfaces;
47 interfaces.emplace_back(interface);
48
Ratan Guptacc8feb42017-07-25 21:52:10 +053049 auto depth = 0;
50
Patrick Venture0b02be92018-08-31 11:55:55 -070051 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ,
52 MAPPER_INTF, "GetSubTree");
Ratan Guptacc8feb42017-07-25 21:52:10 +053053
54 mapperCall.append(serviceRoot, depth, interfaces);
55
56 auto mapperReply = bus.call(mapperCall);
57 if (mapperReply.is_method_error())
58 {
59 log<level::ERR>("Error in mapper call");
60 elog<InternalFailure>();
61 }
62
63 ObjectTree objectTree;
64 mapperReply.read(objectTree);
65
66 if (objectTree.empty())
67 {
Patrick Venturef0c48782017-09-21 18:48:51 -070068 log<level::ERR>("No Object has implemented the interface",
Ratan Guptacc8feb42017-07-25 21:52:10 +053069 entry("INTERFACE=%s", interface.c_str()));
70 elog<InternalFailure>();
71 }
72
73 DbusObjectInfo objectInfo;
74
75 // if match is empty then return the first object
Patrick Venture0b02be92018-08-31 11:55:55 -070076 if (match == "")
Ratan Guptacc8feb42017-07-25 21:52:10 +053077 {
Patrick Venture0b02be92018-08-31 11:55:55 -070078 objectInfo = std::make_pair(
79 objectTree.begin()->first,
Ratan Guptacc8feb42017-07-25 21:52:10 +053080 std::move(objectTree.begin()->second.begin()->first));
81 return objectInfo;
82 }
83
84 // else search the match string in the object path
Patrick Venture2e633522018-10-13 13:51:06 -070085 auto found = std::find_if(
86 objectTree.begin(), objectTree.end(), [&match](const auto& object) {
87 return (object.first.find(match) != std::string::npos);
88 });
Ratan Guptacc8feb42017-07-25 21:52:10 +053089
Patrick Venture2e633522018-10-13 13:51:06 -070090 if (found == objectTree.end())
Ratan Guptacc8feb42017-07-25 21:52:10 +053091 {
92 log<level::ERR>("Failed to find object which matches",
93 entry("MATCH=%s", match.c_str()));
94 elog<InternalFailure>();
Patrick Venture2e633522018-10-13 13:51:06 -070095 // elog<> throws an exception.
Ratan Guptacc8feb42017-07-25 21:52:10 +053096 }
Patrick Venture2e633522018-10-13 13:51:06 -070097
98 return make_pair(found->first, std::move(found->second.begin()->first));
Ratan Guptacc8feb42017-07-25 21:52:10 +053099}
100
Patrick Williams5d82f472022-07-22 19:26:53 -0500101Value getDbusProperty(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -0700102 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800103 const std::string& property,
104 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +0530105{
106
107 Value value;
108
Patrick Venture0b02be92018-08-31 11:55:55 -0700109 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
110 PROP_INTF, METHOD_GET);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530111
112 method.append(interface, property);
113
Kun Yi5dcf41e2019-03-05 14:02:51 -0800114 auto reply = bus.call(method, timeout.count());
Ratan Guptacc8feb42017-07-25 21:52:10 +0530115
116 if (reply.is_method_error())
117 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700118 log<level::ERR>("Failed to get property",
119 entry("PROPERTY=%s", property.c_str()),
120 entry("PATH=%s", objPath.c_str()),
121 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptacc8feb42017-07-25 21:52:10 +0530122 elog<InternalFailure>();
123 }
124
125 reply.read(value);
126
127 return value;
128}
129
Patrick Williams5d82f472022-07-22 19:26:53 -0500130PropertyMap getAllDbusProperties(sdbusplus::bus_t& bus,
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530131 const std::string& service,
Ratan Guptacc8feb42017-07-25 21:52:10 +0530132 const std::string& objPath,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800133 const std::string& interface,
134 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +0530135{
136 PropertyMap properties;
Ratan Guptacc8feb42017-07-25 21:52:10 +0530137
Patrick Venture0b02be92018-08-31 11:55:55 -0700138 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
139 PROP_INTF, METHOD_GET_ALL);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530140
141 method.append(interface);
142
Kun Yi5dcf41e2019-03-05 14:02:51 -0800143 auto reply = bus.call(method, timeout.count());
Ratan Guptacc8feb42017-07-25 21:52:10 +0530144
145 if (reply.is_method_error())
146 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700147 log<level::ERR>("Failed to get all properties",
148 entry("PATH=%s", objPath.c_str()),
149 entry("INTERFACE=%s", interface.c_str()));
150 elog<InternalFailure>();
Ratan Guptacc8feb42017-07-25 21:52:10 +0530151 }
152
153 reply.read(properties);
154 return properties;
155}
156
Patrick Williams5d82f472022-07-22 19:26:53 -0500157ObjectValueTree getManagedObjects(sdbusplus::bus_t& bus,
Patrick Venture0b02be92018-08-31 11:55:55 -0700158 const std::string& service,
159 const std::string& objPath)
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600160{
161 ipmi::ObjectValueTree interfaces;
162
Patrick Venture0b02be92018-08-31 11:55:55 -0700163 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
164 "org.freedesktop.DBus.ObjectManager",
165 "GetManagedObjects");
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600166
167 auto reply = bus.call(method);
168
169 if (reply.is_method_error())
170 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700171 log<level::ERR>("Failed to get managed objects",
172 entry("PATH=%s", objPath.c_str()));
173 elog<InternalFailure>();
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600174 }
175
176 reply.read(interfaces);
177 return interfaces;
178}
179
Patrick Williams5d82f472022-07-22 19:26:53 -0500180void setDbusProperty(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -0700181 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800182 const std::string& property, const Value& value,
183 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +0530184{
Patrick Venture0b02be92018-08-31 11:55:55 -0700185 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
186 PROP_INTF, METHOD_SET);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530187
188 method.append(interface, property, value);
189
Kun Yi5dcf41e2019-03-05 14:02:51 -0800190 if (!bus.call(method, timeout.count()))
Ratan Guptacc8feb42017-07-25 21:52:10 +0530191 {
192 log<level::ERR>("Failed to set property",
193 entry("PROPERTY=%s", property.c_str()),
Patrick Venture0b02be92018-08-31 11:55:55 -0700194 entry("PATH=%s", objPath.c_str()),
195 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptacc8feb42017-07-25 21:52:10 +0530196 elog<InternalFailure>();
197 }
Ratan Guptacc8feb42017-07-25 21:52:10 +0530198}
199
Patrick Venture0b02be92018-08-31 11:55:55 -0700200ServiceCache::ServiceCache(const std::string& intf, const std::string& path) :
Vernon Mauery54012502018-11-07 10:17:31 -0800201 intf(intf), path(path), cachedService(std::nullopt),
202 cachedBusName(std::nullopt)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700203{
204}
205
Patrick Venture0b02be92018-08-31 11:55:55 -0700206ServiceCache::ServiceCache(std::string&& intf, std::string&& path) :
Vernon Mauery54012502018-11-07 10:17:31 -0800207 intf(std::move(intf)), path(std::move(path)), cachedService(std::nullopt),
208 cachedBusName(std::nullopt)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700209{
210}
211
Patrick Williams5d82f472022-07-22 19:26:53 -0500212const std::string& ServiceCache::getService(sdbusplus::bus_t& bus)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700213{
214 if (!isValid(bus))
215 {
216 cachedBusName = bus.get_unique_name();
217 cachedService = ::ipmi::getService(bus, intf, path);
218 }
219 return cachedService.value();
220}
221
222void ServiceCache::invalidate()
223{
Vernon Mauery54012502018-11-07 10:17:31 -0800224 cachedBusName = std::nullopt;
225 cachedService = std::nullopt;
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700226}
227
Patrick Williams5d82f472022-07-22 19:26:53 -0500228sdbusplus::message_t ServiceCache::newMethodCall(sdbusplus::bus_t& bus,
229 const char* intf,
230 const char* method)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700231{
Patrick Venture0b02be92018-08-31 11:55:55 -0700232 return bus.new_method_call(getService(bus).c_str(), path.c_str(), intf,
233 method);
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700234}
235
Patrick Williams5d82f472022-07-22 19:26:53 -0500236bool ServiceCache::isValid(sdbusplus::bus_t& bus) const
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700237{
238 return cachedService && cachedBusName == bus.get_unique_name();
239}
240
Patrick Williams5d82f472022-07-22 19:26:53 -0500241std::string getService(sdbusplus::bus_t& bus, const std::string& intf,
Tom Josephbe703f72017-03-09 12:34:35 +0530242 const std::string& path)
243{
Patrick Venture0b02be92018-08-31 11:55:55 -0700244 auto mapperCall =
245 bus.new_method_call("xyz.openbmc_project.ObjectMapper",
246 "/xyz/openbmc_project/object_mapper",
247 "xyz.openbmc_project.ObjectMapper", "GetObject");
Tom Josephbe703f72017-03-09 12:34:35 +0530248
249 mapperCall.append(path);
250 mapperCall.append(std::vector<std::string>({intf}));
251
252 auto mapperResponseMsg = bus.call(mapperCall);
253
254 if (mapperResponseMsg.is_method_error())
255 {
256 throw std::runtime_error("ERROR in mapper call");
257 }
258
259 std::map<std::string, std::vector<std::string>> mapperResponse;
260 mapperResponseMsg.read(mapperResponse);
261
262 if (mapperResponse.begin() == mapperResponse.end())
263 {
264 throw std::runtime_error("ERROR in reading the mapper response");
265 }
266
267 return mapperResponse.begin()->first;
268}
269
Patrick Williams5d82f472022-07-22 19:26:53 -0500270ipmi::ObjectTree getAllDbusObjects(sdbusplus::bus_t& bus,
Ratan Guptab8e99552017-07-27 07:07:48 +0530271 const std::string& serviceRoot,
272 const std::string& interface,
273 const std::string& match)
274{
275 std::vector<std::string> interfaces;
276 interfaces.emplace_back(interface);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530277
Ratan Guptab8e99552017-07-27 07:07:48 +0530278 auto depth = 0;
279
Patrick Venture0b02be92018-08-31 11:55:55 -0700280 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ,
281 MAPPER_INTF, "GetSubTree");
Ratan Guptab8e99552017-07-27 07:07:48 +0530282
283 mapperCall.append(serviceRoot, depth, interfaces);
284
285 auto mapperReply = bus.call(mapperCall);
286 if (mapperReply.is_method_error())
287 {
288 log<level::ERR>("Error in mapper call",
Patrick Venture0b02be92018-08-31 11:55:55 -0700289 entry("SERVICEROOT=%s", serviceRoot.c_str()),
Ratan Guptab8e99552017-07-27 07:07:48 +0530290 entry("INTERFACE=%s", interface.c_str()));
291
292 elog<InternalFailure>();
293 }
294
295 ObjectTree objectTree;
296 mapperReply.read(objectTree);
297
298 for (auto it = objectTree.begin(); it != objectTree.end();)
299 {
300 if (it->first.find(match) == std::string::npos)
301 {
302 it = objectTree.erase(it);
303 }
304 else
305 {
306 ++it;
307 }
308 }
309
310 return objectTree;
311}
312
Patrick Williams5d82f472022-07-22 19:26:53 -0500313void deleteAllDbusObjects(sdbusplus::bus_t& bus, const std::string& serviceRoot,
Ratan Guptab8e99552017-07-27 07:07:48 +0530314 const std::string& interface,
315 const std::string& match)
316{
317 try
318 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700319 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, match);
Ratan Guptab8e99552017-07-27 07:07:48 +0530320
321 for (auto& object : objectTree)
322 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700323 method_no_args::callDbusMethod(bus, object.second.begin()->first,
324 object.first, DELETE_INTERFACE,
325 "Delete");
Ratan Guptab8e99552017-07-27 07:07:48 +0530326 }
327 }
Patrick Williams5d82f472022-07-22 19:26:53 -0500328 catch (const sdbusplus::exception_t& e)
Ratan Guptab8e99552017-07-27 07:07:48 +0530329 {
Vernon Mauery7a614182018-11-27 12:54:52 -0800330 log<level::INFO>("sdbusplus exception - Unable to delete the objects",
331 entry("ERROR=%s", e.what()),
Ratan Guptab8e99552017-07-27 07:07:48 +0530332 entry("INTERFACE=%s", interface.c_str()),
333 entry("SERVICE=%s", serviceRoot.c_str()));
334 }
335}
336
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700337static inline std::string convertToString(const InterfaceList& interfaces)
338{
339 std::string intfStr;
340 for (const auto& intf : interfaces)
341 {
342 intfStr += "," + intf;
343 }
344 return intfStr;
345}
346
Patrick Williams5d82f472022-07-22 19:26:53 -0500347ObjectTree getAllAncestors(sdbusplus::bus_t& bus, const std::string& path,
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530348 InterfaceList&& interfaces)
349{
Patrick Venture0b02be92018-08-31 11:55:55 -0700350 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ,
351 MAPPER_INTF, "GetAncestors");
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530352 mapperCall.append(path, interfaces);
353
354 auto mapperReply = bus.call(mapperCall);
355 if (mapperReply.is_method_error())
356 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700357 log<level::ERR>(
358 "Error in mapper call", entry("PATH=%s", path.c_str()),
359 entry("INTERFACES=%s", convertToString(interfaces).c_str()));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530360
361 elog<InternalFailure>();
362 }
363
364 ObjectTree objectTree;
365 mapperReply.read(objectTree);
366
367 if (objectTree.empty())
368 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700369 log<level::ERR>(
370 "No Object has implemented the interface",
371 entry("PATH=%s", path.c_str()),
372 entry("INTERFACES=%s", convertToString(interfaces).c_str()));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530373 elog<InternalFailure>();
374 }
375
376 return objectTree;
377}
Ratan Guptab8e99552017-07-27 07:07:48 +0530378
379namespace method_no_args
380{
381
Patrick Williams5d82f472022-07-22 19:26:53 -0500382void callDbusMethod(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -0700383 const std::string& objPath, const std::string& interface,
Ratan Guptab8e99552017-07-27 07:07:48 +0530384 const std::string& method)
385
386{
Patrick Venture0b02be92018-08-31 11:55:55 -0700387 auto busMethod = bus.new_method_call(service.c_str(), objPath.c_str(),
388 interface.c_str(), method.c_str());
Ratan Guptab8e99552017-07-27 07:07:48 +0530389
390 auto reply = bus.call(busMethod);
391
392 if (reply.is_method_error())
393 {
394 log<level::ERR>("Failed to execute method",
395 entry("METHOD=%s", method.c_str()),
396 entry("PATH=%s", objPath.c_str()),
397 entry("INTERFACE=%s", interface.c_str()));
398 elog<InternalFailure>();
399 }
400}
401
Patrick Venture0b02be92018-08-31 11:55:55 -0700402} // namespace method_no_args
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700403
404/********* Begin co-routine yielding alternatives ***************/
405
Vijay Khemka31655692020-03-04 15:22:12 -0800406boost::system::error_code getService(Context::ptr ctx, const std::string& intf,
407 const std::string& path,
408 std::string& service)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700409{
410 boost::system::error_code ec;
411 std::map<std::string, std::vector<std::string>> mapperResponse =
412 ctx->bus->yield_method_call<decltype(mapperResponse)>(
413 ctx->yield, ec, "xyz.openbmc_project.ObjectMapper",
414 "/xyz/openbmc_project/object_mapper",
Jason M. Billsf5967982020-03-06 10:42:08 -0800415 "xyz.openbmc_project.ObjectMapper", "GetObject", path,
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700416 std::vector<std::string>({intf}));
417
418 if (!ec)
419 {
420 service = std::move(mapperResponse.begin()->first);
421 }
422 return ec;
423}
424
425boost::system::error_code getDbusObject(Context::ptr ctx,
426 const std::string& interface,
427 const std::string& subtreePath,
428 const std::string& match,
429 DbusObjectInfo& dbusObject)
430{
431 std::vector<DbusInterface> interfaces;
432 interfaces.emplace_back(interface);
433
434 auto depth = 0;
435 boost::system::error_code ec;
436 ObjectTree objectTree = ctx->bus->yield_method_call<ObjectTree>(
437 ctx->yield, ec, MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF, "GetSubTree",
438 subtreePath, depth, interfaces);
439
440 if (ec)
441 {
442 return ec;
443 }
444
445 if (objectTree.empty())
446 {
447 log<level::ERR>("No Object has implemented the interface",
448 entry("INTERFACE=%s", interface.c_str()),
449 entry("NETFN=%x", ctx->netFn),
450 entry("CMD=%x,", ctx->cmd));
451 return boost::system::errc::make_error_code(
452 boost::system::errc::no_such_process);
453 }
454
455 // if match is empty then return the first object
456 if (match == "")
457 {
458 dbusObject = std::make_pair(
459 std::move(objectTree.begin()->first),
460 std::move(objectTree.begin()->second.begin()->first));
461 return ec;
462 }
463
464 // else search the match string in the object path
465 auto found = std::find_if(
466 objectTree.begin(), objectTree.end(), [&match](const auto& object) {
467 return (object.first.find(match) != std::string::npos);
468 });
469
470 if (found == objectTree.end())
471 {
472 log<level::ERR>("Failed to find object which matches",
473 entry("MATCH=%s", match.c_str()),
474 entry("NETFN=%x", ctx->netFn),
475 entry("CMD=%x,", ctx->cmd));
476 // set ec
477 return boost::system::errc::make_error_code(
478 boost::system::errc::no_such_file_or_directory);
479 }
480
481 dbusObject = std::make_pair(std::move(found->first),
482 std::move(found->second.begin()->first));
483 return ec;
484}
485
486boost::system::error_code getAllDbusProperties(Context::ptr ctx,
487 const std::string& service,
488 const std::string& objPath,
489 const std::string& interface,
490 PropertyMap& properties)
491{
492 boost::system::error_code ec;
493 properties = ctx->bus->yield_method_call<PropertyMap>(
494 ctx->yield, ec, service.c_str(), objPath.c_str(), PROP_INTF,
495 METHOD_GET_ALL, interface);
496 return ec;
497}
498
499boost::system::error_code
500 setDbusProperty(Context::ptr ctx, const std::string& service,
501 const std::string& objPath, const std::string& interface,
502 const std::string& property, const Value& value)
503{
504 boost::system::error_code ec;
505 ctx->bus->yield_method_call(ctx->yield, ec, service.c_str(),
506 objPath.c_str(), PROP_INTF, METHOD_SET,
507 interface, property, value);
508 return ec;
509}
510
511boost::system::error_code getAllDbusObjects(Context::ptr ctx,
512 const std::string& serviceRoot,
513 const std::string& interface,
514 const std::string& match,
515 ObjectTree& objectTree)
516{
517 boost::system::error_code ec;
518 std::vector<std::string> interfaces;
519 interfaces.emplace_back(interface);
520
521 auto depth = 0;
522
523 objectTree = ctx->bus->yield_method_call<ObjectTree>(
524 ctx->yield, ec, MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF, "GetSubTree",
525 serviceRoot, depth, interfaces);
526
527 if (ec)
528 {
529 return ec;
530 }
531
532 for (auto it = objectTree.begin(); it != objectTree.end();)
533 {
534 if (it->first.find(match) == std::string::npos)
535 {
536 it = objectTree.erase(it);
537 }
538 else
539 {
540 ++it;
541 }
542 }
543
544 return ec;
545}
546
547boost::system::error_code deleteAllDbusObjects(Context::ptr ctx,
548 const std::string& serviceRoot,
549 const std::string& interface,
550 const std::string& match)
551{
552 ObjectTree objectTree;
553 boost::system::error_code ec =
554 getAllDbusObjects(ctx, serviceRoot, interface, match, objectTree);
555 if (ec)
556 {
557 return ec;
558 }
559
560 for (auto& object : objectTree)
561 {
562 ctx->bus->yield_method_call(ctx->yield, ec,
563 object.second.begin()->first, object.first,
564 DELETE_INTERFACE, "Delete");
565 if (ec)
566 {
567 log<level::ERR>("Failed to delete all objects",
568 entry("INTERFACE=%s", interface.c_str()),
569 entry("SERVICE=%s", serviceRoot.c_str()),
570 entry("NETFN=%x", ctx->netFn),
571 entry("CMD=%x,", ctx->cmd),
572 entry("ERROR=%s", ec.message().c_str()));
573 break;
574 }
575 }
576 return ec;
577}
578
579boost::system::error_code getManagedObjects(Context::ptr ctx,
580 const std::string& service,
581 const std::string& objPath,
582 ObjectValueTree& objects)
583{
584 boost::system::error_code ec;
585 objects = ctx->bus->yield_method_call<ipmi::ObjectValueTree>(
586 ctx->yield, ec, service.c_str(), objPath.c_str(),
587 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
588 return ec;
589}
590
591boost::system::error_code getAllAncestors(Context::ptr ctx,
592 const std::string& path,
593 const InterfaceList& interfaces,
594 ObjectTree& objectTree)
595{
596 std::string interfaceList = convertToString(interfaces);
597
598 boost::system::error_code ec;
599 objectTree = ctx->bus->yield_method_call<ObjectTree>(
600 ctx->yield, ec, MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
601 "GetAncestors", path, interfaceList);
602
603 if (ec)
604 {
605 return ec;
606 }
607
608 if (objectTree.empty())
609 {
610 log<level::ERR>("No Object has implemented the interface",
611 entry("PATH=%s", path.c_str()),
612 entry("INTERFACES=%s", interfaceList.c_str()));
613 elog<InternalFailure>();
614 }
615
616 return ec;
617}
618
619/********* End co-routine yielding alternatives ***************/
620
Yong Li7dc4ac02019-08-23 17:44:32 +0800621ipmi::Cc i2cWriteRead(std::string i2cBus, const uint8_t slaveAddr,
622 std::vector<uint8_t> writeData,
623 std::vector<uint8_t>& readBuf)
624{
625 // Open the i2c device, for low-level combined data write/read
626 int i2cDev = ::open(i2cBus.c_str(), O_RDWR | O_CLOEXEC);
627 if (i2cDev < 0)
628 {
629 log<level::ERR>("Failed to open i2c bus",
630 phosphor::logging::entry("BUS=%s", i2cBus.c_str()));
631 return ipmi::ccInvalidFieldRequest;
632 }
633
634 const size_t writeCount = writeData.size();
635 const size_t readCount = readBuf.size();
636 int msgCount = 0;
Willy Tu11d68892022-01-20 10:37:34 -0800637 i2c_msg i2cmsg[2] = {};
Yong Li7dc4ac02019-08-23 17:44:32 +0800638 if (writeCount)
639 {
640 // Data will be writtern to the slave address
641 i2cmsg[msgCount].addr = slaveAddr;
642 i2cmsg[msgCount].flags = 0x00;
643 i2cmsg[msgCount].len = writeCount;
644 i2cmsg[msgCount].buf = writeData.data();
645 msgCount++;
646 }
647 if (readCount)
648 {
649 // Data will be read into the buffer from the slave address
650 i2cmsg[msgCount].addr = slaveAddr;
651 i2cmsg[msgCount].flags = I2C_M_RD;
652 i2cmsg[msgCount].len = readCount;
653 i2cmsg[msgCount].buf = readBuf.data();
654 msgCount++;
655 }
656
Willy Tu11d68892022-01-20 10:37:34 -0800657 i2c_rdwr_ioctl_data msgReadWrite = {};
Yong Li7dc4ac02019-08-23 17:44:32 +0800658 msgReadWrite.msgs = i2cmsg;
659 msgReadWrite.nmsgs = msgCount;
660
661 // Perform the combined write/read
662 int ret = ::ioctl(i2cDev, I2C_RDWR, &msgReadWrite);
663 ::close(i2cDev);
664
665 if (ret < 0)
666 {
667 log<level::ERR>("I2C WR Failed!",
668 phosphor::logging::entry("RET=%d", ret));
669 return ipmi::ccUnspecifiedError;
670 }
671 if (readCount)
672 {
673 readBuf.resize(msgReadWrite.msgs[msgCount - 1].len);
674 }
675
676 return ipmi::ccSuccess;
677}
678
Tom Josephbe703f72017-03-09 12:34:35 +0530679} // namespace ipmi