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