Add a IPMI blob handler for SMBIOS tables

smbios-mdr has dependencies on intel-ipmi-oem which makes BIOS sending
SMBIOS tables to BMC through VGA shared memory. For platforms without
intel-ipmi-oem, implement a IPMI blob hanler so that BIOS can send
SMBIOS tables through IPMI blob interfaces.

Test:
Unit tests for the IPMI blob handler.
Manual test that transfers SMBIOS tables to BMC through IPMI blob
interfaces on a platform host.

Signed-off-by: Jie Yang <jjy@google.com>
Change-Id: I9bc1ae7e9bfaa793e47e38fa19049f0f69355189
diff --git a/src/smbios-ipmi-blobs/test/handler_statclose_unittest.cpp b/src/smbios-ipmi-blobs/test/handler_statclose_unittest.cpp
new file mode 100644
index 0000000..b8d32cd
--- /dev/null
+++ b/src/smbios-ipmi-blobs/test/handler_statclose_unittest.cpp
@@ -0,0 +1,78 @@
+#include "handler_unittest.hpp"
+
+#include <blobs-ipmid/blobs.hpp>
+
+#include <cstdint>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+namespace blobs
+{
+
+class SmbiosBlobHandlerStatCloseTest : public SmbiosBlobHandlerTest
+{
+  protected:
+    blobs::BlobMeta meta;
+
+    // Initialize expected_meta_ with empty members
+    blobs::BlobMeta expected_meta_session = {};
+    blobs::BlobMeta expected_meta_path = {};
+};
+
+TEST_F(SmbiosBlobHandlerStatCloseTest, InvalidSessionStatIsRejected)
+{
+    EXPECT_FALSE(handler.stat(session, &meta));
+}
+
+TEST_F(SmbiosBlobHandlerStatCloseTest, SessionStatAlwaysInitialReadAndWrite)
+{
+    // Verify the session stat returns the information for a session.
+
+    EXPECT_TRUE(handler.open(session, blobs::OpenFlags::write, expectedBlobId));
+
+    EXPECT_TRUE(handler.stat(session, &meta));
+    expected_meta_session.blobState = blobs::StateFlags::open_write;
+    EXPECT_EQ(meta, expected_meta_session);
+
+    EXPECT_TRUE(handler.stat(expectedBlobId, &meta));
+    expected_meta_path.blobState = blobs::StateFlags::open_write;
+    EXPECT_EQ(meta, expected_meta_path);
+}
+
+TEST_F(SmbiosBlobHandlerStatCloseTest, AfterWriteMetadataLengthMatches)
+{
+    // Verify that after writes, the length returned matches.
+
+    std::vector<uint8_t> data = {0x01};
+    EXPECT_TRUE(handler.open(session, blobs::OpenFlags::write, expectedBlobId));
+    EXPECT_TRUE(handler.write(session, handlerMaxBufferSize - 1, data));
+
+    // We wrote one byte to the last index, making the length the buffer size.
+    EXPECT_TRUE(handler.stat(session, &meta));
+    expected_meta_session.size = handlerMaxBufferSize;
+    expected_meta_session.blobState = blobs::StateFlags::open_write;
+    EXPECT_EQ(meta, expected_meta_session);
+
+    EXPECT_TRUE(handler.stat(expectedBlobId, &meta));
+    expected_meta_path.size = handlerMaxBufferSize;
+    expected_meta_path.blobState = blobs::StateFlags::open_write;
+    EXPECT_EQ(meta, expected_meta_path);
+}
+
+TEST_F(SmbiosBlobHandlerStatCloseTest, CloseWithInvalidSessionFails)
+{
+    // Verify you cannot close an invalid session.
+
+    EXPECT_FALSE(handler.close(session));
+}
+
+TEST_F(SmbiosBlobHandlerStatCloseTest, CloseWithValidSessionSuccess)
+{
+    // Verify you can close a valid session.
+
+    EXPECT_TRUE(handler.open(session, 0, expectedBlobId));
+
+    EXPECT_TRUE(handler.close(session));
+}
+} // namespace blobs