blob: 1c94aad17e7b921192a7a7fc1ef007cef64d5e8f [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;
Willy Tu523e2d12023-09-05 11:36:48 -070024using namespace sdbusplus::error::xyz::openbmc_project::common;
Ratan Guptacc8feb42017-07-25 21:52:10 +053025
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);
Ratan Guptacc8feb42017-07-25 21:52:10 +053058
59 ObjectTree objectTree;
60 mapperReply.read(objectTree);
61
62 if (objectTree.empty())
63 {
Patrick Venturef0c48782017-09-21 18:48:51 -070064 log<level::ERR>("No Object has implemented the interface",
Ratan Guptacc8feb42017-07-25 21:52:10 +053065 entry("INTERFACE=%s", interface.c_str()));
66 elog<InternalFailure>();
67 }
68
69 DbusObjectInfo objectInfo;
70
71 // if match is empty then return the first object
Patrick Venture0b02be92018-08-31 11:55:55 -070072 if (match == "")
Ratan Guptacc8feb42017-07-25 21:52:10 +053073 {
Patrick Venture0b02be92018-08-31 11:55:55 -070074 objectInfo = std::make_pair(
75 objectTree.begin()->first,
Ratan Guptacc8feb42017-07-25 21:52:10 +053076 std::move(objectTree.begin()->second.begin()->first));
77 return objectInfo;
78 }
79
80 // else search the match string in the object path
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050081 auto found = std::find_if(objectTree.begin(), objectTree.end(),
82 [&match](const auto& object) {
83 return (object.first.find(match) != std::string::npos);
84 });
Ratan Guptacc8feb42017-07-25 21:52:10 +053085
Patrick Venture2e633522018-10-13 13:51:06 -070086 if (found == objectTree.end())
Ratan Guptacc8feb42017-07-25 21:52:10 +053087 {
88 log<level::ERR>("Failed to find object which matches",
89 entry("MATCH=%s", match.c_str()));
90 elog<InternalFailure>();
Patrick Venture2e633522018-10-13 13:51:06 -070091 // elog<> throws an exception.
Ratan Guptacc8feb42017-07-25 21:52:10 +053092 }
Patrick Venture2e633522018-10-13 13:51:06 -070093
94 return make_pair(found->first, std::move(found->second.begin()->first));
Ratan Guptacc8feb42017-07-25 21:52:10 +053095}
96
Patrick Williams5d82f472022-07-22 19:26:53 -050097Value getDbusProperty(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -070098 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -080099 const std::string& property,
100 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +0530101{
Ratan Guptacc8feb42017-07-25 21:52:10 +0530102 Value value;
103
Patrick Venture0b02be92018-08-31 11:55:55 -0700104 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
105 PROP_INTF, METHOD_GET);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530106
107 method.append(interface, property);
108
Kun Yi5dcf41e2019-03-05 14:02:51 -0800109 auto reply = bus.call(method, timeout.count());
Ratan Guptacc8feb42017-07-25 21:52:10 +0530110 reply.read(value);
111
112 return value;
113}
114
Patrick Williams5d82f472022-07-22 19:26:53 -0500115PropertyMap getAllDbusProperties(sdbusplus::bus_t& bus,
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530116 const std::string& service,
Ratan Guptacc8feb42017-07-25 21:52:10 +0530117 const std::string& objPath,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800118 const std::string& interface,
119 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +0530120{
121 PropertyMap properties;
Ratan Guptacc8feb42017-07-25 21:52:10 +0530122
Patrick Venture0b02be92018-08-31 11:55:55 -0700123 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
124 PROP_INTF, METHOD_GET_ALL);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530125
126 method.append(interface);
127
Kun Yi5dcf41e2019-03-05 14:02:51 -0800128 auto reply = bus.call(method, timeout.count());
Ratan Guptacc8feb42017-07-25 21:52:10 +0530129 reply.read(properties);
George Liu3e3cc352023-07-26 15:59:31 +0800130
Ratan Guptacc8feb42017-07-25 21:52:10 +0530131 return properties;
132}
133
Patrick Williams5d82f472022-07-22 19:26:53 -0500134ObjectValueTree getManagedObjects(sdbusplus::bus_t& bus,
Patrick Venture0b02be92018-08-31 11:55:55 -0700135 const std::string& service,
136 const std::string& objPath)
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600137{
138 ipmi::ObjectValueTree interfaces;
139
Patrick Venture0b02be92018-08-31 11:55:55 -0700140 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
141 "org.freedesktop.DBus.ObjectManager",
142 "GetManagedObjects");
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600143 auto reply = bus.call(method);
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600144 reply.read(interfaces);
George Liu3e3cc352023-07-26 15:59:31 +0800145
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600146 return interfaces;
147}
148
Patrick Williams5d82f472022-07-22 19:26:53 -0500149void setDbusProperty(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -0700150 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800151 const std::string& property, const Value& value,
152 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +0530153{
Patrick Venture0b02be92018-08-31 11:55:55 -0700154 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
155 PROP_INTF, METHOD_SET);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530156
157 method.append(interface, property, value);
158
Kun Yi5dcf41e2019-03-05 14:02:51 -0800159 if (!bus.call(method, timeout.count()))
Ratan Guptacc8feb42017-07-25 21:52:10 +0530160 {
161 log<level::ERR>("Failed to set property",
162 entry("PROPERTY=%s", property.c_str()),
Patrick Venture0b02be92018-08-31 11:55:55 -0700163 entry("PATH=%s", objPath.c_str()),
164 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptacc8feb42017-07-25 21:52:10 +0530165 elog<InternalFailure>();
166 }
Ratan Guptacc8feb42017-07-25 21:52:10 +0530167}
168
Patrick Venture0b02be92018-08-31 11:55:55 -0700169ServiceCache::ServiceCache(const std::string& intf, const std::string& path) :
Vernon Mauery54012502018-11-07 10:17:31 -0800170 intf(intf), path(path), cachedService(std::nullopt),
171 cachedBusName(std::nullopt)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500172{}
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700173
Patrick Venture0b02be92018-08-31 11:55:55 -0700174ServiceCache::ServiceCache(std::string&& intf, std::string&& path) :
Vernon Mauery54012502018-11-07 10:17:31 -0800175 intf(std::move(intf)), path(std::move(path)), cachedService(std::nullopt),
176 cachedBusName(std::nullopt)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500177{}
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700178
Patrick Williams5d82f472022-07-22 19:26:53 -0500179const std::string& ServiceCache::getService(sdbusplus::bus_t& bus)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700180{
181 if (!isValid(bus))
182 {
183 cachedBusName = bus.get_unique_name();
184 cachedService = ::ipmi::getService(bus, intf, path);
185 }
186 return cachedService.value();
187}
188
189void ServiceCache::invalidate()
190{
Vernon Mauery54012502018-11-07 10:17:31 -0800191 cachedBusName = std::nullopt;
192 cachedService = std::nullopt;
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700193}
194
Patrick Williams5d82f472022-07-22 19:26:53 -0500195sdbusplus::message_t ServiceCache::newMethodCall(sdbusplus::bus_t& bus,
196 const char* intf,
197 const char* method)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700198{
Patrick Venture0b02be92018-08-31 11:55:55 -0700199 return bus.new_method_call(getService(bus).c_str(), path.c_str(), intf,
200 method);
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700201}
202
Patrick Williams5d82f472022-07-22 19:26:53 -0500203bool ServiceCache::isValid(sdbusplus::bus_t& bus) const
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700204{
205 return cachedService && cachedBusName == bus.get_unique_name();
206}
207
Patrick Williams5d82f472022-07-22 19:26:53 -0500208std::string getService(sdbusplus::bus_t& bus, const std::string& intf,
Tom Josephbe703f72017-03-09 12:34:35 +0530209 const std::string& path)
210{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500211 auto mapperCall = bus.new_method_call("xyz.openbmc_project.ObjectMapper",
212 "/xyz/openbmc_project/object_mapper",
213 "xyz.openbmc_project.ObjectMapper",
214 "GetObject");
Tom Josephbe703f72017-03-09 12:34:35 +0530215
216 mapperCall.append(path);
217 mapperCall.append(std::vector<std::string>({intf}));
218
219 auto mapperResponseMsg = bus.call(mapperCall);
220
Tom Josephbe703f72017-03-09 12:34:35 +0530221 std::map<std::string, std::vector<std::string>> mapperResponse;
222 mapperResponseMsg.read(mapperResponse);
223
224 if (mapperResponse.begin() == mapperResponse.end())
225 {
226 throw std::runtime_error("ERROR in reading the mapper response");
227 }
228
229 return mapperResponse.begin()->first;
230}
231
Patrick Williams5d82f472022-07-22 19:26:53 -0500232ipmi::ObjectTree getAllDbusObjects(sdbusplus::bus_t& bus,
Ratan Guptab8e99552017-07-27 07:07:48 +0530233 const std::string& serviceRoot,
234 const std::string& interface,
235 const std::string& match)
236{
237 std::vector<std::string> interfaces;
238 interfaces.emplace_back(interface);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530239
Ratan Guptab8e99552017-07-27 07:07:48 +0530240 auto depth = 0;
241
Patrick Venture0b02be92018-08-31 11:55:55 -0700242 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ,
243 MAPPER_INTF, "GetSubTree");
Ratan Guptab8e99552017-07-27 07:07:48 +0530244
245 mapperCall.append(serviceRoot, depth, interfaces);
246
247 auto mapperReply = bus.call(mapperCall);
Ratan Guptab8e99552017-07-27 07:07:48 +0530248 ObjectTree objectTree;
249 mapperReply.read(objectTree);
250
251 for (auto it = objectTree.begin(); it != objectTree.end();)
252 {
253 if (it->first.find(match) == std::string::npos)
254 {
255 it = objectTree.erase(it);
256 }
257 else
258 {
259 ++it;
260 }
261 }
262
263 return objectTree;
264}
265
Patrick Williams5d82f472022-07-22 19:26:53 -0500266void deleteAllDbusObjects(sdbusplus::bus_t& bus, const std::string& serviceRoot,
Ratan Guptab8e99552017-07-27 07:07:48 +0530267 const std::string& interface,
268 const std::string& match)
269{
270 try
271 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700272 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, match);
Ratan Guptab8e99552017-07-27 07:07:48 +0530273
274 for (auto& object : objectTree)
275 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700276 method_no_args::callDbusMethod(bus, object.second.begin()->first,
277 object.first, DELETE_INTERFACE,
278 "Delete");
Ratan Guptab8e99552017-07-27 07:07:48 +0530279 }
280 }
Patrick Williams5d82f472022-07-22 19:26:53 -0500281 catch (const sdbusplus::exception_t& e)
Ratan Guptab8e99552017-07-27 07:07:48 +0530282 {
Vernon Mauery7a614182018-11-27 12:54:52 -0800283 log<level::INFO>("sdbusplus exception - Unable to delete the objects",
284 entry("ERROR=%s", e.what()),
Ratan Guptab8e99552017-07-27 07:07:48 +0530285 entry("INTERFACE=%s", interface.c_str()),
286 entry("SERVICE=%s", serviceRoot.c_str()));
287 }
288}
289
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700290static inline std::string convertToString(const InterfaceList& interfaces)
291{
292 std::string intfStr;
293 for (const auto& intf : interfaces)
294 {
295 intfStr += "," + intf;
296 }
297 return intfStr;
298}
299
Patrick Williams5d82f472022-07-22 19:26:53 -0500300ObjectTree getAllAncestors(sdbusplus::bus_t& bus, const std::string& path,
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530301 InterfaceList&& interfaces)
302{
Patrick Venture0b02be92018-08-31 11:55:55 -0700303 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ,
304 MAPPER_INTF, "GetAncestors");
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530305 mapperCall.append(path, interfaces);
306
307 auto mapperReply = bus.call(mapperCall);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530308 ObjectTree objectTree;
309 mapperReply.read(objectTree);
310
311 if (objectTree.empty())
312 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700313 log<level::ERR>(
314 "No Object has implemented the interface",
315 entry("PATH=%s", path.c_str()),
316 entry("INTERFACES=%s", convertToString(interfaces).c_str()));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530317 elog<InternalFailure>();
318 }
319
320 return objectTree;
321}
Ratan Guptab8e99552017-07-27 07:07:48 +0530322
323namespace method_no_args
324{
325
Patrick Williams5d82f472022-07-22 19:26:53 -0500326void callDbusMethod(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -0700327 const std::string& objPath, const std::string& interface,
Ratan Guptab8e99552017-07-27 07:07:48 +0530328 const std::string& method)
329
330{
Patrick Venture0b02be92018-08-31 11:55:55 -0700331 auto busMethod = bus.new_method_call(service.c_str(), objPath.c_str(),
332 interface.c_str(), method.c_str());
Ratan Guptab8e99552017-07-27 07:07:48 +0530333 auto reply = bus.call(busMethod);
Ratan Guptab8e99552017-07-27 07:07:48 +0530334}
335
Patrick Venture0b02be92018-08-31 11:55:55 -0700336} // namespace method_no_args
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700337
338/********* Begin co-routine yielding alternatives ***************/
339
Vijay Khemka31655692020-03-04 15:22:12 -0800340boost::system::error_code getService(Context::ptr ctx, const std::string& intf,
341 const std::string& path,
342 std::string& service)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700343{
344 boost::system::error_code ec;
345 std::map<std::string, std::vector<std::string>> mapperResponse =
346 ctx->bus->yield_method_call<decltype(mapperResponse)>(
347 ctx->yield, ec, "xyz.openbmc_project.ObjectMapper",
348 "/xyz/openbmc_project/object_mapper",
Jason M. Billsf5967982020-03-06 10:42:08 -0800349 "xyz.openbmc_project.ObjectMapper", "GetObject", path,
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700350 std::vector<std::string>({intf}));
351
352 if (!ec)
353 {
354 service = std::move(mapperResponse.begin()->first);
355 }
356 return ec;
357}
358
359boost::system::error_code getDbusObject(Context::ptr ctx,
360 const std::string& interface,
361 const std::string& subtreePath,
362 const std::string& match,
363 DbusObjectInfo& dbusObject)
364{
365 std::vector<DbusInterface> interfaces;
366 interfaces.emplace_back(interface);
367
368 auto depth = 0;
369 boost::system::error_code ec;
370 ObjectTree objectTree = ctx->bus->yield_method_call<ObjectTree>(
371 ctx->yield, ec, MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF, "GetSubTree",
372 subtreePath, depth, interfaces);
373
374 if (ec)
375 {
376 return ec;
377 }
378
379 if (objectTree.empty())
380 {
381 log<level::ERR>("No Object has implemented the interface",
382 entry("INTERFACE=%s", interface.c_str()),
383 entry("NETFN=%x", ctx->netFn),
384 entry("CMD=%x,", ctx->cmd));
385 return boost::system::errc::make_error_code(
386 boost::system::errc::no_such_process);
387 }
388
389 // if match is empty then return the first object
390 if (match == "")
391 {
392 dbusObject = std::make_pair(
393 std::move(objectTree.begin()->first),
394 std::move(objectTree.begin()->second.begin()->first));
395 return ec;
396 }
397
398 // else search the match string in the object path
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500399 auto found = std::find_if(objectTree.begin(), objectTree.end(),
400 [&match](const auto& object) {
401 return (object.first.find(match) != std::string::npos);
402 });
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700403
404 if (found == objectTree.end())
405 {
406 log<level::ERR>("Failed to find object which matches",
407 entry("MATCH=%s", match.c_str()),
408 entry("NETFN=%x", ctx->netFn),
409 entry("CMD=%x,", ctx->cmd));
410 // set ec
411 return boost::system::errc::make_error_code(
412 boost::system::errc::no_such_file_or_directory);
413 }
414
415 dbusObject = std::make_pair(std::move(found->first),
416 std::move(found->second.begin()->first));
417 return ec;
418}
419
420boost::system::error_code getAllDbusProperties(Context::ptr ctx,
421 const std::string& service,
422 const std::string& objPath,
423 const std::string& interface,
424 PropertyMap& properties)
425{
426 boost::system::error_code ec;
427 properties = ctx->bus->yield_method_call<PropertyMap>(
428 ctx->yield, ec, service.c_str(), objPath.c_str(), PROP_INTF,
429 METHOD_GET_ALL, interface);
430 return ec;
431}
432
433boost::system::error_code
434 setDbusProperty(Context::ptr ctx, const std::string& service,
435 const std::string& objPath, const std::string& interface,
436 const std::string& property, const Value& value)
437{
438 boost::system::error_code ec;
439 ctx->bus->yield_method_call(ctx->yield, ec, service.c_str(),
440 objPath.c_str(), PROP_INTF, METHOD_SET,
441 interface, property, value);
442 return ec;
443}
444
445boost::system::error_code getAllDbusObjects(Context::ptr ctx,
446 const std::string& serviceRoot,
447 const std::string& interface,
448 const std::string& match,
449 ObjectTree& objectTree)
450{
451 boost::system::error_code ec;
452 std::vector<std::string> interfaces;
453 interfaces.emplace_back(interface);
454
455 auto depth = 0;
456
457 objectTree = ctx->bus->yield_method_call<ObjectTree>(
458 ctx->yield, ec, MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF, "GetSubTree",
459 serviceRoot, depth, interfaces);
460
461 if (ec)
462 {
463 return ec;
464 }
465
466 for (auto it = objectTree.begin(); it != objectTree.end();)
467 {
468 if (it->first.find(match) == std::string::npos)
469 {
470 it = objectTree.erase(it);
471 }
472 else
473 {
474 ++it;
475 }
476 }
477
478 return ec;
479}
480
481boost::system::error_code deleteAllDbusObjects(Context::ptr ctx,
482 const std::string& serviceRoot,
483 const std::string& interface,
484 const std::string& match)
485{
486 ObjectTree objectTree;
487 boost::system::error_code ec =
488 getAllDbusObjects(ctx, serviceRoot, interface, match, objectTree);
489 if (ec)
490 {
491 return ec;
492 }
493
494 for (auto& object : objectTree)
495 {
496 ctx->bus->yield_method_call(ctx->yield, ec,
497 object.second.begin()->first, object.first,
498 DELETE_INTERFACE, "Delete");
499 if (ec)
500 {
501 log<level::ERR>("Failed to delete all objects",
502 entry("INTERFACE=%s", interface.c_str()),
503 entry("SERVICE=%s", serviceRoot.c_str()),
504 entry("NETFN=%x", ctx->netFn),
505 entry("CMD=%x,", ctx->cmd),
506 entry("ERROR=%s", ec.message().c_str()));
507 break;
508 }
509 }
510 return ec;
511}
512
513boost::system::error_code getManagedObjects(Context::ptr ctx,
514 const std::string& service,
515 const std::string& objPath,
516 ObjectValueTree& objects)
517{
518 boost::system::error_code ec;
519 objects = ctx->bus->yield_method_call<ipmi::ObjectValueTree>(
520 ctx->yield, ec, service.c_str(), objPath.c_str(),
521 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
522 return ec;
523}
524
525boost::system::error_code getAllAncestors(Context::ptr ctx,
526 const std::string& path,
527 const InterfaceList& interfaces,
528 ObjectTree& objectTree)
529{
530 std::string interfaceList = convertToString(interfaces);
531
532 boost::system::error_code ec;
533 objectTree = ctx->bus->yield_method_call<ObjectTree>(
534 ctx->yield, ec, MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
535 "GetAncestors", path, interfaceList);
536
537 if (ec)
538 {
539 return ec;
540 }
541
542 if (objectTree.empty())
543 {
544 log<level::ERR>("No Object has implemented the interface",
545 entry("PATH=%s", path.c_str()),
546 entry("INTERFACES=%s", interfaceList.c_str()));
547 elog<InternalFailure>();
548 }
549
550 return ec;
551}
552
Albert Zhangb53049e2022-04-02 15:39:51 +0800553boost::system::error_code callDbusMethod(Context::ptr ctx,
554 const std::string& service,
555 const std::string& objPath,
556 const std::string& interface,
557 const std::string& method)
558{
559 boost::system::error_code ec;
560 ctx->bus->yield_method_call(ctx->yield, ec, service, objPath, interface,
561 method);
562 return ec;
563}
564
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700565/********* End co-routine yielding alternatives ***************/
566
Yong Li7dc4ac02019-08-23 17:44:32 +0800567ipmi::Cc i2cWriteRead(std::string i2cBus, const uint8_t slaveAddr,
568 std::vector<uint8_t> writeData,
569 std::vector<uint8_t>& readBuf)
570{
571 // Open the i2c device, for low-level combined data write/read
572 int i2cDev = ::open(i2cBus.c_str(), O_RDWR | O_CLOEXEC);
573 if (i2cDev < 0)
574 {
575 log<level::ERR>("Failed to open i2c bus",
576 phosphor::logging::entry("BUS=%s", i2cBus.c_str()));
577 return ipmi::ccInvalidFieldRequest;
578 }
579
580 const size_t writeCount = writeData.size();
581 const size_t readCount = readBuf.size();
582 int msgCount = 0;
Willy Tu11d68892022-01-20 10:37:34 -0800583 i2c_msg i2cmsg[2] = {};
Yong Li7dc4ac02019-08-23 17:44:32 +0800584 if (writeCount)
585 {
586 // Data will be writtern to the slave address
587 i2cmsg[msgCount].addr = slaveAddr;
588 i2cmsg[msgCount].flags = 0x00;
589 i2cmsg[msgCount].len = writeCount;
590 i2cmsg[msgCount].buf = writeData.data();
591 msgCount++;
592 }
593 if (readCount)
594 {
595 // Data will be read into the buffer from the slave address
596 i2cmsg[msgCount].addr = slaveAddr;
597 i2cmsg[msgCount].flags = I2C_M_RD;
598 i2cmsg[msgCount].len = readCount;
599 i2cmsg[msgCount].buf = readBuf.data();
600 msgCount++;
601 }
602
Willy Tu11d68892022-01-20 10:37:34 -0800603 i2c_rdwr_ioctl_data msgReadWrite = {};
Yong Li7dc4ac02019-08-23 17:44:32 +0800604 msgReadWrite.msgs = i2cmsg;
605 msgReadWrite.nmsgs = msgCount;
606
607 // Perform the combined write/read
608 int ret = ::ioctl(i2cDev, I2C_RDWR, &msgReadWrite);
609 ::close(i2cDev);
610
611 if (ret < 0)
612 {
613 log<level::ERR>("I2C WR Failed!",
614 phosphor::logging::entry("RET=%d", ret));
615 return ipmi::ccUnspecifiedError;
616 }
617 if (readCount)
618 {
619 readBuf.resize(msgReadWrite.msgs[msgCount - 1].len);
620 }
621
622 return ipmi::ccSuccess;
623}
624
Tom Josephbe703f72017-03-09 12:34:35 +0530625} // namespace ipmi