Support IPMI Serial Transport
Support IPMI Serial interface (basic mode) based on Sec 14,
IPMI 2.0 spec. Serial transport tested with meta-evb-arm
platform with socat and ipmitool.
HW transport can be selected by meson configure flasg.
Tested:
1. socat -x pty,raw,echo=0,link=/tmp/ttyHOST2BMC tcp:localhost:5066
2. ipmitool -I serial-basic -D /tmp/ttyHOST2BMC:115200 mc info
Device ID : 0
Device Revision : 0
Firmware Revision : 2.17
IPMI Version : 2.0
Manufacturer ID : 0
Manufacturer Name : Unknown
Product ID : 0 (0x0000)
Product Name : Unknown (0x0)
Device Available : no
Provides Device SDRs : no
Additional Device Support :
Aux Firmware Rev Info :
0x00
0x00
0x00
0x00
Change-Id: I2a56390022fce7a974ed75ed6a72ad3fffed9bb6
Signed-off-by: John Chung <john.chung@arm.com>
diff --git a/transport/serialbridge/serialbridged.cpp b/transport/serialbridge/serialbridged.cpp
new file mode 100644
index 0000000..b022dc6
--- /dev/null
+++ b/transport/serialbridge/serialbridged.cpp
@@ -0,0 +1,85 @@
+#include "serialcmd.hpp"
+
+#include <systemd/sd-daemon.h>
+
+#include <CLI/CLI.hpp>
+#include <phosphor-logging/lg2.hpp>
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/slot.hpp>
+#include <sdeventplus/event.hpp>
+#include <sdeventplus/source/io.hpp>
+#include <sdeventplus/source/signal.hpp>
+#include <stdplus/exception.hpp>
+#include <stdplus/fd/create.hpp>
+#include <stdplus/fd/ops.hpp>
+#include <stdplus/signal.hpp>
+
+namespace serialbridge
+{
+
+using sdeventplus::source::IO;
+using sdeventplus::source::Signal;
+using stdplus::fd::OpenAccess;
+using stdplus::fd::OpenFlag;
+using stdplus::fd::OpenFlags;
+
+int execute(const std::string& channel, const bool& verbose)
+{
+ // Set up DBus and event loop
+ auto event = sdeventplus::Event::get_default();
+ auto bus = sdbusplus::bus::new_default();
+ bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
+
+ // Configure basic signal handling
+ auto exit_handler = [&event](Signal&, const struct signalfd_siginfo*) {
+ lg2::error("Interrupted, Exiting\n");
+ event.exit(0);
+ };
+ stdplus::signal::block(SIGINT);
+ Signal sig_init(event, SIGINT, exit_handler);
+ stdplus::signal::block(SIGTERM);
+ Signal sig_term(event, SIGTERM, exit_handler);
+
+ // Open an FD for the UART channel
+ stdplus::ManagedFd uart = stdplus::fd::open(
+ std::format("/dev/{}", channel.c_str()),
+ OpenFlags(OpenAccess::ReadWrite).set(OpenFlag::NonBlock));
+ sdbusplus::slot_t slot(nullptr);
+
+ std::unique_ptr<SerialChannel> serialchannel =
+ std::make_unique<SerialChannel>(verbose);
+
+ // Add a reader to the bus for handling inbound IPMI
+ IO ioSource(event, uart.get(), EPOLLIN | EPOLLET,
+ stdplus::exception::ignore(
+ [&serialchannel, &uart, &bus, &slot](IO&, int, uint32_t) {
+ serialchannel->read(uart, bus, slot);
+ }));
+
+ sd_notify(0, "READY=1");
+ return event.loop();
+}
+
+} // namespace serialbridge
+
+int main(int argc, char* argv[])
+{
+ std::string device;
+ bool verbose = 0;
+
+ // Parse input parameter
+ CLI::App app("Serial IPMI Bridge");
+ app.add_option("-d,--device", device, "select uart device");
+ app.add_option("-v,--verbose", verbose, "enable debug message");
+ CLI11_PARSE(app, argc, argv);
+
+ try
+ {
+ return serialbridge::execute(device, verbose);
+ }
+ catch (const std::exception& e)
+ {
+ lg2::error("FAILED: {MSG}\n", "MSG", e);
+ return 1;
+ }
+}