blob: 81cc4c4015f036a51ea2c0de0b342ab72da1009e [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
George Liu50f186c2024-02-04 16:51:26 +080050 ObjectTree objectTree = getSubTree(bus, interfaces, serviceRoot);
Ratan Guptacc8feb42017-07-25 21:52:10 +053051 if (objectTree.empty())
52 {
Patrick Venturef0c48782017-09-21 18:48:51 -070053 log<level::ERR>("No Object has implemented the interface",
Ratan Guptacc8feb42017-07-25 21:52:10 +053054 entry("INTERFACE=%s", interface.c_str()));
55 elog<InternalFailure>();
56 }
57
58 DbusObjectInfo objectInfo;
59
60 // if match is empty then return the first object
Patrick Venture0b02be92018-08-31 11:55:55 -070061 if (match == "")
Ratan Guptacc8feb42017-07-25 21:52:10 +053062 {
Patrick Venture0b02be92018-08-31 11:55:55 -070063 objectInfo = std::make_pair(
64 objectTree.begin()->first,
Ratan Guptacc8feb42017-07-25 21:52:10 +053065 std::move(objectTree.begin()->second.begin()->first));
66 return objectInfo;
67 }
68
69 // else search the match string in the object path
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050070 auto found = std::find_if(objectTree.begin(), objectTree.end(),
71 [&match](const auto& object) {
72 return (object.first.find(match) != std::string::npos);
73 });
Ratan Guptacc8feb42017-07-25 21:52:10 +053074
Patrick Venture2e633522018-10-13 13:51:06 -070075 if (found == objectTree.end())
Ratan Guptacc8feb42017-07-25 21:52:10 +053076 {
77 log<level::ERR>("Failed to find object which matches",
78 entry("MATCH=%s", match.c_str()));
79 elog<InternalFailure>();
Patrick Venture2e633522018-10-13 13:51:06 -070080 // elog<> throws an exception.
Ratan Guptacc8feb42017-07-25 21:52:10 +053081 }
Patrick Venture2e633522018-10-13 13:51:06 -070082
83 return make_pair(found->first, std::move(found->second.begin()->first));
Ratan Guptacc8feb42017-07-25 21:52:10 +053084}
85
Patrick Williams5d82f472022-07-22 19:26:53 -050086Value getDbusProperty(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -070087 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -080088 const std::string& property,
89 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +053090{
Ratan Guptacc8feb42017-07-25 21:52:10 +053091 Value value;
92
Patrick Venture0b02be92018-08-31 11:55:55 -070093 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
94 PROP_INTF, METHOD_GET);
Ratan Guptacc8feb42017-07-25 21:52:10 +053095
96 method.append(interface, property);
97
Kun Yi5dcf41e2019-03-05 14:02:51 -080098 auto reply = bus.call(method, timeout.count());
Ratan Guptacc8feb42017-07-25 21:52:10 +053099 reply.read(value);
100
101 return value;
102}
103
Patrick Williams5d82f472022-07-22 19:26:53 -0500104PropertyMap getAllDbusProperties(sdbusplus::bus_t& bus,
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530105 const std::string& service,
Ratan Guptacc8feb42017-07-25 21:52:10 +0530106 const std::string& objPath,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800107 const std::string& interface,
108 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +0530109{
110 PropertyMap properties;
Ratan Guptacc8feb42017-07-25 21:52:10 +0530111
Patrick Venture0b02be92018-08-31 11:55:55 -0700112 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
113 PROP_INTF, METHOD_GET_ALL);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530114
115 method.append(interface);
116
Kun Yi5dcf41e2019-03-05 14:02:51 -0800117 auto reply = bus.call(method, timeout.count());
Ratan Guptacc8feb42017-07-25 21:52:10 +0530118 reply.read(properties);
George Liu3e3cc352023-07-26 15:59:31 +0800119
Ratan Guptacc8feb42017-07-25 21:52:10 +0530120 return properties;
121}
122
Patrick Williams5d82f472022-07-22 19:26:53 -0500123ObjectValueTree getManagedObjects(sdbusplus::bus_t& bus,
Patrick Venture0b02be92018-08-31 11:55:55 -0700124 const std::string& service,
125 const std::string& objPath)
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600126{
127 ipmi::ObjectValueTree interfaces;
128
Patrick Venture0b02be92018-08-31 11:55:55 -0700129 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
130 "org.freedesktop.DBus.ObjectManager",
131 "GetManagedObjects");
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600132 auto reply = bus.call(method);
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600133 reply.read(interfaces);
George Liu3e3cc352023-07-26 15:59:31 +0800134
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600135 return interfaces;
136}
137
Patrick Williams5d82f472022-07-22 19:26:53 -0500138void setDbusProperty(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -0700139 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800140 const std::string& property, const Value& value,
141 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +0530142{
Patrick Venture0b02be92018-08-31 11:55:55 -0700143 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
144 PROP_INTF, METHOD_SET);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530145
146 method.append(interface, property, value);
147
Kun Yi5dcf41e2019-03-05 14:02:51 -0800148 if (!bus.call(method, timeout.count()))
Ratan Guptacc8feb42017-07-25 21:52:10 +0530149 {
150 log<level::ERR>("Failed to set property",
151 entry("PROPERTY=%s", property.c_str()),
Patrick Venture0b02be92018-08-31 11:55:55 -0700152 entry("PATH=%s", objPath.c_str()),
153 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptacc8feb42017-07-25 21:52:10 +0530154 elog<InternalFailure>();
155 }
Ratan Guptacc8feb42017-07-25 21:52:10 +0530156}
157
Patrick Venture0b02be92018-08-31 11:55:55 -0700158ServiceCache::ServiceCache(const std::string& intf, const std::string& path) :
Vernon Mauery54012502018-11-07 10:17:31 -0800159 intf(intf), path(path), cachedService(std::nullopt),
160 cachedBusName(std::nullopt)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500161{}
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700162
Patrick Venture0b02be92018-08-31 11:55:55 -0700163ServiceCache::ServiceCache(std::string&& intf, std::string&& path) :
Vernon Mauery54012502018-11-07 10:17:31 -0800164 intf(std::move(intf)), path(std::move(path)), cachedService(std::nullopt),
165 cachedBusName(std::nullopt)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500166{}
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700167
Patrick Williams5d82f472022-07-22 19:26:53 -0500168const std::string& ServiceCache::getService(sdbusplus::bus_t& bus)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700169{
170 if (!isValid(bus))
171 {
172 cachedBusName = bus.get_unique_name();
173 cachedService = ::ipmi::getService(bus, intf, path);
174 }
175 return cachedService.value();
176}
177
178void ServiceCache::invalidate()
179{
Vernon Mauery54012502018-11-07 10:17:31 -0800180 cachedBusName = std::nullopt;
181 cachedService = std::nullopt;
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700182}
183
Patrick Williams5d82f472022-07-22 19:26:53 -0500184sdbusplus::message_t ServiceCache::newMethodCall(sdbusplus::bus_t& bus,
185 const char* intf,
186 const char* method)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700187{
Patrick Venture0b02be92018-08-31 11:55:55 -0700188 return bus.new_method_call(getService(bus).c_str(), path.c_str(), intf,
189 method);
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700190}
191
Patrick Williams5d82f472022-07-22 19:26:53 -0500192bool ServiceCache::isValid(sdbusplus::bus_t& bus) const
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700193{
194 return cachedService && cachedBusName == bus.get_unique_name();
195}
196
Patrick Williams5d82f472022-07-22 19:26:53 -0500197std::string getService(sdbusplus::bus_t& bus, const std::string& intf,
Tom Josephbe703f72017-03-09 12:34:35 +0530198 const std::string& path)
199{
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500200 auto mapperCall = bus.new_method_call("xyz.openbmc_project.ObjectMapper",
201 "/xyz/openbmc_project/object_mapper",
202 "xyz.openbmc_project.ObjectMapper",
203 "GetObject");
Tom Josephbe703f72017-03-09 12:34:35 +0530204
205 mapperCall.append(path);
206 mapperCall.append(std::vector<std::string>({intf}));
207
208 auto mapperResponseMsg = bus.call(mapperCall);
209
Tom Josephbe703f72017-03-09 12:34:35 +0530210 std::map<std::string, std::vector<std::string>> mapperResponse;
211 mapperResponseMsg.read(mapperResponse);
212
213 if (mapperResponse.begin() == mapperResponse.end())
214 {
215 throw std::runtime_error("ERROR in reading the mapper response");
216 }
217
218 return mapperResponse.begin()->first;
219}
220
George Liu50f186c2024-02-04 16:51:26 +0800221ObjectTree getSubTree(sdbusplus::bus_t& bus, const InterfaceList& interfaces,
222 const std::string& subtreePath, int32_t depth)
223{
224 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ,
225 MAPPER_INTF, "GetSubTree");
226
227 mapperCall.append(subtreePath, depth, interfaces);
228
229 auto mapperReply = bus.call(mapperCall);
230 ObjectTree objectTree;
231 mapperReply.read(objectTree);
232
233 return objectTree;
234}
235
Patrick Williams5d82f472022-07-22 19:26:53 -0500236ipmi::ObjectTree getAllDbusObjects(sdbusplus::bus_t& bus,
Ratan Guptab8e99552017-07-27 07:07:48 +0530237 const std::string& serviceRoot,
238 const std::string& interface,
239 const std::string& match)
240{
241 std::vector<std::string> interfaces;
242 interfaces.emplace_back(interface);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530243
George Liu50f186c2024-02-04 16:51:26 +0800244 ObjectTree objectTree = getSubTree(bus, interfaces, serviceRoot);
Ratan Guptab8e99552017-07-27 07:07:48 +0530245 for (auto it = objectTree.begin(); it != objectTree.end();)
246 {
247 if (it->first.find(match) == std::string::npos)
248 {
249 it = objectTree.erase(it);
250 }
251 else
252 {
253 ++it;
254 }
255 }
256
257 return objectTree;
258}
259
Patrick Williams5d82f472022-07-22 19:26:53 -0500260void deleteAllDbusObjects(sdbusplus::bus_t& bus, const std::string& serviceRoot,
Ratan Guptab8e99552017-07-27 07:07:48 +0530261 const std::string& interface,
262 const std::string& match)
263{
264 try
265 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700266 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, match);
Ratan Guptab8e99552017-07-27 07:07:48 +0530267
268 for (auto& object : objectTree)
269 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700270 method_no_args::callDbusMethod(bus, object.second.begin()->first,
271 object.first, DELETE_INTERFACE,
272 "Delete");
Ratan Guptab8e99552017-07-27 07:07:48 +0530273 }
274 }
Patrick Williams5d82f472022-07-22 19:26:53 -0500275 catch (const sdbusplus::exception_t& e)
Ratan Guptab8e99552017-07-27 07:07:48 +0530276 {
Vernon Mauery7a614182018-11-27 12:54:52 -0800277 log<level::INFO>("sdbusplus exception - Unable to delete the objects",
278 entry("ERROR=%s", e.what()),
Ratan Guptab8e99552017-07-27 07:07:48 +0530279 entry("INTERFACE=%s", interface.c_str()),
280 entry("SERVICE=%s", serviceRoot.c_str()));
281 }
282}
283
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700284static inline std::string convertToString(const InterfaceList& interfaces)
285{
286 std::string intfStr;
287 for (const auto& intf : interfaces)
288 {
289 intfStr += "," + intf;
290 }
291 return intfStr;
292}
293
Patrick Williams5d82f472022-07-22 19:26:53 -0500294ObjectTree getAllAncestors(sdbusplus::bus_t& bus, const std::string& path,
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530295 InterfaceList&& interfaces)
296{
Patrick Venture0b02be92018-08-31 11:55:55 -0700297 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME, MAPPER_OBJ,
298 MAPPER_INTF, "GetAncestors");
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530299 mapperCall.append(path, interfaces);
300
301 auto mapperReply = bus.call(mapperCall);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530302 ObjectTree objectTree;
303 mapperReply.read(objectTree);
304
305 if (objectTree.empty())
306 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700307 log<level::ERR>(
308 "No Object has implemented the interface",
309 entry("PATH=%s", path.c_str()),
310 entry("INTERFACES=%s", convertToString(interfaces).c_str()));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530311 elog<InternalFailure>();
312 }
313
314 return objectTree;
315}
Ratan Guptab8e99552017-07-27 07:07:48 +0530316
317namespace method_no_args
318{
319
Patrick Williams5d82f472022-07-22 19:26:53 -0500320void callDbusMethod(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -0700321 const std::string& objPath, const std::string& interface,
Ratan Guptab8e99552017-07-27 07:07:48 +0530322 const std::string& method)
323
324{
Patrick Venture0b02be92018-08-31 11:55:55 -0700325 auto busMethod = bus.new_method_call(service.c_str(), objPath.c_str(),
326 interface.c_str(), method.c_str());
Ratan Guptab8e99552017-07-27 07:07:48 +0530327 auto reply = bus.call(busMethod);
Ratan Guptab8e99552017-07-27 07:07:48 +0530328}
329
Patrick Venture0b02be92018-08-31 11:55:55 -0700330} // namespace method_no_args
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700331
332/********* Begin co-routine yielding alternatives ***************/
333
Vijay Khemka31655692020-03-04 15:22:12 -0800334boost::system::error_code getService(Context::ptr ctx, const std::string& intf,
335 const std::string& path,
336 std::string& service)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700337{
338 boost::system::error_code ec;
339 std::map<std::string, std::vector<std::string>> mapperResponse =
340 ctx->bus->yield_method_call<decltype(mapperResponse)>(
341 ctx->yield, ec, "xyz.openbmc_project.ObjectMapper",
342 "/xyz/openbmc_project/object_mapper",
Jason M. Billsf5967982020-03-06 10:42:08 -0800343 "xyz.openbmc_project.ObjectMapper", "GetObject", path,
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700344 std::vector<std::string>({intf}));
345
346 if (!ec)
347 {
348 service = std::move(mapperResponse.begin()->first);
349 }
350 return ec;
351}
352
George Liu50f186c2024-02-04 16:51:26 +0800353boost::system::error_code getSubTree(Context::ptr ctx,
354 const InterfaceList& interfaces,
355 const std::string& subtreePath,
356 int32_t depth, ObjectTree& objectTree)
357{
358 boost::system::error_code ec;
359 objectTree = ctx->bus->yield_method_call<ObjectTree>(
360 ctx->yield, ec, MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF, "GetSubTree",
361 subtreePath, depth, interfaces);
362
363 return ec;
364}
365
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700366boost::system::error_code getDbusObject(Context::ptr ctx,
367 const std::string& interface,
368 const std::string& subtreePath,
369 const std::string& match,
370 DbusObjectInfo& dbusObject)
371{
372 std::vector<DbusInterface> interfaces;
373 interfaces.emplace_back(interface);
374
375 auto depth = 0;
George Liu50f186c2024-02-04 16:51:26 +0800376 ObjectTree objectTree;
377 boost::system::error_code ec = getSubTree(ctx, interfaces, subtreePath,
378 depth, objectTree);
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700379
380 if (ec)
381 {
382 return ec;
383 }
384
385 if (objectTree.empty())
386 {
387 log<level::ERR>("No Object has implemented the interface",
388 entry("INTERFACE=%s", interface.c_str()),
389 entry("NETFN=%x", ctx->netFn),
390 entry("CMD=%x,", ctx->cmd));
391 return boost::system::errc::make_error_code(
392 boost::system::errc::no_such_process);
393 }
394
395 // if match is empty then return the first object
396 if (match == "")
397 {
398 dbusObject = std::make_pair(
399 std::move(objectTree.begin()->first),
400 std::move(objectTree.begin()->second.begin()->first));
401 return ec;
402 }
403
404 // else search the match string in the object path
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500405 auto found = std::find_if(objectTree.begin(), objectTree.end(),
406 [&match](const auto& object) {
407 return (object.first.find(match) != std::string::npos);
408 });
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700409
410 if (found == objectTree.end())
411 {
412 log<level::ERR>("Failed to find object which matches",
413 entry("MATCH=%s", match.c_str()),
414 entry("NETFN=%x", ctx->netFn),
415 entry("CMD=%x,", ctx->cmd));
416 // set ec
417 return boost::system::errc::make_error_code(
418 boost::system::errc::no_such_file_or_directory);
419 }
420
421 dbusObject = std::make_pair(std::move(found->first),
422 std::move(found->second.begin()->first));
423 return ec;
424}
425
426boost::system::error_code getAllDbusProperties(Context::ptr ctx,
427 const std::string& service,
428 const std::string& objPath,
429 const std::string& interface,
430 PropertyMap& properties)
431{
432 boost::system::error_code ec;
433 properties = ctx->bus->yield_method_call<PropertyMap>(
434 ctx->yield, ec, service.c_str(), objPath.c_str(), PROP_INTF,
435 METHOD_GET_ALL, interface);
436 return ec;
437}
438
439boost::system::error_code
440 setDbusProperty(Context::ptr ctx, const std::string& service,
441 const std::string& objPath, const std::string& interface,
442 const std::string& property, const Value& value)
443{
444 boost::system::error_code ec;
445 ctx->bus->yield_method_call(ctx->yield, ec, service.c_str(),
446 objPath.c_str(), PROP_INTF, METHOD_SET,
447 interface, property, value);
448 return ec;
449}
450
451boost::system::error_code getAllDbusObjects(Context::ptr ctx,
452 const std::string& serviceRoot,
453 const std::string& interface,
454 const std::string& match,
455 ObjectTree& objectTree)
456{
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700457 std::vector<std::string> interfaces;
458 interfaces.emplace_back(interface);
459
460 auto depth = 0;
George Liu50f186c2024-02-04 16:51:26 +0800461 boost::system::error_code ec = getSubTree(ctx, interfaces, serviceRoot,
462 depth, objectTree);
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700463 if (ec)
464 {
465 return ec;
466 }
467
468 for (auto it = objectTree.begin(); it != objectTree.end();)
469 {
470 if (it->first.find(match) == std::string::npos)
471 {
472 it = objectTree.erase(it);
473 }
474 else
475 {
476 ++it;
477 }
478 }
479
480 return ec;
481}
482
483boost::system::error_code deleteAllDbusObjects(Context::ptr ctx,
484 const std::string& serviceRoot,
485 const std::string& interface,
486 const std::string& match)
487{
488 ObjectTree objectTree;
489 boost::system::error_code ec =
490 getAllDbusObjects(ctx, serviceRoot, interface, match, objectTree);
491 if (ec)
492 {
493 return ec;
494 }
495
496 for (auto& object : objectTree)
497 {
498 ctx->bus->yield_method_call(ctx->yield, ec,
499 object.second.begin()->first, object.first,
500 DELETE_INTERFACE, "Delete");
501 if (ec)
502 {
503 log<level::ERR>("Failed to delete all objects",
504 entry("INTERFACE=%s", interface.c_str()),
505 entry("SERVICE=%s", serviceRoot.c_str()),
506 entry("NETFN=%x", ctx->netFn),
507 entry("CMD=%x,", ctx->cmd),
508 entry("ERROR=%s", ec.message().c_str()));
509 break;
510 }
511 }
512 return ec;
513}
514
515boost::system::error_code getManagedObjects(Context::ptr ctx,
516 const std::string& service,
517 const std::string& objPath,
518 ObjectValueTree& objects)
519{
520 boost::system::error_code ec;
521 objects = ctx->bus->yield_method_call<ipmi::ObjectValueTree>(
522 ctx->yield, ec, service.c_str(), objPath.c_str(),
523 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
524 return ec;
525}
526
527boost::system::error_code getAllAncestors(Context::ptr ctx,
528 const std::string& path,
529 const InterfaceList& interfaces,
530 ObjectTree& objectTree)
531{
532 std::string interfaceList = convertToString(interfaces);
533
534 boost::system::error_code ec;
535 objectTree = ctx->bus->yield_method_call<ObjectTree>(
536 ctx->yield, ec, MAPPER_BUS_NAME, MAPPER_OBJ, MAPPER_INTF,
537 "GetAncestors", path, interfaceList);
538
539 if (ec)
540 {
541 return ec;
542 }
543
544 if (objectTree.empty())
545 {
546 log<level::ERR>("No Object has implemented the interface",
547 entry("PATH=%s", path.c_str()),
548 entry("INTERFACES=%s", interfaceList.c_str()));
549 elog<InternalFailure>();
550 }
551
552 return ec;
553}
554
Albert Zhangb53049e2022-04-02 15:39:51 +0800555boost::system::error_code callDbusMethod(Context::ptr ctx,
556 const std::string& service,
557 const std::string& objPath,
558 const std::string& interface,
559 const std::string& method)
560{
561 boost::system::error_code ec;
562 ctx->bus->yield_method_call(ctx->yield, ec, service, objPath, interface,
563 method);
564 return ec;
565}
566
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700567/********* End co-routine yielding alternatives ***************/
568
Matt Simmering68d9d402023-11-09 14:22:11 -0800569ipmi::Cc i2cWriteRead(std::string i2cBus, const uint8_t targetAddr,
Yong Li7dc4ac02019-08-23 17:44:32 +0800570 std::vector<uint8_t> writeData,
571 std::vector<uint8_t>& readBuf)
572{
573 // Open the i2c device, for low-level combined data write/read
574 int i2cDev = ::open(i2cBus.c_str(), O_RDWR | O_CLOEXEC);
575 if (i2cDev < 0)
576 {
577 log<level::ERR>("Failed to open i2c bus",
578 phosphor::logging::entry("BUS=%s", i2cBus.c_str()));
579 return ipmi::ccInvalidFieldRequest;
580 }
581
582 const size_t writeCount = writeData.size();
583 const size_t readCount = readBuf.size();
584 int msgCount = 0;
Willy Tu11d68892022-01-20 10:37:34 -0800585 i2c_msg i2cmsg[2] = {};
Yong Li7dc4ac02019-08-23 17:44:32 +0800586 if (writeCount)
587 {
Matt Simmering68d9d402023-11-09 14:22:11 -0800588 // Data will be writtern to the target address
589 i2cmsg[msgCount].addr = targetAddr;
Yong Li7dc4ac02019-08-23 17:44:32 +0800590 i2cmsg[msgCount].flags = 0x00;
591 i2cmsg[msgCount].len = writeCount;
592 i2cmsg[msgCount].buf = writeData.data();
593 msgCount++;
594 }
595 if (readCount)
596 {
Matt Simmering68d9d402023-11-09 14:22:11 -0800597 // Data will be read into the buffer from the target address
598 i2cmsg[msgCount].addr = targetAddr;
Yong Li7dc4ac02019-08-23 17:44:32 +0800599 i2cmsg[msgCount].flags = I2C_M_RD;
600 i2cmsg[msgCount].len = readCount;
601 i2cmsg[msgCount].buf = readBuf.data();
602 msgCount++;
603 }
604
Willy Tu11d68892022-01-20 10:37:34 -0800605 i2c_rdwr_ioctl_data msgReadWrite = {};
Yong Li7dc4ac02019-08-23 17:44:32 +0800606 msgReadWrite.msgs = i2cmsg;
607 msgReadWrite.nmsgs = msgCount;
608
609 // Perform the combined write/read
610 int ret = ::ioctl(i2cDev, I2C_RDWR, &msgReadWrite);
611 ::close(i2cDev);
612
613 if (ret < 0)
614 {
615 log<level::ERR>("I2C WR Failed!",
616 phosphor::logging::entry("RET=%d", ret));
617 return ipmi::ccUnspecifiedError;
618 }
619 if (readCount)
620 {
621 readBuf.resize(msgReadWrite.msgs[msgCount - 1].len);
622 }
623
624 return ipmi::ccSuccess;
625}
626
Tom Josephbe703f72017-03-09 12:34:35 +0530627} // namespace ipmi