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/test/serial_unittest.cpp b/transport/serialbridge/test/serial_unittest.cpp
new file mode 100644
index 0000000..3fb0227
--- /dev/null
+++ b/transport/serialbridge/test/serial_unittest.cpp
@@ -0,0 +1,84 @@
+#include <transport/serialbridge/serialcmd.hpp>
+
+#include <gtest/gtest.h>
+
+namespace serialbridge
+{
+
+/**
+ * @brief Table of special characters
+ */
+std::unordered_map<uint8_t, uint8_t> testsets = {
+ {bmStart, 0xB0}, /* start */
+ {bmStop, 0xB5}, /* stop */
+ {bmHandshake, 0xB6}, /* packet handshake */
+ {bmEscape, 0xBA}, /* data escape */
+ {0x1B, 0x3B} /* escape */
+};
+
+TEST(TestSpecialCharact, getUnescapedCharact)
+{
+ uint8_t c;
+ auto channel = std::make_shared<SerialChannel>(0);
+
+ for (const auto& set : testsets)
+ {
+ c = channel->getUnescapedCharacter(set.second);
+ ASSERT_EQ(c, set.first);
+ }
+}
+
+TEST(TestSpecialCharact, processEscapedCharacter)
+{
+ std::vector<uint8_t> buffer;
+ uint8_t unescaped = 0xd0;
+ auto channel = std::make_shared<SerialChannel>(0);
+
+ channel->processEscapedCharacter(buffer, std::vector<uint8_t>{bmStart});
+
+ ASSERT_EQ(buffer.at(0), bmEscape);
+ ASSERT_EQ(buffer.at(1), testsets.at(bmStart));
+
+ buffer.clear();
+ channel->processEscapedCharacter(buffer, std::vector<uint8_t>{unescaped});
+
+ ASSERT_EQ(buffer.at(0), unescaped);
+}
+
+TEST(TestChecksum, calculateChecksum)
+{
+ std::array<uint8_t, 5> dataBytes{0x01, 0x10, 0x60, 0xf0, 0x50};
+ auto channel = std::make_shared<SerialChannel>(0);
+
+ uint8_t checksum =
+ channel->calculateChecksum(std::span<uint8_t>(dataBytes));
+
+ checksum += (~checksum) + 1;
+ ASSERT_EQ(checksum, 0);
+}
+
+TEST(TestIpmiSerialPacket, consumeIpmiSerialPacket)
+{
+ std::vector<uint8_t> dataBytes{bmStart, 0x20, 0x18, 0xc8, 0x81,
+ 0xc, 0x46, 0x01, 0x2c, bmStop};
+ std::vector<uint8_t> dataBytesSplit1{bmStart, 0x20, 0x18, 0xc8};
+ std::vector<uint8_t> dataBytesSplit2{0x81, 0xc, 0x46, 0x01, 0x2c, bmStop};
+ std::span<uint8_t> input(dataBytes);
+ std::span<uint8_t> input1(dataBytesSplit1);
+ std::span<uint8_t> input2(dataBytesSplit2);
+ std::vector<uint8_t> output;
+
+ auto channel = std::make_shared<SerialChannel>(0);
+
+ auto result = channel->consumeIpmiSerialPacket(input, output);
+
+ ASSERT_EQ(result, true);
+
+ output.clear();
+ result = channel->consumeIpmiSerialPacket(input1, output);
+ ASSERT_EQ(result, false);
+ result = channel->consumeIpmiSerialPacket(input2, output);
+ ASSERT_EQ(result, true);
+}
+
+} // namespace serialbridge