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