buffer: Implement "readEntryHeader"

Add struct QueueEntryHeader along with it.

Tested: Unit Tested

Signed-off-by: Brandon Kim <brandonkim@google.com>
Change-Id: Icbfe8d39db4242664794d8c65a84488aeffd23a6
diff --git a/include/buffer.hpp b/include/buffer.hpp
index ad845c4..d199a94 100644
--- a/include/buffer.hpp
+++ b/include/buffer.hpp
@@ -49,6 +49,24 @@
 static_assert(sizeof(CircularBufferHeader) == 0x30,
               "Size of CircularBufferHeader struct is incorrect.");
 
+struct QueueEntryHeader
+{
+    little_uint16_t sequenceId; // Offset 0x0
+    little_uint16_t entrySize;  // Offset 0x2
+    uint8_t checksum;           // Offset 0x4
+    uint8_t rdeCommandType;     // Offset 0x5
+    // RDE Command                 Offset 0x6
+    bool operator==(const QueueEntryHeader& other) const
+    {
+        return std::tie(this->sequenceId, this->entrySize, this->checksum,
+                        this->rdeCommandType) ==
+               std::tie(other.sequenceId, other.entrySize, other.checksum,
+                        other.rdeCommandType);
+    }
+};
+static_assert(sizeof(QueueEntryHeader) == 0x6,
+              "Size of QueueEntryHeader struct is incorrect.");
+
 /**
  * An interface class for the buffer helper APIs
  */
@@ -99,6 +117,13 @@
     virtual std::vector<uint8_t>
         wraparoundRead(const uint32_t offset, const uint32_t length,
                        const uint32_t additionalBoundaryCheck) = 0;
+    /**
+     * Read the entry header from shared buffer
+     *
+     * @param[in] offset - offset to read from
+     * @return the entry header
+     */
+    virtual struct QueueEntryHeader readEntryHeader(size_t offset) = 0;
 };
 
 /**
@@ -120,6 +145,7 @@
     std::vector<uint8_t>
         wraparoundRead(const uint32_t offset, const uint32_t length,
                        const uint32_t additionalBoundaryCheck = 0) override;
+    struct QueueEntryHeader readEntryHeader(size_t offset) override;
 
   private:
     /** @brief The Error log queue starts after the UE region, which is where
diff --git a/src/buffer.cpp b/src/buffer.cpp
index 0b6f460..87d9fa2 100644
--- a/src/buffer.cpp
+++ b/src/buffer.cpp
@@ -160,4 +160,14 @@
     return bytesRead;
 }
 
+struct QueueEntryHeader BufferImpl::readEntryHeader(size_t offset)
+{
+    size_t headerSize = sizeof(struct QueueEntryHeader);
+    // wraparonudRead will throw if it did not read all the bytes, let it
+    // propagate up the stack
+    std::vector<uint8_t> bytesRead = wraparoundRead(offset, headerSize);
+
+    return *reinterpret_cast<struct QueueEntryHeader*>(bytesRead.data());
+}
+
 } // namespace bios_bmc_smm_error_logger
diff --git a/test/buffer_test.cpp b/test/buffer_test.cpp
index 290d1ca..9042f67 100644
--- a/test/buffer_test.cpp
+++ b/test/buffer_test.cpp
@@ -343,5 +343,49 @@
                 ElementsAreArray(expectedBytes));
 }
 
+class BufferEntryHeaderTest : public BufferWraparoundReadTest
+{
+  protected:
+    BufferEntryHeaderTest()
+    {
+        testEntryHeader.sequenceId = testSequenceId;
+        testEntryHeader.entrySize = testEntrySize;
+        testEntryHeader.checksum = testChecksum;
+        testEntryHeader.rdeCommandType = testRdeCommandType;
+    }
+    ~BufferEntryHeaderTest() override = default;
+
+    void wraparoundReadMock(std::span<std::uint8_t> expetedBytesOutput)
+    {
+        EXPECT_CALL(*dataInterfaceMockPtr, getMemoryRegionSize())
+            .WillOnce(Return(testRegionSize));
+        EXPECT_CALL(*dataInterfaceMockPtr, read(_, _))
+            .WillOnce(Return(std::vector<std::uint8_t>(
+                expetedBytesOutput.begin(), expetedBytesOutput.end())));
+
+        EXPECT_CALL(*dataInterfaceMockPtr, write(_, _))
+            .WillOnce(Return(expectedWriteSize));
+    }
+
+    static constexpr size_t entryHeaderSize = sizeof(struct QueueEntryHeader);
+    static constexpr uint16_t testSequenceId = 0;
+    static constexpr uint16_t testEntrySize = 0x20;
+    static constexpr uint8_t testChecksum = 1;
+    static constexpr uint8_t testRdeCommandType = 0x01;
+    size_t testOffset = 0x50;
+
+    struct QueueEntryHeader testEntryHeader
+    {};
+};
+
+TEST_F(BufferEntryHeaderTest, ReadEntryHeaderPass)
+{
+    uint8_t* testEntryHeaderPtr = reinterpret_cast<uint8_t*>(&testEntryHeader);
+    std::vector<uint8_t> testEntryHeaderVector(
+        testEntryHeaderPtr, testEntryHeaderPtr + entryHeaderSize);
+    wraparoundReadMock(testEntryHeaderVector);
+    EXPECT_EQ(bufferImpl->readEntryHeader(testOffset), testEntryHeader);
+}
+
 } // namespace
 } // namespace bios_bmc_smm_error_logger