xref: /openbmc/phosphor-host-ipmid/transport/serialbridge/serialbridged.cpp (revision e2fae4b9fe17e30149b077b38ea513d7207c5405)
1 #include "serialcmd.hpp"
2 
3 #include <systemd/sd-daemon.h>
4 
5 #include <CLI/CLI.hpp>
6 #include <phosphor-logging/lg2.hpp>
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/fd/ops.hpp>
15 #include <stdplus/signal.hpp>
16 
17 namespace serialbridge
18 {
19 
20 using sdeventplus::source::IO;
21 using sdeventplus::source::Signal;
22 using stdplus::fd::OpenAccess;
23 using stdplus::fd::OpenFlag;
24 using stdplus::fd::OpenFlags;
25 
execute(const std::string & channel,const bool & verbose)26 int execute(const std::string& channel, const bool& verbose)
27 {
28     // Set up DBus and event loop
29     auto event = sdeventplus::Event::get_default();
30     auto bus = sdbusplus::bus::new_default();
31     bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
32 
33     // Configure basic signal handling
34     auto exit_handler = [&event](Signal&, const struct signalfd_siginfo*) {
35         lg2::error("Interrupted, Exiting\n");
36         event.exit(0);
37     };
38     stdplus::signal::block(SIGINT);
39     Signal sig_init(event, SIGINT, exit_handler);
40     stdplus::signal::block(SIGTERM);
41     Signal sig_term(event, SIGTERM, exit_handler);
42 
43     // Open an FD for the UART channel
44     stdplus::ManagedFd uart = stdplus::fd::open(
45         std::format("/dev/{}", channel.c_str()),
46         OpenFlags(OpenAccess::ReadWrite).set(OpenFlag::NonBlock));
47     sdbusplus::slot_t slot(nullptr);
48 
49     std::unique_ptr<SerialChannel> serialchannel =
50         std::make_unique<SerialChannel>(verbose);
51 
52     // Add a reader to the bus for handling inbound IPMI
53     IO ioSource(event, uart.get(), EPOLLIN | EPOLLET,
54                 stdplus::exception::ignore(
55                     [&serialchannel, &uart, &bus, &slot](IO&, int, uint32_t) {
56                         serialchannel->read(uart, bus, slot);
57                     }));
58 
59     sd_notify(0, "READY=1");
60     return event.loop();
61 }
62 
63 } // namespace serialbridge
64 
main(int argc,char * argv[])65 int main(int argc, char* argv[])
66 {
67     std::string device;
68     bool verbose = 0;
69 
70     // Parse input parameter
71     CLI::App app("Serial IPMI Bridge");
72     app.add_option("-d,--device", device, "select uart device");
73     app.add_option("-v,--verbose", verbose, "enable debug message");
74     CLI11_PARSE(app, argc, argv);
75 
76     try
77     {
78         return serialbridge::execute(device, verbose);
79     }
80     catch (const std::exception& e)
81     {
82         lg2::error("FAILED: {MSG}\n", "MSG", e);
83         return 1;
84     }
85 }
86