1 #include "args.hpp" 2 #include "cmd.hpp" 3 #include "print.hpp" 4 #include "server.hpp" 5 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 <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 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 std::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 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 std::print(stderr, "FAILED: {}\n", e.what()); 86 return 1; 87 } 88 } 89