blob: fb96ea60494e72961b4b9626a9bf4b8f41edbf52 [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 Williams1318a5e2024-08-16 15:19:54 -040042DbusObjectInfo
43 getDbusObject(sdbusplus::bus_t& bus, const std::string& interface,
44 const std::string& serviceRoot, const std::string& match)
Ratan Guptacc8feb42017-07-25 21:52:10 +053045{
46 std::vector<DbusInterface> interfaces;
47 interfaces.emplace_back(interface);
48
George Liu50f186c2024-02-04 16:51:26 +080049 ObjectTree objectTree = getSubTree(bus, interfaces, serviceRoot);
Ratan Guptacc8feb42017-07-25 21:52:10 +053050 if (objectTree.empty())
51 {
Patrick Venturef0c48782017-09-21 18:48:51 -070052 log<level::ERR>("No Object has implemented the interface",
Ratan Guptacc8feb42017-07-25 21:52:10 +053053 entry("INTERFACE=%s", interface.c_str()));
54 elog<InternalFailure>();
55 }
56
57 DbusObjectInfo objectInfo;
58
59 // if match is empty then return the first object
Patrick Venture0b02be92018-08-31 11:55:55 -070060 if (match == "")
Ratan Guptacc8feb42017-07-25 21:52:10 +053061 {
Patrick Venture0b02be92018-08-31 11:55:55 -070062 objectInfo = std::make_pair(
63 objectTree.begin()->first,
Ratan Guptacc8feb42017-07-25 21:52:10 +053064 std::move(objectTree.begin()->second.begin()->first));
65 return objectInfo;
66 }
67
68 // else search the match string in the object path
Patrick Williams1318a5e2024-08-16 15:19:54 -040069 auto found = std::find_if(
70 objectTree.begin(), objectTree.end(), [&match](const auto& object) {
71 return (object.first.find(match) != std::string::npos);
72 });
Ratan Guptacc8feb42017-07-25 21:52:10 +053073
Patrick Venture2e633522018-10-13 13:51:06 -070074 if (found == objectTree.end())
Ratan Guptacc8feb42017-07-25 21:52:10 +053075 {
76 log<level::ERR>("Failed to find object which matches",
77 entry("MATCH=%s", match.c_str()));
78 elog<InternalFailure>();
Patrick Venture2e633522018-10-13 13:51:06 -070079 // elog<> throws an exception.
Ratan Guptacc8feb42017-07-25 21:52:10 +053080 }
Patrick Venture2e633522018-10-13 13:51:06 -070081
82 return make_pair(found->first, std::move(found->second.begin()->first));
Ratan Guptacc8feb42017-07-25 21:52:10 +053083}
84
Patrick Williams5d82f472022-07-22 19:26:53 -050085Value getDbusProperty(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -070086 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -080087 const std::string& property,
88 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +053089{
Ratan Guptacc8feb42017-07-25 21:52:10 +053090 Value value;
91
Patrick Venture0b02be92018-08-31 11:55:55 -070092 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
93 PROP_INTF, METHOD_GET);
Ratan Guptacc8feb42017-07-25 21:52:10 +053094
95 method.append(interface, property);
96
Kun Yi5dcf41e2019-03-05 14:02:51 -080097 auto reply = bus.call(method, timeout.count());
Ratan Guptacc8feb42017-07-25 21:52:10 +053098 reply.read(value);
99
100 return value;
101}
102
Patrick Williams1318a5e2024-08-16 15:19:54 -0400103PropertyMap getAllDbusProperties(
104 sdbusplus::bus_t& bus, const std::string& service,
105 const std::string& objPath, const std::string& interface,
106 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +0530107{
108 PropertyMap properties;
Ratan Guptacc8feb42017-07-25 21:52:10 +0530109
Patrick Venture0b02be92018-08-31 11:55:55 -0700110 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
111 PROP_INTF, METHOD_GET_ALL);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530112
113 method.append(interface);
114
Kun Yi5dcf41e2019-03-05 14:02:51 -0800115 auto reply = bus.call(method, timeout.count());
Ratan Guptacc8feb42017-07-25 21:52:10 +0530116 reply.read(properties);
George Liu3e3cc352023-07-26 15:59:31 +0800117
Ratan Guptacc8feb42017-07-25 21:52:10 +0530118 return properties;
119}
120
Patrick Williams5d82f472022-07-22 19:26:53 -0500121ObjectValueTree getManagedObjects(sdbusplus::bus_t& bus,
Patrick Venture0b02be92018-08-31 11:55:55 -0700122 const std::string& service,
123 const std::string& objPath)
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600124{
125 ipmi::ObjectValueTree interfaces;
126
Patrick Venture0b02be92018-08-31 11:55:55 -0700127 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
128 "org.freedesktop.DBus.ObjectManager",
129 "GetManagedObjects");
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600130 auto reply = bus.call(method);
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600131 reply.read(interfaces);
George Liu3e3cc352023-07-26 15:59:31 +0800132
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600133 return interfaces;
134}
135
Patrick Williams5d82f472022-07-22 19:26:53 -0500136void setDbusProperty(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -0700137 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800138 const std::string& property, const Value& value,
139 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +0530140{
Patrick Venture0b02be92018-08-31 11:55:55 -0700141 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
142 PROP_INTF, METHOD_SET);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530143
144 method.append(interface, property, value);
145
Kun Yi5dcf41e2019-03-05 14:02:51 -0800146 if (!bus.call(method, timeout.count()))
Ratan Guptacc8feb42017-07-25 21:52:10 +0530147 {
148 log<level::ERR>("Failed to set property",
149 entry("PROPERTY=%s", property.c_str()),
Patrick Venture0b02be92018-08-31 11:55:55 -0700150 entry("PATH=%s", objPath.c_str()),
151 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptacc8feb42017-07-25 21:52:10 +0530152 elog<InternalFailure>();
153 }
Ratan Guptacc8feb42017-07-25 21:52:10 +0530154}
155
Patrick Venture0b02be92018-08-31 11:55:55 -0700156ServiceCache::ServiceCache(const std::string& intf, const std::string& path) :
Vernon Mauery54012502018-11-07 10:17:31 -0800157 intf(intf), path(path), cachedService(std::nullopt),
158 cachedBusName(std::nullopt)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500159{}
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700160
Patrick Venture0b02be92018-08-31 11:55:55 -0700161ServiceCache::ServiceCache(std::string&& intf, std::string&& path) :
Vernon Mauery54012502018-11-07 10:17:31 -0800162 intf(std::move(intf)), path(std::move(path)), cachedService(std::nullopt),
163 cachedBusName(std::nullopt)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500164{}
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700165
Patrick Williams5d82f472022-07-22 19:26:53 -0500166const std::string& ServiceCache::getService(sdbusplus::bus_t& bus)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700167{
168 if (!isValid(bus))
169 {
170 cachedBusName = bus.get_unique_name();
171 cachedService = ::ipmi::getService(bus, intf, path);
172 }
173 return cachedService.value();
174}
175
176void ServiceCache::invalidate()
177{
Vernon Mauery54012502018-11-07 10:17:31 -0800178 cachedBusName = std::nullopt;
179 cachedService = std::nullopt;
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700180}
181
Patrick Williams1318a5e2024-08-16 15:19:54 -0400182sdbusplus::message_t ServiceCache::newMethodCall(
183 sdbusplus::bus_t& bus, const char* intf, const char* method)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700184{
Patrick Venture0b02be92018-08-31 11:55:55 -0700185 return bus.new_method_call(getService(bus).c_str(), path.c_str(), intf,
186 method);
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700187}
188
Patrick Williams5d82f472022-07-22 19:26:53 -0500189bool ServiceCache::isValid(sdbusplus::bus_t& bus) const
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700190{
191 return cachedService && cachedBusName == bus.get_unique_name();
192}
193
Patrick Williams5d82f472022-07-22 19:26:53 -0500194std::string getService(sdbusplus::bus_t& bus, const std::string& intf,
Tom Josephbe703f72017-03-09 12:34:35 +0530195 const std::string& path)
196{
Patrick Williams1318a5e2024-08-16 15:19:54 -0400197 auto mapperCall =
198 bus.new_method_call("xyz.openbmc_project.ObjectMapper",
199 "/xyz/openbmc_project/object_mapper",
200 "xyz.openbmc_project.ObjectMapper", "GetObject");
Tom Josephbe703f72017-03-09 12:34:35 +0530201
202 mapperCall.append(path);
203 mapperCall.append(std::vector<std::string>({intf}));
204
205 auto mapperResponseMsg = bus.call(mapperCall);
206
Tom Josephbe703f72017-03-09 12:34:35 +0530207 std::map<std::string, std::vector<std::string>> mapperResponse;
208 mapperResponseMsg.read(mapperResponse);
209
210 if (mapperResponse.begin() == mapperResponse.end())
211 {
212 throw std::runtime_error("ERROR in reading the mapper response");
213 }
214
215 return mapperResponse.begin()->first;
216}
217
George Liu50f186c2024-02-04 16:51:26 +0800218ObjectTree getSubTree(sdbusplus::bus_t& bus, const InterfaceList& interfaces,
219 const std::string& subtreePath, int32_t depth)
220{
221 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ,
222 MAPPER_INTF, "GetSubTree");
223
224 mapperCall.append(subtreePath, depth, interfaces);
225
226 auto mapperReply = bus.call(mapperCall);
227 ObjectTree objectTree;
228 mapperReply.read(objectTree);
229
230 return objectTree;
231}
232
Patrick Williams1318a5e2024-08-16 15:19:54 -0400233ipmi::ObjectTree
234 getAllDbusObjects(sdbusplus::bus_t& bus, const std::string& serviceRoot,
235 const std::string& interface, const std::string& match)
Ratan Guptab8e99552017-07-27 07:07:48 +0530236{
237 std::vector<std::string> interfaces;
238 interfaces.emplace_back(interface);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530239
George Liu50f186c2024-02-04 16:51:26 +0800240 ObjectTree objectTree = getSubTree(bus, interfaces, serviceRoot);
Ratan Guptab8e99552017-07-27 07:07:48 +0530241 for (auto it = objectTree.begin(); it != objectTree.end();)
242 {
243 if (it->first.find(match) == std::string::npos)
244 {
245 it = objectTree.erase(it);
246 }
247 else
248 {
249 ++it;
250 }
251 }
252
253 return objectTree;
254}
255
Patrick Williams5d82f472022-07-22 19:26:53 -0500256void deleteAllDbusObjects(sdbusplus::bus_t& bus, const std::string& serviceRoot,
Ratan Guptab8e99552017-07-27 07:07:48 +0530257 const std::string& interface,
258 const std::string& match)
259{
260 try
261 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700262 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, match);
Ratan Guptab8e99552017-07-27 07:07:48 +0530263
264 for (auto& object : objectTree)
265 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700266 method_no_args::callDbusMethod(bus, object.second.begin()->first,
267 object.first, DELETE_INTERFACE,
268 "Delete");
Ratan Guptab8e99552017-07-27 07:07:48 +0530269 }
270 }
Patrick Williams5d82f472022-07-22 19:26:53 -0500271 catch (const sdbusplus::exception_t& e)
Ratan Guptab8e99552017-07-27 07:07:48 +0530272 {
Vernon Mauery7a614182018-11-27 12:54:52 -0800273 log<level::INFO>("sdbusplus exception - Unable to delete the objects",
274 entry("ERROR=%s", e.what()),
Ratan Guptab8e99552017-07-27 07:07:48 +0530275 entry("INTERFACE=%s", interface.c_str()),
276 entry("SERVICE=%s", serviceRoot.c_str()));
277 }
278}
279
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700280static inline std::string convertToString(const InterfaceList& interfaces)
281{
282 std::string intfStr;
283 for (const auto& intf : interfaces)
284 {
285 intfStr += "," + intf;
286 }
287 return intfStr;
288}
289
Patrick Williams5d82f472022-07-22 19:26:53 -0500290ObjectTree getAllAncestors(sdbusplus::bus_t& bus, const std::string& path,
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530291 InterfaceList&& interfaces)
292{
Patrick Venture0b02be92018-08-31 11:55:55 -0700293 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ,
294 MAPPER_INTF, "GetAncestors");
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530295 mapperCall.append(path, interfaces);
296
297 auto mapperReply = bus.call(mapperCall);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530298 ObjectTree objectTree;
299 mapperReply.read(objectTree);
300
301 if (objectTree.empty())
302 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700303 log<level::ERR>(
304 "No Object has implemented the interface",
305 entry("PATH=%s", path.c_str()),
306 entry("INTERFACES=%s", convertToString(interfaces).c_str()));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530307 elog<InternalFailure>();
308 }
309
310 return objectTree;
311}
Ratan Guptab8e99552017-07-27 07:07:48 +0530312
313namespace method_no_args
314{
315
Patrick Williams5d82f472022-07-22 19:26:53 -0500316void callDbusMethod(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -0700317 const std::string& objPath, const std::string& interface,
Ratan Guptab8e99552017-07-27 07:07:48 +0530318 const std::string& method)
319
320{
Patrick Venture0b02be92018-08-31 11:55:55 -0700321 auto busMethod = bus.new_method_call(service.c_str(), objPath.c_str(),
322 interface.c_str(), method.c_str());
Ratan Guptab8e99552017-07-27 07:07:48 +0530323 auto reply = bus.call(busMethod);
Ratan Guptab8e99552017-07-27 07:07:48 +0530324}
325
Patrick Venture0b02be92018-08-31 11:55:55 -0700326} // namespace method_no_args
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700327
328/********* Begin co-routine yielding alternatives ***************/
329
Patrick Williams1318a5e2024-08-16 15:19:54 -0400330boost::system::error_code
331 getService(Context::ptr ctx, const std::string& intf,
332 const std::string& path, std::string& service)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700333{
334 boost::system::error_code ec;
335 std::map<std::string, std::vector<std::string>> mapperResponse =
336 ctx->bus->yield_method_call<decltype(mapperResponse)>(
337 ctx->yield, ec, "xyz.openbmc_project.ObjectMapper",
338 "/xyz/openbmc_project/object_mapper",
Jason M. Billsf5967982020-03-06 10:42:08 -0800339 "xyz.openbmc_project.ObjectMapper", "GetObject", path,
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700340 std::vector<std::string>({intf}));
341
342 if (!ec)
343 {
344 service = std::move(mapperResponse.begin()->first);
345 }
346 return ec;
347}
348
Patrick Williams1318a5e2024-08-16 15:19:54 -0400349boost::system::error_code getSubTree(
350 Context::ptr ctx, const InterfaceList& interfaces,
351 const std::string& subtreePath, int32_t depth, ObjectTree& objectTree)
George Liu50f186c2024-02-04 16:51:26 +0800352{
353 boost::system::error_code ec;
354 objectTree = ctx->bus->yield_method_call<ObjectTree>(
355 ctx->yield, ec, MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF, "GetSubTree",
356 subtreePath, depth, interfaces);
357
358 return ec;
359}
360
Patrick Williams1318a5e2024-08-16 15:19:54 -0400361boost::system::error_code
362 getDbusObject(Context::ptr ctx, const std::string& interface,
363 const std::string& subtreePath, const std::string& match,
364 DbusObjectInfo& dbusObject)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700365{
366 std::vector<DbusInterface> interfaces;
367 interfaces.emplace_back(interface);
368
369 auto depth = 0;
George Liu50f186c2024-02-04 16:51:26 +0800370 ObjectTree objectTree;
Patrick Williams1318a5e2024-08-16 15:19:54 -0400371 boost::system::error_code ec =
372 getSubTree(ctx, interfaces, subtreePath, depth, objectTree);
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700373
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 Williams1318a5e2024-08-16 15:19:54 -0400399 auto found = std::find_if(
400 objectTree.begin(), objectTree.end(), [&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
Patrick Williams1318a5e2024-08-16 15:19:54 -0400420boost::system::error_code getAllDbusProperties(
421 Context::ptr ctx, const std::string& service, const std::string& objPath,
422 const std::string& interface, PropertyMap& properties)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700423{
424 boost::system::error_code ec;
425 properties = ctx->bus->yield_method_call<PropertyMap>(
426 ctx->yield, ec, service.c_str(), objPath.c_str(), PROP_INTF,
427 METHOD_GET_ALL, interface);
428 return ec;
429}
430
431boost::system::error_code
432 setDbusProperty(Context::ptr ctx, const std::string& service,
433 const std::string& objPath, const std::string& interface,
434 const std::string& property, const Value& value)
435{
436 boost::system::error_code ec;
437 ctx->bus->yield_method_call(ctx->yield, ec, service.c_str(),
438 objPath.c_str(), PROP_INTF, METHOD_SET,
439 interface, property, value);
440 return ec;
441}
442
Patrick Williams1318a5e2024-08-16 15:19:54 -0400443boost::system::error_code
444 getAllDbusObjects(Context::ptr ctx, const std::string& serviceRoot,
445 const std::string& interface, const std::string& match,
446 ObjectTree& objectTree)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700447{
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700448 std::vector<std::string> interfaces;
449 interfaces.emplace_back(interface);
450
451 auto depth = 0;
Patrick Williams1318a5e2024-08-16 15:19:54 -0400452 boost::system::error_code ec =
453 getSubTree(ctx, interfaces, serviceRoot, depth, objectTree);
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700454 if (ec)
455 {
456 return ec;
457 }
458
459 for (auto it = objectTree.begin(); it != objectTree.end();)
460 {
461 if (it->first.find(match) == std::string::npos)
462 {
463 it = objectTree.erase(it);
464 }
465 else
466 {
467 ++it;
468 }
469 }
470
471 return ec;
472}
473
Patrick Williams1318a5e2024-08-16 15:19:54 -0400474boost::system::error_code
475 deleteAllDbusObjects(Context::ptr ctx, const std::string& serviceRoot,
476 const std::string& interface, const std::string& match)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700477{
478 ObjectTree objectTree;
479 boost::system::error_code ec =
480 getAllDbusObjects(ctx, serviceRoot, interface, match, objectTree);
481 if (ec)
482 {
483 return ec;
484 }
485
486 for (auto& object : objectTree)
487 {
488 ctx->bus->yield_method_call(ctx->yield, ec,
489 object.second.begin()->first, object.first,
490 DELETE_INTERFACE, "Delete");
491 if (ec)
492 {
493 log<level::ERR>("Failed to delete all objects",
494 entry("INTERFACE=%s", interface.c_str()),
495 entry("SERVICE=%s", serviceRoot.c_str()),
496 entry("NETFN=%x", ctx->netFn),
497 entry("CMD=%x,", ctx->cmd),
498 entry("ERROR=%s", ec.message().c_str()));
499 break;
500 }
501 }
502 return ec;
503}
504
Patrick Williams1318a5e2024-08-16 15:19:54 -0400505boost::system::error_code
506 getManagedObjects(Context::ptr ctx, const std::string& service,
507 const std::string& objPath, ObjectValueTree& objects)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700508{
509 boost::system::error_code ec;
510 objects = ctx->bus->yield_method_call<ipmi::ObjectValueTree>(
511 ctx->yield, ec, service.c_str(), objPath.c_str(),
512 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
513 return ec;
514}
515
Patrick Williams1318a5e2024-08-16 15:19:54 -0400516boost::system::error_code
517 getAllAncestors(Context::ptr ctx, const std::string& path,
518 const InterfaceList& interfaces, ObjectTree& objectTree)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700519{
520 std::string interfaceList = convertToString(interfaces);
521
522 boost::system::error_code ec;
523 objectTree = ctx->bus->yield_method_call<ObjectTree>(
524 ctx->yield, ec, MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
525 "GetAncestors", path, interfaceList);
526
527 if (ec)
528 {
529 return ec;
530 }
531
532 if (objectTree.empty())
533 {
534 log<level::ERR>("No Object has implemented the interface",
535 entry("PATH=%s", path.c_str()),
536 entry("INTERFACES=%s", interfaceList.c_str()));
537 elog<InternalFailure>();
538 }
539
540 return ec;
541}
542
Patrick Williams1318a5e2024-08-16 15:19:54 -0400543boost::system::error_code callDbusMethod(
544 Context::ptr ctx, const std::string& service, const std::string& objPath,
545 const std::string& interface, const std::string& method)
Albert Zhangb53049e2022-04-02 15:39:51 +0800546{
547 boost::system::error_code ec;
548 ctx->bus->yield_method_call(ctx->yield, ec, service, objPath, interface,
549 method);
550 return ec;
551}
552
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700553/********* End co-routine yielding alternatives ***************/
554
Matt Simmering68d9d402023-11-09 14:22:11 -0800555ipmi::Cc i2cWriteRead(std::string i2cBus, const uint8_t targetAddr,
Yong Li7dc4ac02019-08-23 17:44:32 +0800556 std::vector<uint8_t> writeData,
557 std::vector<uint8_t>& readBuf)
558{
559 // Open the i2c device, for low-level combined data write/read
560 int i2cDev = ::open(i2cBus.c_str(), O_RDWR | O_CLOEXEC);
561 if (i2cDev < 0)
562 {
563 log<level::ERR>("Failed to open i2c bus",
564 phosphor::logging::entry("BUS=%s", i2cBus.c_str()));
565 return ipmi::ccInvalidFieldRequest;
566 }
567
568 const size_t writeCount = writeData.size();
569 const size_t readCount = readBuf.size();
570 int msgCount = 0;
Willy Tu11d68892022-01-20 10:37:34 -0800571 i2c_msg i2cmsg[2] = {};
Yong Li7dc4ac02019-08-23 17:44:32 +0800572 if (writeCount)
573 {
Matt Simmering68d9d402023-11-09 14:22:11 -0800574 // Data will be writtern to the target address
575 i2cmsg[msgCount].addr = targetAddr;
Yong Li7dc4ac02019-08-23 17:44:32 +0800576 i2cmsg[msgCount].flags = 0x00;
577 i2cmsg[msgCount].len = writeCount;
578 i2cmsg[msgCount].buf = writeData.data();
579 msgCount++;
580 }
581 if (readCount)
582 {
Matt Simmering68d9d402023-11-09 14:22:11 -0800583 // Data will be read into the buffer from the target address
584 i2cmsg[msgCount].addr = targetAddr;
Yong Li7dc4ac02019-08-23 17:44:32 +0800585 i2cmsg[msgCount].flags = I2C_M_RD;
586 i2cmsg[msgCount].len = readCount;
587 i2cmsg[msgCount].buf = readBuf.data();
588 msgCount++;
589 }
590
Willy Tu11d68892022-01-20 10:37:34 -0800591 i2c_rdwr_ioctl_data msgReadWrite = {};
Yong Li7dc4ac02019-08-23 17:44:32 +0800592 msgReadWrite.msgs = i2cmsg;
593 msgReadWrite.nmsgs = msgCount;
594
595 // Perform the combined write/read
596 int ret = ::ioctl(i2cDev, I2C_RDWR, &msgReadWrite);
597 ::close(i2cDev);
598
599 if (ret < 0)
600 {
601 log<level::ERR>("I2C WR Failed!",
602 phosphor::logging::entry("RET=%d", ret));
603 return ipmi::ccUnspecifiedError;
604 }
605 if (readCount)
606 {
607 readBuf.resize(msgReadWrite.msgs[msgCount - 1].len);
608 }
609
610 return ipmi::ccSuccess;
611}
612
Tom Josephbe703f72017-03-09 12:34:35 +0530613} // namespace ipmi