blob: 302c0b719337698ebb3533f6331cb77a8ee7dd67 [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
Vernon Mauery6a98fe72019-03-11 15:57:48 -070011#include <ipmid/utils.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070012#include <phosphor-logging/elog-errors.hpp>
13#include <phosphor-logging/log.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070014#include <sdbusplus/message/types.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070015#include <xyz/openbmc_project/Common/error.hpp>
16
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050017#include <algorithm>
18#include <chrono>
19
Tom Josephbe703f72017-03-09 12:34:35 +053020namespace ipmi
21{
22
Ratan Guptacc8feb42017-07-25 21:52:10 +053023using namespace phosphor::logging;
24using namespace sdbusplus::xyz::openbmc_project::Common::Error;
25
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -050026namespace network
27{
28
29/** @brief checks if the given ip is Link Local Ip or not.
Patrick Venture0b02be92018-08-31 11:55:55 -070030 * @param[in] ipaddress - IPAddress.
31 */
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -050032bool isLinkLocalIP(const std::string& ipaddress);
33
Patrick Venture0b02be92018-08-31 11:55:55 -070034} // namespace network
Ratan Guptacc8feb42017-07-25 21:52:10 +053035
Patrick Venture0b02be92018-08-31 11:55:55 -070036// TODO There may be cases where an interface is implemented by multiple
Ratan Guptacc8feb42017-07-25 21:52:10 +053037// objects,to handle such cases we are interested on that object
38// which are on interested busname.
39// Currently mapper doesn't give the readable busname(gives busid) so we can't
40// use busname to find the object,will do later once the support is there.
41
Patrick Williams5d82f472022-07-22 19:26:53 -050042DbusObjectInfo getDbusObject(sdbusplus::bus_t& bus,
Ratan Gupta01d4bd12017-08-07 15:53:25 +053043 const std::string& interface,
Ratan Guptacc8feb42017-07-25 21:52:10 +053044 const std::string& serviceRoot,
45 const std::string& match)
46{
47 std::vector<DbusInterface> interfaces;
48 interfaces.emplace_back(interface);
49
Ratan Guptacc8feb42017-07-25 21:52:10 +053050 auto depth = 0;
51
Patrick Venture0b02be92018-08-31 11:55:55 -070052 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ,
53 MAPPER_INTF, "GetSubTree");
Ratan Guptacc8feb42017-07-25 21:52:10 +053054
55 mapperCall.append(serviceRoot, depth, interfaces);
56
57 auto mapperReply = bus.call(mapperCall);
58 if (mapperReply.is_method_error())
59 {
60 log<level::ERR>("Error in mapper call");
61 elog<InternalFailure>();
62 }
63
64 ObjectTree objectTree;
65 mapperReply.read(objectTree);
66
67 if (objectTree.empty())
68 {
Patrick Venturef0c48782017-09-21 18:48:51 -070069 log<level::ERR>("No Object has implemented the interface",
Ratan Guptacc8feb42017-07-25 21:52:10 +053070 entry("INTERFACE=%s", interface.c_str()));
71 elog<InternalFailure>();
72 }
73
74 DbusObjectInfo objectInfo;
75
76 // if match is empty then return the first object
Patrick Venture0b02be92018-08-31 11:55:55 -070077 if (match == "")
Ratan Guptacc8feb42017-07-25 21:52:10 +053078 {
Patrick Venture0b02be92018-08-31 11:55:55 -070079 objectInfo = std::make_pair(
80 objectTree.begin()->first,
Ratan Guptacc8feb42017-07-25 21:52:10 +053081 std::move(objectTree.begin()->second.begin()->first));
82 return objectInfo;
83 }
84
85 // else search the match string in the object path
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050086 auto found = std::find_if(objectTree.begin(), objectTree.end(),
87 [&match](const auto& object) {
88 return (object.first.find(match) != std::string::npos);
89 });
Ratan Guptacc8feb42017-07-25 21:52:10 +053090
Patrick Venture2e633522018-10-13 13:51:06 -070091 if (found == objectTree.end())
Ratan Guptacc8feb42017-07-25 21:52:10 +053092 {
93 log<level::ERR>("Failed to find object which matches",
94 entry("MATCH=%s", match.c_str()));
95 elog<InternalFailure>();
Patrick Venture2e633522018-10-13 13:51:06 -070096 // elog<> throws an exception.
Ratan Guptacc8feb42017-07-25 21:52:10 +053097 }
Patrick Venture2e633522018-10-13 13:51:06 -070098
99 return make_pair(found->first, std::move(found->second.begin()->first));
Ratan Guptacc8feb42017-07-25 21:52:10 +0530100}
101
Patrick Williams5d82f472022-07-22 19:26:53 -0500102Value getDbusProperty(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -0700103 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800104 const std::string& property,
105 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +0530106{
Ratan Guptacc8feb42017-07-25 21:52:10 +0530107 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)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500203{}
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700204
Patrick Venture0b02be92018-08-31 11:55:55 -0700205ServiceCache::ServiceCache(std::string&& intf, std::string&& path) :
Vernon Mauery54012502018-11-07 10:17:31 -0800206 intf(std::move(intf)), path(std::move(path)), cachedService(std::nullopt),
207 cachedBusName(std::nullopt)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500208{}
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700209
Patrick Williams5d82f472022-07-22 19:26:53 -0500210const std::string& ServiceCache::getService(sdbusplus::bus_t& bus)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700211{
212 if (!isValid(bus))
213 {
214 cachedBusName = bus.get_unique_name();
215 cachedService = ::ipmi::getService(bus, intf, path);
216 }
217 return cachedService.value();
218}
219
220void ServiceCache::invalidate()
221{
Vernon Mauery54012502018-11-07 10:17:31 -0800222 cachedBusName = std::nullopt;
223 cachedService = std::nullopt;
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700224}
225
Patrick Williams5d82f472022-07-22 19:26:53 -0500226sdbusplus::message_t ServiceCache::newMethodCall(sdbusplus::bus_t& bus,
227 const char* intf,
228 const char* method)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700229{
Patrick Venture0b02be92018-08-31 11:55:55 -0700230 return bus.new_method_call(getService(bus).c_str(), path.c_str(), intf,
231 method);
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700232}
233
Patrick Williams5d82f472022-07-22 19:26:53 -0500234bool ServiceCache::isValid(sdbusplus::bus_t& bus) const
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700235{
236 return cachedService && cachedBusName == bus.get_unique_name();
237}
238
Patrick Williams5d82f472022-07-22 19:26:53 -0500239std::string getService(sdbusplus::bus_t& bus, const std::string& intf,
Tom Josephbe703f72017-03-09 12:34:35 +0530240 const std::string& path)
241{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500242 auto mapperCall = bus.new_method_call("xyz.openbmc_project.ObjectMapper",
243 "/xyz/openbmc_project/object_mapper",
244 "xyz.openbmc_project.ObjectMapper",
245 "GetObject");
Tom Josephbe703f72017-03-09 12:34:35 +0530246
247 mapperCall.append(path);
248 mapperCall.append(std::vector<std::string>({intf}));
249
250 auto mapperResponseMsg = bus.call(mapperCall);
251
252 if (mapperResponseMsg.is_method_error())
253 {
254 throw std::runtime_error("ERROR in mapper call");
255 }
256
257 std::map<std::string, std::vector<std::string>> mapperResponse;
258 mapperResponseMsg.read(mapperResponse);
259
260 if (mapperResponse.begin() == mapperResponse.end())
261 {
262 throw std::runtime_error("ERROR in reading the mapper response");
263 }
264
265 return mapperResponse.begin()->first;
266}
267
Patrick Williams5d82f472022-07-22 19:26:53 -0500268ipmi::ObjectTree getAllDbusObjects(sdbusplus::bus_t& bus,
Ratan Guptab8e99552017-07-27 07:07:48 +0530269 const std::string& serviceRoot,
270 const std::string& interface,
271 const std::string& match)
272{
273 std::vector<std::string> interfaces;
274 interfaces.emplace_back(interface);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530275
Ratan Guptab8e99552017-07-27 07:07:48 +0530276 auto depth = 0;
277
Patrick Venture0b02be92018-08-31 11:55:55 -0700278 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ,
279 MAPPER_INTF, "GetSubTree");
Ratan Guptab8e99552017-07-27 07:07:48 +0530280
281 mapperCall.append(serviceRoot, depth, interfaces);
282
283 auto mapperReply = bus.call(mapperCall);
284 if (mapperReply.is_method_error())
285 {
286 log<level::ERR>("Error in mapper call",
Patrick Venture0b02be92018-08-31 11:55:55 -0700287 entry("SERVICEROOT=%s", serviceRoot.c_str()),
Ratan Guptab8e99552017-07-27 07:07:48 +0530288 entry("INTERFACE=%s", interface.c_str()));
289
290 elog<InternalFailure>();
291 }
292
293 ObjectTree objectTree;
294 mapperReply.read(objectTree);
295
296 for (auto it = objectTree.begin(); it != objectTree.end();)
297 {
298 if (it->first.find(match) == std::string::npos)
299 {
300 it = objectTree.erase(it);
301 }
302 else
303 {
304 ++it;
305 }
306 }
307
308 return objectTree;
309}
310
Patrick Williams5d82f472022-07-22 19:26:53 -0500311void deleteAllDbusObjects(sdbusplus::bus_t& bus, const std::string& serviceRoot,
Ratan Guptab8e99552017-07-27 07:07:48 +0530312 const std::string& interface,
313 const std::string& match)
314{
315 try
316 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700317 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, match);
Ratan Guptab8e99552017-07-27 07:07:48 +0530318
319 for (auto& object : objectTree)
320 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700321 method_no_args::callDbusMethod(bus, object.second.begin()->first,
322 object.first, DELETE_INTERFACE,
323 "Delete");
Ratan Guptab8e99552017-07-27 07:07:48 +0530324 }
325 }
Patrick Williams5d82f472022-07-22 19:26:53 -0500326 catch (const sdbusplus::exception_t& e)
Ratan Guptab8e99552017-07-27 07:07:48 +0530327 {
Vernon Mauery7a614182018-11-27 12:54:52 -0800328 log<level::INFO>("sdbusplus exception - Unable to delete the objects",
329 entry("ERROR=%s", e.what()),
Ratan Guptab8e99552017-07-27 07:07:48 +0530330 entry("INTERFACE=%s", interface.c_str()),
331 entry("SERVICE=%s", serviceRoot.c_str()));
332 }
333}
334
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700335static inline std::string convertToString(const InterfaceList& interfaces)
336{
337 std::string intfStr;
338 for (const auto& intf : interfaces)
339 {
340 intfStr += "," + intf;
341 }
342 return intfStr;
343}
344
Patrick Williams5d82f472022-07-22 19:26:53 -0500345ObjectTree getAllAncestors(sdbusplus::bus_t& bus, const std::string& path,
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530346 InterfaceList&& interfaces)
347{
Patrick Venture0b02be92018-08-31 11:55:55 -0700348 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ,
349 MAPPER_INTF, "GetAncestors");
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530350 mapperCall.append(path, interfaces);
351
352 auto mapperReply = bus.call(mapperCall);
353 if (mapperReply.is_method_error())
354 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700355 log<level::ERR>(
356 "Error in mapper call", entry("PATH=%s", path.c_str()),
357 entry("INTERFACES=%s", convertToString(interfaces).c_str()));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530358
359 elog<InternalFailure>();
360 }
361
362 ObjectTree objectTree;
363 mapperReply.read(objectTree);
364
365 if (objectTree.empty())
366 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700367 log<level::ERR>(
368 "No Object has implemented the interface",
369 entry("PATH=%s", path.c_str()),
370 entry("INTERFACES=%s", convertToString(interfaces).c_str()));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530371 elog<InternalFailure>();
372 }
373
374 return objectTree;
375}
Ratan Guptab8e99552017-07-27 07:07:48 +0530376
377namespace method_no_args
378{
379
Patrick Williams5d82f472022-07-22 19:26:53 -0500380void callDbusMethod(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -0700381 const std::string& objPath, const std::string& interface,
Ratan Guptab8e99552017-07-27 07:07:48 +0530382 const std::string& method)
383
384{
Patrick Venture0b02be92018-08-31 11:55:55 -0700385 auto busMethod = bus.new_method_call(service.c_str(), objPath.c_str(),
386 interface.c_str(), method.c_str());
Ratan Guptab8e99552017-07-27 07:07:48 +0530387
388 auto reply = bus.call(busMethod);
389
390 if (reply.is_method_error())
391 {
392 log<level::ERR>("Failed to execute method",
393 entry("METHOD=%s", method.c_str()),
394 entry("PATH=%s", objPath.c_str()),
395 entry("INTERFACE=%s", interface.c_str()));
396 elog<InternalFailure>();
397 }
398}
399
Patrick Venture0b02be92018-08-31 11:55:55 -0700400} // namespace method_no_args
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700401
402/********* Begin co-routine yielding alternatives ***************/
403
Vijay Khemka31655692020-03-04 15:22:12 -0800404boost::system::error_code getService(Context::ptr ctx, const std::string& intf,
405 const std::string& path,
406 std::string& service)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700407{
408 boost::system::error_code ec;
409 std::map<std::string, std::vector<std::string>> mapperResponse =
410 ctx->bus->yield_method_call<decltype(mapperResponse)>(
411 ctx->yield, ec, "xyz.openbmc_project.ObjectMapper",
412 "/xyz/openbmc_project/object_mapper",
Jason M. Billsf5967982020-03-06 10:42:08 -0800413 "xyz.openbmc_project.ObjectMapper", "GetObject", path,
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700414 std::vector<std::string>({intf}));
415
416 if (!ec)
417 {
418 service = std::move(mapperResponse.begin()->first);
419 }
420 return ec;
421}
422
423boost::system::error_code getDbusObject(Context::ptr ctx,
424 const std::string& interface,
425 const std::string& subtreePath,
426 const std::string& match,
427 DbusObjectInfo& dbusObject)
428{
429 std::vector<DbusInterface> interfaces;
430 interfaces.emplace_back(interface);
431
432 auto depth = 0;
433 boost::system::error_code ec;
434 ObjectTree objectTree = ctx->bus->yield_method_call<ObjectTree>(
435 ctx->yield, ec, MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF, "GetSubTree",
436 subtreePath, depth, interfaces);
437
438 if (ec)
439 {
440 return ec;
441 }
442
443 if (objectTree.empty())
444 {
445 log<level::ERR>("No Object has implemented the interface",
446 entry("INTERFACE=%s", interface.c_str()),
447 entry("NETFN=%x", ctx->netFn),
448 entry("CMD=%x,", ctx->cmd));
449 return boost::system::errc::make_error_code(
450 boost::system::errc::no_such_process);
451 }
452
453 // if match is empty then return the first object
454 if (match == "")
455 {
456 dbusObject = std::make_pair(
457 std::move(objectTree.begin()->first),
458 std::move(objectTree.begin()->second.begin()->first));
459 return ec;
460 }
461
462 // else search the match string in the object path
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500463 auto found = std::find_if(objectTree.begin(), objectTree.end(),
464 [&match](const auto& object) {
465 return (object.first.find(match) != std::string::npos);
466 });
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700467
468 if (found == objectTree.end())
469 {
470 log<level::ERR>("Failed to find object which matches",
471 entry("MATCH=%s", match.c_str()),
472 entry("NETFN=%x", ctx->netFn),
473 entry("CMD=%x,", ctx->cmd));
474 // set ec
475 return boost::system::errc::make_error_code(
476 boost::system::errc::no_such_file_or_directory);
477 }
478
479 dbusObject = std::make_pair(std::move(found->first),
480 std::move(found->second.begin()->first));
481 return ec;
482}
483
484boost::system::error_code getAllDbusProperties(Context::ptr ctx,
485 const std::string& service,
486 const std::string& objPath,
487 const std::string& interface,
488 PropertyMap& properties)
489{
490 boost::system::error_code ec;
491 properties = ctx->bus->yield_method_call<PropertyMap>(
492 ctx->yield, ec, service.c_str(), objPath.c_str(), PROP_INTF,
493 METHOD_GET_ALL, interface);
494 return ec;
495}
496
497boost::system::error_code
498 setDbusProperty(Context::ptr ctx, const std::string& service,
499 const std::string& objPath, const std::string& interface,
500 const std::string& property, const Value& value)
501{
502 boost::system::error_code ec;
503 ctx->bus->yield_method_call(ctx->yield, ec, service.c_str(),
504 objPath.c_str(), PROP_INTF, METHOD_SET,
505 interface, property, value);
506 return ec;
507}
508
509boost::system::error_code getAllDbusObjects(Context::ptr ctx,
510 const std::string& serviceRoot,
511 const std::string& interface,
512 const std::string& match,
513 ObjectTree& objectTree)
514{
515 boost::system::error_code ec;
516 std::vector<std::string> interfaces;
517 interfaces.emplace_back(interface);
518
519 auto depth = 0;
520
521 objectTree = ctx->bus->yield_method_call<ObjectTree>(
522 ctx->yield, ec, MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF, "GetSubTree",
523 serviceRoot, depth, interfaces);
524
525 if (ec)
526 {
527 return ec;
528 }
529
530 for (auto it = objectTree.begin(); it != objectTree.end();)
531 {
532 if (it->first.find(match) == std::string::npos)
533 {
534 it = objectTree.erase(it);
535 }
536 else
537 {
538 ++it;
539 }
540 }
541
542 return ec;
543}
544
545boost::system::error_code deleteAllDbusObjects(Context::ptr ctx,
546 const std::string& serviceRoot,
547 const std::string& interface,
548 const std::string& match)
549{
550 ObjectTree objectTree;
551 boost::system::error_code ec =
552 getAllDbusObjects(ctx, serviceRoot, interface, match, objectTree);
553 if (ec)
554 {
555 return ec;
556 }
557
558 for (auto& object : objectTree)
559 {
560 ctx->bus->yield_method_call(ctx->yield, ec,
561 object.second.begin()->first, object.first,
562 DELETE_INTERFACE, "Delete");
563 if (ec)
564 {
565 log<level::ERR>("Failed to delete all objects",
566 entry("INTERFACE=%s", interface.c_str()),
567 entry("SERVICE=%s", serviceRoot.c_str()),
568 entry("NETFN=%x", ctx->netFn),
569 entry("CMD=%x,", ctx->cmd),
570 entry("ERROR=%s", ec.message().c_str()));
571 break;
572 }
573 }
574 return ec;
575}
576
577boost::system::error_code getManagedObjects(Context::ptr ctx,
578 const std::string& service,
579 const std::string& objPath,
580 ObjectValueTree& objects)
581{
582 boost::system::error_code ec;
583 objects = ctx->bus->yield_method_call<ipmi::ObjectValueTree>(
584 ctx->yield, ec, service.c_str(), objPath.c_str(),
585 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
586 return ec;
587}
588
589boost::system::error_code getAllAncestors(Context::ptr ctx,
590 const std::string& path,
591 const InterfaceList& interfaces,
592 ObjectTree& objectTree)
593{
594 std::string interfaceList = convertToString(interfaces);
595
596 boost::system::error_code ec;
597 objectTree = ctx->bus->yield_method_call<ObjectTree>(
598 ctx->yield, ec, MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
599 "GetAncestors", path, interfaceList);
600
601 if (ec)
602 {
603 return ec;
604 }
605
606 if (objectTree.empty())
607 {
608 log<level::ERR>("No Object has implemented the interface",
609 entry("PATH=%s", path.c_str()),
610 entry("INTERFACES=%s", interfaceList.c_str()));
611 elog<InternalFailure>();
612 }
613
614 return ec;
615}
616
Albert Zhangb53049e2022-04-02 15:39:51 +0800617boost::system::error_code callDbusMethod(Context::ptr ctx,
618 const std::string& service,
619 const std::string& objPath,
620 const std::string& interface,
621 const std::string& method)
622{
623 boost::system::error_code ec;
624 ctx->bus->yield_method_call(ctx->yield, ec, service, objPath, interface,
625 method);
626 return ec;
627}
628
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700629/********* End co-routine yielding alternatives ***************/
630
Yong Li7dc4ac02019-08-23 17:44:32 +0800631ipmi::Cc i2cWriteRead(std::string i2cBus, const uint8_t slaveAddr,
632 std::vector<uint8_t> writeData,
633 std::vector<uint8_t>& readBuf)
634{
635 // Open the i2c device, for low-level combined data write/read
636 int i2cDev = ::open(i2cBus.c_str(), O_RDWR | O_CLOEXEC);
637 if (i2cDev < 0)
638 {
639 log<level::ERR>("Failed to open i2c bus",
640 phosphor::logging::entry("BUS=%s", i2cBus.c_str()));
641 return ipmi::ccInvalidFieldRequest;
642 }
643
644 const size_t writeCount = writeData.size();
645 const size_t readCount = readBuf.size();
646 int msgCount = 0;
Willy Tu11d68892022-01-20 10:37:34 -0800647 i2c_msg i2cmsg[2] = {};
Yong Li7dc4ac02019-08-23 17:44:32 +0800648 if (writeCount)
649 {
650 // Data will be writtern to the slave address
651 i2cmsg[msgCount].addr = slaveAddr;
652 i2cmsg[msgCount].flags = 0x00;
653 i2cmsg[msgCount].len = writeCount;
654 i2cmsg[msgCount].buf = writeData.data();
655 msgCount++;
656 }
657 if (readCount)
658 {
659 // Data will be read into the buffer from the slave address
660 i2cmsg[msgCount].addr = slaveAddr;
661 i2cmsg[msgCount].flags = I2C_M_RD;
662 i2cmsg[msgCount].len = readCount;
663 i2cmsg[msgCount].buf = readBuf.data();
664 msgCount++;
665 }
666
Willy Tu11d68892022-01-20 10:37:34 -0800667 i2c_rdwr_ioctl_data msgReadWrite = {};
Yong Li7dc4ac02019-08-23 17:44:32 +0800668 msgReadWrite.msgs = i2cmsg;
669 msgReadWrite.nmsgs = msgCount;
670
671 // Perform the combined write/read
672 int ret = ::ioctl(i2cDev, I2C_RDWR, &msgReadWrite);
673 ::close(i2cDev);
674
675 if (ret < 0)
676 {
677 log<level::ERR>("I2C WR Failed!",
678 phosphor::logging::entry("RET=%d", ret));
679 return ipmi::ccUnspecifiedError;
680 }
681 if (readCount)
682 {
683 readBuf.resize(msgReadWrite.msgs[msgCount - 1].len);
684 }
685
686 return ipmi::ccSuccess;
687}
688
Tom Josephbe703f72017-03-09 12:34:35 +0530689} // namespace ipmi