xref: /openbmc/kcsbridge/src/main.cpp (revision 03e6defc)
1 #include "args.hpp"
2 #include "cmd.hpp"
3 #include "server.hpp"
4 
5 #include <fmt/format.h>
6 #include <systemd/sd-daemon.h>
7 
8 #include <sdbusplus/bus.hpp>
9 #include <sdbusplus/slot.hpp>
10 #include <sdeventplus/event.hpp>
11 #include <sdeventplus/source/io.hpp>
12 #include <sdeventplus/source/signal.hpp>
13 #include <stdplus/exception.hpp>
14 #include <stdplus/fd/create.hpp>
15 #include <stdplus/signal.hpp>
16 
17 #include <algorithm>
18 #include <stdexcept>
19 #include <string>
20 
21 namespace kcsbridge
22 {
23 
24 using sdeventplus::source::IO;
25 using sdeventplus::source::Signal;
26 using stdplus::fd::OpenAccess;
27 using stdplus::fd::OpenFlag;
28 using stdplus::fd::OpenFlags;
29 
30 int execute(const char* channel)
31 {
32     // Set up our DBus and event loop
33     auto event = sdeventplus::Event::get_default();
34     auto bus = sdbusplus::bus::new_default();
35     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
36 
37     // Configure basic signal handling
38     auto exit_handler = [&event](Signal&, const struct signalfd_siginfo*) {
39         fmt::print(stderr, "Interrupted, Exiting\n");
40         event.exit(0);
41     };
42     stdplus::signal::block(SIGINT);
43     Signal sig_int(event, SIGINT, exit_handler);
44     stdplus::signal::block(SIGTERM);
45     Signal sig_term(event, SIGTERM, exit_handler);
46 
47     // Open an FD for the KCS channel
48     stdplus::ManagedFd kcs = stdplus::fd::open(
49         fmt::format("/dev/{}", channel),
50         OpenFlags(OpenAccess::ReadWrite).set(OpenFlag::NonBlock));
51     sdbusplus::slot::slot slot(nullptr);
52 
53     // Add a reader to the bus for handling inbound IPMI
54     IO ioSource(
55         event, kcs.get(), EPOLLIN | EPOLLET,
56         stdplus::exception::ignore(
57             [&kcs, &bus, &slot](IO&, int, uint32_t) { read(kcs, bus, slot); }));
58 
59     // Allow processes to affect the state machine
60     std::string dbusChannel = channel;
61     std::replace(dbusChannel.begin(), dbusChannel.end(), '-', '_');
62     auto obj = "/xyz/openbmc_project/Ipmi/Channel/" + dbusChannel;
63     auto srv = "xyz.openbmc_project.Ipmi.Channel." + dbusChannel;
64     auto intf = createSMSHandler(bus, obj.c_str(), kcs);
65     bus.request_name(srv.c_str());
66 
67     sd_notify(0, "READY=1");
68     return event.loop();
69 }
70 
71 } // namespace kcsbridge
72 
73 int main(int argc, char* argv[])
74 {
75     try
76     {
77         kcsbridge::Args args(argc, argv);
78         return kcsbridge::execute(args.channel);
79     }
80     catch (const std::exception& e)
81     {
82         fmt::print(stderr, "FAILED: {}\n", e.what());
83         return 1;
84     }
85 }
86