1275f7c39SAndrew Jeffery #include "MCTPEndpoint.hpp"
2275f7c39SAndrew Jeffery #include "MCTPReactor.hpp"
3275f7c39SAndrew Jeffery #include "Utils.hpp"
4275f7c39SAndrew Jeffery
5275f7c39SAndrew Jeffery #include <boost/asio/io_context.hpp>
6275f7c39SAndrew Jeffery #include <boost/asio/post.hpp>
7275f7c39SAndrew Jeffery #include <boost/asio/steady_timer.hpp>
8275f7c39SAndrew Jeffery #include <phosphor-logging/lg2.hpp>
9275f7c39SAndrew Jeffery #include <sdbusplus/asio/connection.hpp>
10275f7c39SAndrew Jeffery #include <sdbusplus/asio/object_server.hpp>
11275f7c39SAndrew Jeffery #include <sdbusplus/bus.hpp>
12275f7c39SAndrew Jeffery #include <sdbusplus/bus/match.hpp>
13275f7c39SAndrew Jeffery #include <sdbusplus/message.hpp>
14275f7c39SAndrew Jeffery #include <sdbusplus/message/native_types.hpp>
15275f7c39SAndrew Jeffery
16275f7c39SAndrew Jeffery #include <chrono>
17275f7c39SAndrew Jeffery #include <cstdlib>
18275f7c39SAndrew Jeffery #include <format>
19275f7c39SAndrew Jeffery #include <functional>
20275f7c39SAndrew Jeffery #include <map>
21275f7c39SAndrew Jeffery #include <memory>
22275f7c39SAndrew Jeffery #include <optional>
23275f7c39SAndrew Jeffery #include <set>
24275f7c39SAndrew Jeffery #include <stdexcept>
25275f7c39SAndrew Jeffery #include <system_error>
26275f7c39SAndrew Jeffery #include <vector>
27275f7c39SAndrew Jeffery
28275f7c39SAndrew Jeffery PHOSPHOR_LOG2_USING;
29275f7c39SAndrew Jeffery
30275f7c39SAndrew Jeffery class DBusAssociationServer : public AssociationServer
31275f7c39SAndrew Jeffery {
32275f7c39SAndrew Jeffery public:
33275f7c39SAndrew Jeffery DBusAssociationServer() = delete;
34275f7c39SAndrew Jeffery DBusAssociationServer(const DBusAssociationServer&) = delete;
35275f7c39SAndrew Jeffery DBusAssociationServer(DBusAssociationServer&&) = delete;
DBusAssociationServer(const std::shared_ptr<sdbusplus::asio::connection> & connection)36275f7c39SAndrew Jeffery explicit DBusAssociationServer(
37275f7c39SAndrew Jeffery const std::shared_ptr<sdbusplus::asio::connection>& connection) :
38275f7c39SAndrew Jeffery server(connection)
39275f7c39SAndrew Jeffery {
40*19d1fda6SThu Nguyen server.add_manager("/au/com/codeconstruct/mctp1");
41275f7c39SAndrew Jeffery }
42275f7c39SAndrew Jeffery ~DBusAssociationServer() override = default;
43275f7c39SAndrew Jeffery DBusAssociationServer& operator=(const DBusAssociationServer&) = delete;
44275f7c39SAndrew Jeffery DBusAssociationServer& operator=(DBusAssociationServer&&) = delete;
45275f7c39SAndrew Jeffery
associate(const std::string & path,const std::vector<Association> & associations)46275f7c39SAndrew Jeffery void associate(const std::string& path,
47275f7c39SAndrew Jeffery const std::vector<Association>& associations) override
48275f7c39SAndrew Jeffery {
49275f7c39SAndrew Jeffery auto [entry, _] = objects.emplace(
50275f7c39SAndrew Jeffery path, server.add_interface(path, association::interface));
51275f7c39SAndrew Jeffery std::shared_ptr<sdbusplus::asio::dbus_interface> iface = entry->second;
52275f7c39SAndrew Jeffery iface->register_property("Associations", associations);
53275f7c39SAndrew Jeffery iface->initialize();
54275f7c39SAndrew Jeffery }
55275f7c39SAndrew Jeffery
disassociate(const std::string & path)56275f7c39SAndrew Jeffery void disassociate(const std::string& path) override
57275f7c39SAndrew Jeffery {
58275f7c39SAndrew Jeffery const auto entry = objects.find(path);
59275f7c39SAndrew Jeffery if (entry == objects.end())
60275f7c39SAndrew Jeffery {
61275f7c39SAndrew Jeffery throw std::logic_error(std::format(
62275f7c39SAndrew Jeffery "Attempted to untrack path that was not tracked: {}", path));
63275f7c39SAndrew Jeffery }
64275f7c39SAndrew Jeffery std::shared_ptr<sdbusplus::asio::dbus_interface> iface = entry->second;
65275f7c39SAndrew Jeffery server.remove_interface(entry->second);
66275f7c39SAndrew Jeffery objects.erase(entry);
67275f7c39SAndrew Jeffery }
68275f7c39SAndrew Jeffery
69275f7c39SAndrew Jeffery private:
70275f7c39SAndrew Jeffery std::shared_ptr<sdbusplus::asio::connection> connection;
71275f7c39SAndrew Jeffery sdbusplus::asio::object_server server;
72275f7c39SAndrew Jeffery std::map<std::string, std::shared_ptr<sdbusplus::asio::dbus_interface>>
73275f7c39SAndrew Jeffery objects;
74275f7c39SAndrew Jeffery };
75275f7c39SAndrew Jeffery
deviceFromConfig(const std::shared_ptr<sdbusplus::asio::connection> & connection,const SensorData & config)76275f7c39SAndrew Jeffery static std::shared_ptr<MCTPDevice> deviceFromConfig(
77275f7c39SAndrew Jeffery const std::shared_ptr<sdbusplus::asio::connection>& connection,
78275f7c39SAndrew Jeffery const SensorData& config)
79275f7c39SAndrew Jeffery {
80275f7c39SAndrew Jeffery try
81275f7c39SAndrew Jeffery {
82275f7c39SAndrew Jeffery std::optional<SensorBaseConfigMap> iface;
83275f7c39SAndrew Jeffery // NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
84275f7c39SAndrew Jeffery if ((iface = I2CMCTPDDevice::match(config)))
85275f7c39SAndrew Jeffery {
86275f7c39SAndrew Jeffery return I2CMCTPDDevice::from(connection, *iface);
87275f7c39SAndrew Jeffery }
88275f7c39SAndrew Jeffery }
89275f7c39SAndrew Jeffery catch (const std::invalid_argument& ex)
90275f7c39SAndrew Jeffery {
91275f7c39SAndrew Jeffery error("Unable to create device: {EXCEPTION}", "EXCEPTION", ex);
92275f7c39SAndrew Jeffery }
93275f7c39SAndrew Jeffery
94275f7c39SAndrew Jeffery return {};
95275f7c39SAndrew Jeffery }
96275f7c39SAndrew Jeffery
addInventory(const std::shared_ptr<sdbusplus::asio::connection> & connection,const std::shared_ptr<MCTPReactor> & reactor,sdbusplus::message_t & msg)97275f7c39SAndrew Jeffery static void addInventory(
98275f7c39SAndrew Jeffery const std::shared_ptr<sdbusplus::asio::connection>& connection,
99275f7c39SAndrew Jeffery const std::shared_ptr<MCTPReactor>& reactor, sdbusplus::message_t& msg)
100275f7c39SAndrew Jeffery {
101275f7c39SAndrew Jeffery auto [path,
102275f7c39SAndrew Jeffery exposed] = msg.unpack<sdbusplus::message::object_path, SensorData>();
103275f7c39SAndrew Jeffery try
104275f7c39SAndrew Jeffery {
105275f7c39SAndrew Jeffery reactor->manageMCTPDevice(path, deviceFromConfig(connection, exposed));
106275f7c39SAndrew Jeffery }
107275f7c39SAndrew Jeffery catch (const std::logic_error& e)
108275f7c39SAndrew Jeffery {
109275f7c39SAndrew Jeffery error(
110275f7c39SAndrew Jeffery "Addition of inventory at '{INVENTORY_PATH}' caused an invalid program state: {EXCEPTION}",
111275f7c39SAndrew Jeffery "INVENTORY_PATH", path, "EXCEPTION", e);
112275f7c39SAndrew Jeffery }
113275f7c39SAndrew Jeffery catch (const std::system_error& e)
114275f7c39SAndrew Jeffery {
115275f7c39SAndrew Jeffery error(
116275f7c39SAndrew Jeffery "Failed to manage device described by inventory at '{INVENTORY_PATH}: {EXCEPTION}'",
117275f7c39SAndrew Jeffery "INVENTORY_PATH", path, "EXCEPTION", e);
118275f7c39SAndrew Jeffery }
119275f7c39SAndrew Jeffery }
120275f7c39SAndrew Jeffery
removeInventory(const std::shared_ptr<MCTPReactor> & reactor,sdbusplus::message_t & msg)121275f7c39SAndrew Jeffery static void removeInventory(const std::shared_ptr<MCTPReactor>& reactor,
122275f7c39SAndrew Jeffery sdbusplus::message_t& msg)
123275f7c39SAndrew Jeffery {
124275f7c39SAndrew Jeffery auto [path, removed] =
125275f7c39SAndrew Jeffery msg.unpack<sdbusplus::message::object_path, std::set<std::string>>();
126275f7c39SAndrew Jeffery try
127275f7c39SAndrew Jeffery {
128275f7c39SAndrew Jeffery if (I2CMCTPDDevice::match(removed))
129275f7c39SAndrew Jeffery {
130275f7c39SAndrew Jeffery reactor->unmanageMCTPDevice(path.str);
131275f7c39SAndrew Jeffery }
132275f7c39SAndrew Jeffery }
133275f7c39SAndrew Jeffery catch (const std::logic_error& e)
134275f7c39SAndrew Jeffery {
135275f7c39SAndrew Jeffery error(
136275f7c39SAndrew Jeffery "Removal of inventory at '{INVENTORY_PATH}' caused an invalid program state: {EXCEPTION}",
137275f7c39SAndrew Jeffery "INVENTORY_PATH", path, "EXCEPTION", e);
138275f7c39SAndrew Jeffery }
139275f7c39SAndrew Jeffery catch (const std::system_error& e)
140275f7c39SAndrew Jeffery {
141275f7c39SAndrew Jeffery error(
142275f7c39SAndrew Jeffery "Failed to unmanage device described by inventory at '{INVENTORY_PATH}: {EXCEPTION}'",
143275f7c39SAndrew Jeffery "INVENTORY_PATH", path, "EXCEPTION", e);
144275f7c39SAndrew Jeffery }
145275f7c39SAndrew Jeffery }
146275f7c39SAndrew Jeffery
manageMCTPEntity(const std::shared_ptr<sdbusplus::asio::connection> & connection,const std::shared_ptr<MCTPReactor> & reactor,ManagedObjectType & entities)147275f7c39SAndrew Jeffery static void manageMCTPEntity(
148275f7c39SAndrew Jeffery const std::shared_ptr<sdbusplus::asio::connection>& connection,
149275f7c39SAndrew Jeffery const std::shared_ptr<MCTPReactor>& reactor, ManagedObjectType& entities)
150275f7c39SAndrew Jeffery {
151275f7c39SAndrew Jeffery for (const auto& [path, config] : entities)
152275f7c39SAndrew Jeffery {
153275f7c39SAndrew Jeffery try
154275f7c39SAndrew Jeffery {
155275f7c39SAndrew Jeffery reactor->manageMCTPDevice(path,
156275f7c39SAndrew Jeffery deviceFromConfig(connection, config));
157275f7c39SAndrew Jeffery }
158275f7c39SAndrew Jeffery catch (const std::logic_error& e)
159275f7c39SAndrew Jeffery {
160275f7c39SAndrew Jeffery error(
161275f7c39SAndrew Jeffery "Addition of inventory at '{INVENTORY_PATH}' caused an invalid program state: {EXCEPTION}",
162275f7c39SAndrew Jeffery "INVENTORY_PATH", path, "EXCEPTION", e);
163275f7c39SAndrew Jeffery }
164275f7c39SAndrew Jeffery catch (const std::system_error& e)
165275f7c39SAndrew Jeffery {
166275f7c39SAndrew Jeffery error(
167275f7c39SAndrew Jeffery "Failed to manage device described by inventory at '{INVENTORY_PATH}: {EXCEPTION}'",
168275f7c39SAndrew Jeffery "INVENTORY_PATH", path, "EXCEPTION", e);
169275f7c39SAndrew Jeffery }
170275f7c39SAndrew Jeffery }
171275f7c39SAndrew Jeffery }
172275f7c39SAndrew Jeffery
exitReactor(boost::asio::io_context * io,sdbusplus::message_t & msg)173275f7c39SAndrew Jeffery static void exitReactor(boost::asio::io_context* io, sdbusplus::message_t& msg)
174275f7c39SAndrew Jeffery {
175275f7c39SAndrew Jeffery auto name = msg.unpack<std::string>();
176275f7c39SAndrew Jeffery info("Shutting down mctpreactor, lost dependency '{SERVICE_NAME}'",
177275f7c39SAndrew Jeffery "SERVICE_NAME", name);
178275f7c39SAndrew Jeffery io->stop();
179275f7c39SAndrew Jeffery }
180275f7c39SAndrew Jeffery
main()181275f7c39SAndrew Jeffery int main()
182275f7c39SAndrew Jeffery {
183275f7c39SAndrew Jeffery constexpr std::chrono::seconds period(5);
184275f7c39SAndrew Jeffery
185275f7c39SAndrew Jeffery boost::asio::io_context io;
186275f7c39SAndrew Jeffery auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
187275f7c39SAndrew Jeffery DBusAssociationServer associationServer(systemBus);
188275f7c39SAndrew Jeffery auto reactor = std::make_shared<MCTPReactor>(associationServer);
189275f7c39SAndrew Jeffery boost::asio::steady_timer clock(io);
190275f7c39SAndrew Jeffery
191275f7c39SAndrew Jeffery std::function<void(const boost::system::error_code&)> alarm =
192275f7c39SAndrew Jeffery [&](const boost::system::error_code& ec) {
193275f7c39SAndrew Jeffery if (ec)
194275f7c39SAndrew Jeffery {
195275f7c39SAndrew Jeffery return;
196275f7c39SAndrew Jeffery }
197275f7c39SAndrew Jeffery clock.expires_after(period);
198275f7c39SAndrew Jeffery clock.async_wait(alarm);
199275f7c39SAndrew Jeffery reactor->tick();
200275f7c39SAndrew Jeffery };
201275f7c39SAndrew Jeffery clock.expires_after(period);
202275f7c39SAndrew Jeffery clock.async_wait(alarm);
203275f7c39SAndrew Jeffery
204275f7c39SAndrew Jeffery using namespace sdbusplus::bus::match;
205275f7c39SAndrew Jeffery
206275f7c39SAndrew Jeffery const std::string entityManagerNameLostSpec =
207275f7c39SAndrew Jeffery rules::nameOwnerChanged("xyz.openbmc_project.EntityManager");
208275f7c39SAndrew Jeffery
209275f7c39SAndrew Jeffery auto entityManagerNameLostMatch = sdbusplus::bus::match_t(
210275f7c39SAndrew Jeffery static_cast<sdbusplus::bus_t&>(*systemBus), entityManagerNameLostSpec,
211275f7c39SAndrew Jeffery std::bind_front(exitReactor, &io));
212275f7c39SAndrew Jeffery
213275f7c39SAndrew Jeffery const std::string mctpdNameLostSpec =
214*19d1fda6SThu Nguyen rules::nameOwnerChanged("au.com.codeconstruct.MCTP1");
215275f7c39SAndrew Jeffery
216275f7c39SAndrew Jeffery auto mctpdNameLostMatch = sdbusplus::bus::match_t(
217275f7c39SAndrew Jeffery static_cast<sdbusplus::bus_t&>(*systemBus), mctpdNameLostSpec,
218275f7c39SAndrew Jeffery std::bind_front(exitReactor, &io));
219275f7c39SAndrew Jeffery
220275f7c39SAndrew Jeffery const std::string interfacesRemovedMatchSpec =
221275f7c39SAndrew Jeffery rules::sender("xyz.openbmc_project.EntityManager") +
222275f7c39SAndrew Jeffery // Trailing slash on path: Listen for signals on the inventory subtree
223275f7c39SAndrew Jeffery rules::interfacesRemovedAtPath("/xyz/openbmc_project/inventory/");
224275f7c39SAndrew Jeffery
225275f7c39SAndrew Jeffery auto interfacesRemovedMatch = sdbusplus::bus::match_t(
226275f7c39SAndrew Jeffery static_cast<sdbusplus::bus_t&>(*systemBus), interfacesRemovedMatchSpec,
227275f7c39SAndrew Jeffery std::bind_front(removeInventory, reactor));
228275f7c39SAndrew Jeffery
229275f7c39SAndrew Jeffery const std::string interfacesAddedMatchSpec =
230275f7c39SAndrew Jeffery rules::sender("xyz.openbmc_project.EntityManager") +
231275f7c39SAndrew Jeffery // Trailing slash on path: Listen for signals on the inventory subtree
232275f7c39SAndrew Jeffery rules::interfacesAddedAtPath("/xyz/openbmc_project/inventory/");
233275f7c39SAndrew Jeffery
234275f7c39SAndrew Jeffery auto interfacesAddedMatch = sdbusplus::bus::match_t(
235275f7c39SAndrew Jeffery static_cast<sdbusplus::bus_t&>(*systemBus), interfacesAddedMatchSpec,
236275f7c39SAndrew Jeffery std::bind_front(addInventory, systemBus, reactor));
237275f7c39SAndrew Jeffery
238275f7c39SAndrew Jeffery systemBus->request_name("xyz.openbmc_project.MCTPReactor");
239275f7c39SAndrew Jeffery
240275f7c39SAndrew Jeffery boost::asio::post(io, [reactor, systemBus]() {
241275f7c39SAndrew Jeffery auto gsc = std::make_shared<GetSensorConfiguration>(
242275f7c39SAndrew Jeffery systemBus, std::bind_front(manageMCTPEntity, systemBus, reactor));
243275f7c39SAndrew Jeffery gsc->getConfiguration({"MCTPI2CTarget"});
244275f7c39SAndrew Jeffery });
245275f7c39SAndrew Jeffery
246275f7c39SAndrew Jeffery io.run();
247275f7c39SAndrew Jeffery
248275f7c39SAndrew Jeffery return EXIT_SUCCESS;
249275f7c39SAndrew Jeffery }
250