blob: e2fb65cbc98cdefa98dd43fba9fbda85f6f6797d [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>
George Liub4b40912024-07-17 16:14:17 +080013#include <phosphor-logging/lg2.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>
Alexander Hansen93aa9832025-11-07 15:29:49 +010016#include <xyz/openbmc_project/ObjectMapper/common.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070017
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050018#include <algorithm>
19#include <chrono>
Prithvi Paic1e7b5c2025-09-01 13:13:15 +053020#include <sstream>
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -050021
Tom Josephbe703f72017-03-09 12:34:35 +053022namespace ipmi
23{
24
Ratan Guptacc8feb42017-07-25 21:52:10 +053025using namespace phosphor::logging;
Willy Tu523e2d12023-09-05 11:36:48 -070026using namespace sdbusplus::error::xyz::openbmc_project::common;
Ratan Guptacc8feb42017-07-25 21:52:10 +053027
Alexander Hansen93aa9832025-11-07 15:29:49 +010028using ObjectMapper = sdbusplus::common::xyz::openbmc_project::ObjectMapper;
29
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -050030namespace network
31{
32
33/** @brief checks if the given ip is Link Local Ip or not.
Patrick Venture0b02be92018-08-31 11:55:55 -070034 * @param[in] ipaddress - IPAddress.
35 */
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -050036bool isLinkLocalIP(const std::string& ipaddress);
37
Patrick Venture0b02be92018-08-31 11:55:55 -070038} // namespace network
Ratan Guptacc8feb42017-07-25 21:52:10 +053039
Patrick Venture0b02be92018-08-31 11:55:55 -070040// TODO There may be cases where an interface is implemented by multiple
Ratan Guptacc8feb42017-07-25 21:52:10 +053041// objects,to handle such cases we are interested on that object
42// which are on interested busname.
43// Currently mapper doesn't give the readable busname(gives busid) so we can't
44// use busname to find the object,will do later once the support is there.
45
Patrick Williams69b4c282025-03-03 11:19:13 -050046DbusObjectInfo getDbusObject(
47 sdbusplus::bus_t& bus, const std::string& interface,
48 const std::string& serviceRoot, const std::string& match)
Ratan Guptacc8feb42017-07-25 21:52:10 +053049{
50 std::vector<DbusInterface> interfaces;
51 interfaces.emplace_back(interface);
52
George Liu50f186c2024-02-04 16:51:26 +080053 ObjectTree objectTree = getSubTree(bus, interfaces, serviceRoot);
Ratan Guptacc8feb42017-07-25 21:52:10 +053054 if (objectTree.empty())
55 {
George Liub4b40912024-07-17 16:14:17 +080056 lg2::error("No Object has implemented the interface: {INTERFACE}",
57 "INTERFACE", interface);
Ratan Guptacc8feb42017-07-25 21:52:10 +053058 elog<InternalFailure>();
59 }
60
61 DbusObjectInfo objectInfo;
62
63 // if match is empty then return the first object
Patrick Venture0b02be92018-08-31 11:55:55 -070064 if (match == "")
Ratan Guptacc8feb42017-07-25 21:52:10 +053065 {
Patrick Venture0b02be92018-08-31 11:55:55 -070066 objectInfo = std::make_pair(
67 objectTree.begin()->first,
Ratan Guptacc8feb42017-07-25 21:52:10 +053068 std::move(objectTree.begin()->second.begin()->first));
69 return objectInfo;
70 }
71
72 // else search the match string in the object path
Patrick Williams1318a5e2024-08-16 15:19:54 -040073 auto found = std::find_if(
74 objectTree.begin(), objectTree.end(), [&match](const auto& object) {
75 return (object.first.find(match) != std::string::npos);
76 });
Ratan Guptacc8feb42017-07-25 21:52:10 +053077
Patrick Venture2e633522018-10-13 13:51:06 -070078 if (found == objectTree.end())
Ratan Guptacc8feb42017-07-25 21:52:10 +053079 {
George Liub4b40912024-07-17 16:14:17 +080080 lg2::error("Failed to find object which matches: {MATCH}", "MATCH",
81 match);
Ratan Guptacc8feb42017-07-25 21:52:10 +053082 elog<InternalFailure>();
Patrick Venture2e633522018-10-13 13:51:06 -070083 // elog<> throws an exception.
Ratan Guptacc8feb42017-07-25 21:52:10 +053084 }
Patrick Venture2e633522018-10-13 13:51:06 -070085
86 return make_pair(found->first, std::move(found->second.begin()->first));
Ratan Guptacc8feb42017-07-25 21:52:10 +053087}
88
Patrick Williams5d82f472022-07-22 19:26:53 -050089Value getDbusProperty(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -070090 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -080091 const std::string& property,
92 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +053093{
Ratan Guptacc8feb42017-07-25 21:52:10 +053094 Value value;
95
Patrick Venture0b02be92018-08-31 11:55:55 -070096 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
97 PROP_INTF, METHOD_GET);
Ratan Guptacc8feb42017-07-25 21:52:10 +053098
99 method.append(interface, property);
100
Kun Yi5dcf41e2019-03-05 14:02:51 -0800101 auto reply = bus.call(method, timeout.count());
Ratan Guptacc8feb42017-07-25 21:52:10 +0530102 reply.read(value);
103
104 return value;
105}
106
Patrick Williams1318a5e2024-08-16 15:19:54 -0400107PropertyMap getAllDbusProperties(
108 sdbusplus::bus_t& bus, const std::string& service,
109 const std::string& objPath, const std::string& interface,
110 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +0530111{
112 PropertyMap properties;
Ratan Guptacc8feb42017-07-25 21:52:10 +0530113
Patrick Venture0b02be92018-08-31 11:55:55 -0700114 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
115 PROP_INTF, METHOD_GET_ALL);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530116
117 method.append(interface);
118
Kun Yi5dcf41e2019-03-05 14:02:51 -0800119 auto reply = bus.call(method, timeout.count());
Ratan Guptacc8feb42017-07-25 21:52:10 +0530120 reply.read(properties);
George Liu3e3cc352023-07-26 15:59:31 +0800121
Ratan Guptacc8feb42017-07-25 21:52:10 +0530122 return properties;
123}
124
Patrick Williams5d82f472022-07-22 19:26:53 -0500125ObjectValueTree getManagedObjects(sdbusplus::bus_t& bus,
Patrick Venture0b02be92018-08-31 11:55:55 -0700126 const std::string& service,
127 const std::string& objPath)
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600128{
129 ipmi::ObjectValueTree interfaces;
130
Patrick Venture0b02be92018-08-31 11:55:55 -0700131 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
132 "org.freedesktop.DBus.ObjectManager",
133 "GetManagedObjects");
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600134 auto reply = bus.call(method);
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600135 reply.read(interfaces);
George Liu3e3cc352023-07-26 15:59:31 +0800136
Dhruvaraj Subhashchandran5c0beec2018-01-23 04:47:06 -0600137 return interfaces;
138}
139
Patrick Williams5d82f472022-07-22 19:26:53 -0500140void setDbusProperty(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -0700141 const std::string& objPath, const std::string& interface,
Kun Yi5dcf41e2019-03-05 14:02:51 -0800142 const std::string& property, const Value& value,
143 std::chrono::microseconds timeout)
Ratan Guptacc8feb42017-07-25 21:52:10 +0530144{
Patrick Venture0b02be92018-08-31 11:55:55 -0700145 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
146 PROP_INTF, METHOD_SET);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530147
148 method.append(interface, property, value);
149
Kun Yi5dcf41e2019-03-05 14:02:51 -0800150 if (!bus.call(method, timeout.count()))
Ratan Guptacc8feb42017-07-25 21:52:10 +0530151 {
George Liub4b40912024-07-17 16:14:17 +0800152 lg2::error("Failed to set {PROPERTY}, path: {PATH}, "
153 "interface: {INTERFACE}",
154 "PROPERTY", property, "PATH", objPath, "INTERFACE",
155 interface);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530156 elog<InternalFailure>();
157 }
Ratan Guptacc8feb42017-07-25 21:52:10 +0530158}
159
Patrick Venture0b02be92018-08-31 11:55:55 -0700160ServiceCache::ServiceCache(const std::string& intf, const std::string& path) :
Vernon Mauery54012502018-11-07 10:17:31 -0800161 intf(intf), path(path), cachedService(std::nullopt),
162 cachedBusName(std::nullopt)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500163{}
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700164
Patrick Venture0b02be92018-08-31 11:55:55 -0700165ServiceCache::ServiceCache(std::string&& intf, std::string&& path) :
Vernon Mauery54012502018-11-07 10:17:31 -0800166 intf(std::move(intf)), path(std::move(path)), cachedService(std::nullopt),
167 cachedBusName(std::nullopt)
Patrick Williamsfbc6c9d2023-05-10 07:50:16 -0500168{}
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700169
Patrick Williams5d82f472022-07-22 19:26:53 -0500170const std::string& ServiceCache::getService(sdbusplus::bus_t& bus)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700171{
172 if (!isValid(bus))
173 {
174 cachedBusName = bus.get_unique_name();
175 cachedService = ::ipmi::getService(bus, intf, path);
176 }
Jayanth Othayoth195d5522025-06-07 02:28:07 -0500177
178 if (!cachedService)
179 {
180 throw std::runtime_error("Service not cached");
181 }
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700182 return cachedService.value();
183}
184
185void ServiceCache::invalidate()
186{
Vernon Mauery54012502018-11-07 10:17:31 -0800187 cachedBusName = std::nullopt;
188 cachedService = std::nullopt;
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700189}
190
Patrick Williams1318a5e2024-08-16 15:19:54 -0400191sdbusplus::message_t ServiceCache::newMethodCall(
192 sdbusplus::bus_t& bus, const char* intf, const char* method)
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700193{
Patrick Venture0b02be92018-08-31 11:55:55 -0700194 return bus.new_method_call(getService(bus).c_str(), path.c_str(), intf,
195 method);
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700196}
197
Patrick Williams5d82f472022-07-22 19:26:53 -0500198bool ServiceCache::isValid(sdbusplus::bus_t& bus) const
William A. Kennington IIIe47fdfb2018-03-15 17:09:28 -0700199{
200 return cachedService && cachedBusName == bus.get_unique_name();
201}
202
Patrick Williams5d82f472022-07-22 19:26:53 -0500203std::string getService(sdbusplus::bus_t& bus, const std::string& intf,
Tom Josephbe703f72017-03-09 12:34:35 +0530204 const std::string& path)
205{
Alexander Hansen93aa9832025-11-07 15:29:49 +0100206 auto mapperCall = bus.new_method_call(
207 ObjectMapper::default_service, ObjectMapper::instance_path,
208 ObjectMapper::interface, ObjectMapper::method_names::get_object);
Tom Josephbe703f72017-03-09 12:34:35 +0530209
210 mapperCall.append(path);
211 mapperCall.append(std::vector<std::string>({intf}));
212
213 auto mapperResponseMsg = bus.call(mapperCall);
214
Patrick Williams94b23392025-11-05 00:16:19 -0500215 auto mapperResponse =
216 mapperResponseMsg
217 .unpack<std::map<std::string, std::vector<std::string>>>();
Tom Josephbe703f72017-03-09 12:34:35 +0530218
219 if (mapperResponse.begin() == mapperResponse.end())
220 {
221 throw std::runtime_error("ERROR in reading the mapper response");
222 }
223
224 return mapperResponse.begin()->first;
225}
226
George Liu50f186c2024-02-04 16:51:26 +0800227ObjectTree getSubTree(sdbusplus::bus_t& bus, const InterfaceList& interfaces,
228 const std::string& subtreePath, int32_t depth)
229{
Alexander Hansen93aa9832025-11-07 15:29:49 +0100230 auto mapperCall = bus.new_method_call(
231 ObjectMapper::default_service, ObjectMapper::instance_path,
232 ObjectMapper::interface, ObjectMapper::method_names::get_sub_tree);
George Liu50f186c2024-02-04 16:51:26 +0800233
234 mapperCall.append(subtreePath, depth, interfaces);
235
236 auto mapperReply = bus.call(mapperCall);
Patrick Williams94b23392025-11-05 00:16:19 -0500237 auto objectTree = mapperReply.unpack<ObjectTree>();
George Liu50f186c2024-02-04 16:51:26 +0800238
239 return objectTree;
240}
241
Patrick Williams69b4c282025-03-03 11:19:13 -0500242ipmi::ObjectTree getAllDbusObjects(
243 sdbusplus::bus_t& bus, const std::string& serviceRoot,
244 const std::string& interface, const std::string& match)
Ratan Guptab8e99552017-07-27 07:07:48 +0530245{
246 std::vector<std::string> interfaces;
247 interfaces.emplace_back(interface);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530248
George Liu50f186c2024-02-04 16:51:26 +0800249 ObjectTree objectTree = getSubTree(bus, interfaces, serviceRoot);
Ratan Guptab8e99552017-07-27 07:07:48 +0530250 for (auto it = objectTree.begin(); it != objectTree.end();)
251 {
252 if (it->first.find(match) == std::string::npos)
253 {
254 it = objectTree.erase(it);
255 }
256 else
257 {
258 ++it;
259 }
260 }
261
262 return objectTree;
263}
264
Ratan Guptab8e99552017-07-27 07:07:48 +0530265namespace method_no_args
266{
267
Patrick Williams5d82f472022-07-22 19:26:53 -0500268void callDbusMethod(sdbusplus::bus_t& bus, const std::string& service,
Patrick Venture0b02be92018-08-31 11:55:55 -0700269 const std::string& objPath, const std::string& interface,
Ratan Guptab8e99552017-07-27 07:07:48 +0530270 const std::string& method)
271
272{
Patrick Venture0b02be92018-08-31 11:55:55 -0700273 auto busMethod = bus.new_method_call(service.c_str(), objPath.c_str(),
274 interface.c_str(), method.c_str());
Ratan Guptab8e99552017-07-27 07:07:48 +0530275 auto reply = bus.call(busMethod);
Ratan Guptab8e99552017-07-27 07:07:48 +0530276}
277
Patrick Venture0b02be92018-08-31 11:55:55 -0700278} // namespace method_no_args
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700279
280/********* Begin co-routine yielding alternatives ***************/
281
Patrick Williams69b4c282025-03-03 11:19:13 -0500282boost::system::error_code getService(Context::ptr ctx, const std::string& intf,
283 const std::string& path,
284 std::string& service)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700285{
286 boost::system::error_code ec;
287 std::map<std::string, std::vector<std::string>> mapperResponse =
288 ctx->bus->yield_method_call<decltype(mapperResponse)>(
Alexander Hansen93aa9832025-11-07 15:29:49 +0100289 ctx->yield, ec, ObjectMapper::default_service,
290 ObjectMapper::instance_path, ObjectMapper::interface,
291 ObjectMapper::method_names::get_object, path,
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700292 std::vector<std::string>({intf}));
293
294 if (!ec)
295 {
296 service = std::move(mapperResponse.begin()->first);
297 }
298 return ec;
299}
300
Patrick Williams1318a5e2024-08-16 15:19:54 -0400301boost::system::error_code getSubTree(
302 Context::ptr ctx, const InterfaceList& interfaces,
303 const std::string& subtreePath, int32_t depth, ObjectTree& objectTree)
George Liu50f186c2024-02-04 16:51:26 +0800304{
305 boost::system::error_code ec;
306 objectTree = ctx->bus->yield_method_call<ObjectTree>(
Alexander Hansen93aa9832025-11-07 15:29:49 +0100307 ctx->yield, ec, ObjectMapper::default_service,
308 ObjectMapper::instance_path, ObjectMapper::interface,
309 ObjectMapper::method_names::get_sub_tree, subtreePath, depth,
310 interfaces);
George Liu50f186c2024-02-04 16:51:26 +0800311
312 return ec;
313}
314
Patrick Williams69b4c282025-03-03 11:19:13 -0500315boost::system::error_code getDbusObject(
316 Context::ptr ctx, const std::string& interface,
317 const std::string& subtreePath, const std::string& match,
318 DbusObjectInfo& dbusObject)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700319{
320 std::vector<DbusInterface> interfaces;
321 interfaces.emplace_back(interface);
322
323 auto depth = 0;
George Liu50f186c2024-02-04 16:51:26 +0800324 ObjectTree objectTree;
Patrick Williams1318a5e2024-08-16 15:19:54 -0400325 boost::system::error_code ec =
326 getSubTree(ctx, interfaces, subtreePath, depth, objectTree);
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700327
328 if (ec)
329 {
330 return ec;
331 }
332
333 if (objectTree.empty())
334 {
George Liub4b40912024-07-17 16:14:17 +0800335 lg2::error("No Object has implemented the interface: {INTERFACE}, "
336 "NetFn: {NETFN}, Cmd: {CMD}",
337 "INTERFACE", interface, "NETFN", lg2::hex, ctx->netFn, "CMD",
338 lg2::hex, ctx->cmd);
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700339 return boost::system::errc::make_error_code(
340 boost::system::errc::no_such_process);
341 }
342
343 // if match is empty then return the first object
344 if (match == "")
345 {
346 dbusObject = std::make_pair(
347 std::move(objectTree.begin()->first),
348 std::move(objectTree.begin()->second.begin()->first));
349 return ec;
350 }
351
352 // else search the match string in the object path
Patrick Williams1318a5e2024-08-16 15:19:54 -0400353 auto found = std::find_if(
354 objectTree.begin(), objectTree.end(), [&match](const auto& object) {
355 return (object.first.find(match) != std::string::npos);
356 });
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700357
358 if (found == objectTree.end())
359 {
George Liub4b40912024-07-17 16:14:17 +0800360 lg2::error("Failed to find object which matches: {MATCH}, "
361 "NetFn: {NETFN}, Cmd: {CMD}",
362 "MATCH", match, "NETFN", lg2::hex, ctx->netFn, "CMD",
363 lg2::hex, ctx->cmd);
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700364 // set ec
365 return boost::system::errc::make_error_code(
366 boost::system::errc::no_such_file_or_directory);
367 }
368
369 dbusObject = std::make_pair(std::move(found->first),
370 std::move(found->second.begin()->first));
371 return ec;
372}
373
Patrick Williams1318a5e2024-08-16 15:19:54 -0400374boost::system::error_code getAllDbusProperties(
375 Context::ptr ctx, const std::string& service, const std::string& objPath,
376 const std::string& interface, PropertyMap& properties)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700377{
378 boost::system::error_code ec;
379 properties = ctx->bus->yield_method_call<PropertyMap>(
380 ctx->yield, ec, service.c_str(), objPath.c_str(), PROP_INTF,
381 METHOD_GET_ALL, interface);
382 return ec;
383}
384
Patrick Williams69b4c282025-03-03 11:19:13 -0500385boost::system::error_code setDbusProperty(
386 Context::ptr ctx, const std::string& service, const std::string& objPath,
387 const std::string& interface, const std::string& property,
388 const Value& value)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700389{
390 boost::system::error_code ec;
391 ctx->bus->yield_method_call(ctx->yield, ec, service.c_str(),
392 objPath.c_str(), PROP_INTF, METHOD_SET,
393 interface, property, value);
394 return ec;
395}
396
Patrick Williams69b4c282025-03-03 11:19:13 -0500397boost::system::error_code getAllDbusObjects(
398 Context::ptr ctx, const std::string& serviceRoot,
399 const std::string& interface, const std::string& match,
400 ObjectTree& objectTree)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700401{
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700402 std::vector<std::string> interfaces;
403 interfaces.emplace_back(interface);
404
405 auto depth = 0;
Patrick Williams1318a5e2024-08-16 15:19:54 -0400406 boost::system::error_code ec =
407 getSubTree(ctx, interfaces, serviceRoot, depth, objectTree);
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700408 if (ec)
409 {
410 return ec;
411 }
412
413 for (auto it = objectTree.begin(); it != objectTree.end();)
414 {
415 if (it->first.find(match) == std::string::npos)
416 {
417 it = objectTree.erase(it);
418 }
419 else
420 {
421 ++it;
422 }
423 }
424
425 return ec;
426}
427
Patrick Williams69b4c282025-03-03 11:19:13 -0500428boost::system::error_code getManagedObjects(
429 Context::ptr ctx, const std::string& service, const std::string& objPath,
430 ObjectValueTree& objects)
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700431{
432 boost::system::error_code ec;
433 objects = ctx->bus->yield_method_call<ipmi::ObjectValueTree>(
434 ctx->yield, ec, service.c_str(), objPath.c_str(),
435 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
436 return ec;
437}
438
Patrick Williams1318a5e2024-08-16 15:19:54 -0400439boost::system::error_code callDbusMethod(
440 Context::ptr ctx, const std::string& service, const std::string& objPath,
441 const std::string& interface, const std::string& method)
Albert Zhangb53049e2022-04-02 15:39:51 +0800442{
443 boost::system::error_code ec;
444 ctx->bus->yield_method_call(ctx->yield, ec, service, objPath, interface,
445 method);
446 return ec;
447}
448
Vernon Maueryeeb0f982019-05-29 16:36:58 -0700449/********* End co-routine yielding alternatives ***************/
450
Matt Simmering68d9d402023-11-09 14:22:11 -0800451ipmi::Cc i2cWriteRead(std::string i2cBus, const uint8_t targetAddr,
Yong Li7dc4ac02019-08-23 17:44:32 +0800452 std::vector<uint8_t> writeData,
453 std::vector<uint8_t>& readBuf)
454{
455 // Open the i2c device, for low-level combined data write/read
456 int i2cDev = ::open(i2cBus.c_str(), O_RDWR | O_CLOEXEC);
457 if (i2cDev < 0)
458 {
George Liub4b40912024-07-17 16:14:17 +0800459 lg2::error("Failed to open i2c bus: {BUS}", "BUS", i2cBus);
Yong Li7dc4ac02019-08-23 17:44:32 +0800460 return ipmi::ccInvalidFieldRequest;
461 }
462
463 const size_t writeCount = writeData.size();
464 const size_t readCount = readBuf.size();
465 int msgCount = 0;
Willy Tu11d68892022-01-20 10:37:34 -0800466 i2c_msg i2cmsg[2] = {};
Yong Li7dc4ac02019-08-23 17:44:32 +0800467 if (writeCount)
468 {
Matt Simmering68d9d402023-11-09 14:22:11 -0800469 // Data will be writtern to the target address
470 i2cmsg[msgCount].addr = targetAddr;
Yong Li7dc4ac02019-08-23 17:44:32 +0800471 i2cmsg[msgCount].flags = 0x00;
472 i2cmsg[msgCount].len = writeCount;
473 i2cmsg[msgCount].buf = writeData.data();
474 msgCount++;
475 }
476 if (readCount)
477 {
Matt Simmering68d9d402023-11-09 14:22:11 -0800478 // Data will be read into the buffer from the target address
479 i2cmsg[msgCount].addr = targetAddr;
Yong Li7dc4ac02019-08-23 17:44:32 +0800480 i2cmsg[msgCount].flags = I2C_M_RD;
481 i2cmsg[msgCount].len = readCount;
482 i2cmsg[msgCount].buf = readBuf.data();
483 msgCount++;
484 }
485
Willy Tu11d68892022-01-20 10:37:34 -0800486 i2c_rdwr_ioctl_data msgReadWrite = {};
Yong Li7dc4ac02019-08-23 17:44:32 +0800487 msgReadWrite.msgs = i2cmsg;
488 msgReadWrite.nmsgs = msgCount;
489
490 // Perform the combined write/read
491 int ret = ::ioctl(i2cDev, I2C_RDWR, &msgReadWrite);
492 ::close(i2cDev);
493
494 if (ret < 0)
495 {
George Liub4b40912024-07-17 16:14:17 +0800496 lg2::error("I2C WR Failed! {RET}", "RET", ret);
Yong Li7dc4ac02019-08-23 17:44:32 +0800497 return ipmi::ccUnspecifiedError;
498 }
499 if (readCount)
500 {
501 readBuf.resize(msgReadWrite.msgs[msgCount - 1].len);
502 }
503
504 return ipmi::ccSuccess;
505}
506
Prithvi Paic1e7b5c2025-09-01 13:13:15 +0530507std::vector<std::string> split(const std::string& srcStr, char delim)
508{
509 std::vector<std::string> out;
510 std::stringstream ss(srcStr);
511 std::string item;
512
513 while (std::getline(ss, item, delim))
514 {
515 if (!item.empty())
516 {
517 out.emplace_back(item);
518 }
519 }
520 return out;
521}
522
Tom Josephbe703f72017-03-09 12:34:35 +0530523} // namespace ipmi