xref: /openbmc/bios-bmc-smm-error-logger/src/buffer.cpp (revision 82ab8320be0e10c64f78bd46e68693174052a822)
1*82ab8320SBrandon Kim #include "config.h"
2*82ab8320SBrandon Kim 
3fcbc3db1SBrandon Kim #include "buffer.hpp"
4fcbc3db1SBrandon Kim 
5fcbc3db1SBrandon Kim #include "pci_handler.hpp"
6fcbc3db1SBrandon Kim 
7fcbc3db1SBrandon Kim #include <fmt/format.h>
8fcbc3db1SBrandon Kim 
917ee1a93SBrandon Kim #include <boost/endian/arithmetic.hpp>
1017ee1a93SBrandon Kim #include <boost/endian/conversion.hpp>
1117ee1a93SBrandon Kim 
1217ee1a93SBrandon Kim #include <algorithm>
13fcbc3db1SBrandon Kim #include <array>
14cf0b9752SBrandon Kim #include <cstddef>
15fcbc3db1SBrandon Kim #include <cstdint>
16fcbc3db1SBrandon Kim #include <memory>
1740ce08e1SBrandon Kim #include <numeric>
18fcbc3db1SBrandon Kim #include <span>
19fcbc3db1SBrandon Kim #include <vector>
20fcbc3db1SBrandon Kim 
21fcbc3db1SBrandon Kim namespace bios_bmc_smm_error_logger
22fcbc3db1SBrandon Kim {
23fcbc3db1SBrandon Kim 
24fcbc3db1SBrandon Kim BufferImpl::BufferImpl(std::unique_ptr<DataInterface> dataInterface) :
25fcbc3db1SBrandon Kim     dataInterface(std::move(dataInterface)){};
26fcbc3db1SBrandon Kim 
27fcbc3db1SBrandon Kim void BufferImpl::initialize(uint32_t bmcInterfaceVersion, uint16_t queueSize,
28fcbc3db1SBrandon Kim                             uint16_t ueRegionSize,
29fcbc3db1SBrandon Kim                             const std::array<uint32_t, 4>& magicNumber)
30fcbc3db1SBrandon Kim {
31fcbc3db1SBrandon Kim     const size_t memoryRegionSize = dataInterface->getMemoryRegionSize();
323def3c8eSBrandon Kim     if (queueSize > memoryRegionSize)
3326660e9bSBrandon Kim     {
3426660e9bSBrandon Kim         throw std::runtime_error(fmt::format(
353def3c8eSBrandon Kim             "[initialize] Proposed queue size '{}' is bigger than the "
3626660e9bSBrandon Kim             "BMC's allocated MMIO region of '{}'",
373def3c8eSBrandon Kim             queueSize, memoryRegionSize));
3826660e9bSBrandon Kim     }
3926660e9bSBrandon Kim 
4026660e9bSBrandon Kim     // Initialize the whole buffer with 0x00
413def3c8eSBrandon Kim     const std::vector<uint8_t> emptyVector(queueSize, 0);
42fcbc3db1SBrandon Kim     size_t byteWritten = dataInterface->write(0, emptyVector);
433def3c8eSBrandon Kim     if (byteWritten != queueSize)
44fcbc3db1SBrandon Kim     {
45fcbc3db1SBrandon Kim         throw std::runtime_error(
4626660e9bSBrandon Kim             fmt::format("[initialize] Only erased '{}'", byteWritten));
47fcbc3db1SBrandon Kim     }
48fcbc3db1SBrandon Kim 
49fcbc3db1SBrandon Kim     // Create an initial buffer header and write to it
50fcbc3db1SBrandon Kim     struct CircularBufferHeader initializationHeader = {};
5117ee1a93SBrandon Kim     initializationHeader.bmcInterfaceVersion =
5217ee1a93SBrandon Kim         boost::endian::native_to_little(bmcInterfaceVersion);
5317ee1a93SBrandon Kim     initializationHeader.queueSize = boost::endian::native_to_little(queueSize);
5417ee1a93SBrandon Kim     initializationHeader.ueRegionSize =
5517ee1a93SBrandon Kim         boost::endian::native_to_little(ueRegionSize);
5617ee1a93SBrandon Kim     std::transform(magicNumber.begin(), magicNumber.end(),
5717ee1a93SBrandon Kim                    initializationHeader.magicNumber.begin(),
5817ee1a93SBrandon Kim                    [](uint32_t number) -> little_uint32_t {
5917ee1a93SBrandon Kim                        return boost::endian::native_to_little(number);
6017ee1a93SBrandon Kim                    });
61fcbc3db1SBrandon Kim 
62fcbc3db1SBrandon Kim     uint8_t* initializationHeaderPtr =
63fcbc3db1SBrandon Kim         reinterpret_cast<uint8_t*>(&initializationHeader);
64fcbc3db1SBrandon Kim     size_t initializationHeaderSize = sizeof(initializationHeader);
65fcbc3db1SBrandon Kim     byteWritten = dataInterface->write(
66fcbc3db1SBrandon Kim         0, std::span<const uint8_t>(initializationHeaderPtr,
67fcbc3db1SBrandon Kim                                     initializationHeaderPtr +
68fcbc3db1SBrandon Kim                                         initializationHeaderSize));
69fcbc3db1SBrandon Kim     if (byteWritten != initializationHeaderSize)
70fcbc3db1SBrandon Kim     {
71fcbc3db1SBrandon Kim         throw std::runtime_error(fmt::format(
7226660e9bSBrandon Kim             "[initialize] Only wrote '{}' bytes of the header", byteWritten));
73fcbc3db1SBrandon Kim     }
7460cab57fSBrandon Kim     cachedBufferHeader = initializationHeader;
75fcbc3db1SBrandon Kim }
76fcbc3db1SBrandon Kim 
7717ee1a93SBrandon Kim void BufferImpl::readBufferHeader()
7817ee1a93SBrandon Kim {
7917ee1a93SBrandon Kim     size_t headerSize = sizeof(struct CircularBufferHeader);
80b8125763SPatrick Williams     std::vector<uint8_t> bytesRead = dataInterface->read(/*offset=*/0,
81b8125763SPatrick Williams                                                          headerSize);
8217ee1a93SBrandon Kim 
8317ee1a93SBrandon Kim     if (bytesRead.size() != headerSize)
8417ee1a93SBrandon Kim     {
8517ee1a93SBrandon Kim         throw std::runtime_error(
8617ee1a93SBrandon Kim             fmt::format("Buffer header read only read '{}', expected '{}'",
8717ee1a93SBrandon Kim                         bytesRead.size(), headerSize));
8817ee1a93SBrandon Kim     }
8917ee1a93SBrandon Kim 
9017ee1a93SBrandon Kim     cachedBufferHeader =
9160cab57fSBrandon Kim         *reinterpret_cast<struct CircularBufferHeader*>(bytesRead.data());
9217ee1a93SBrandon Kim };
9317ee1a93SBrandon Kim 
9417ee1a93SBrandon Kim struct CircularBufferHeader BufferImpl::getCachedBufferHeader() const
9517ee1a93SBrandon Kim {
9617ee1a93SBrandon Kim     return cachedBufferHeader;
9717ee1a93SBrandon Kim }
9817ee1a93SBrandon Kim 
99cf0b9752SBrandon Kim void BufferImpl::updateReadPtr(const uint32_t newReadPtr)
100cf0b9752SBrandon Kim {
101b8125763SPatrick Williams     constexpr uint8_t bmcReadPtrOffset = offsetof(struct CircularBufferHeader,
102b8125763SPatrick Williams                                                   bmcReadPtr);
103cf0b9752SBrandon Kim 
104271d2313SBrandon Kim     little_uint24_t truncatedReadPtr =
105271d2313SBrandon Kim         boost::endian::native_to_little(newReadPtr & 0xffffff);
106cf0b9752SBrandon Kim     uint8_t* truncatedReadPtrPtr =
107cf0b9752SBrandon Kim         reinterpret_cast<uint8_t*>(&truncatedReadPtr);
108cf0b9752SBrandon Kim 
109cf0b9752SBrandon Kim     size_t writtenSize = dataInterface->write(
110cf0b9752SBrandon Kim         bmcReadPtrOffset, std::span<const uint8_t>{
111cf0b9752SBrandon Kim                               truncatedReadPtrPtr,
112271d2313SBrandon Kim                               truncatedReadPtrPtr + sizeof(truncatedReadPtr)});
113271d2313SBrandon Kim     if (writtenSize != sizeof(truncatedReadPtr))
114cf0b9752SBrandon Kim     {
115cf0b9752SBrandon Kim         throw std::runtime_error(fmt::format(
116cf0b9752SBrandon Kim             "[updateReadPtr] Wrote '{}' bytes, instead of expected '{}'",
117271d2313SBrandon Kim             writtenSize, sizeof(truncatedReadPtr)));
118cf0b9752SBrandon Kim     }
119cf0b9752SBrandon Kim     cachedBufferHeader.bmcReadPtr = truncatedReadPtr;
120cf0b9752SBrandon Kim }
121cf0b9752SBrandon Kim 
122c49284b6SBrandon Kim void BufferImpl::updateBmcFlags(const uint32_t newBmcFlag)
123c49284b6SBrandon Kim {
124b8125763SPatrick Williams     constexpr uint8_t bmcFlagsPtrOffset = offsetof(struct CircularBufferHeader,
125b8125763SPatrick Williams                                                    bmcFlags);
126c49284b6SBrandon Kim 
127c49284b6SBrandon Kim     little_uint32_t littleNewBmcFlag =
128c49284b6SBrandon Kim         boost::endian::native_to_little(newBmcFlag);
129c49284b6SBrandon Kim     uint8_t* littleNewBmcFlagPtr =
130c49284b6SBrandon Kim         reinterpret_cast<uint8_t*>(&littleNewBmcFlag);
131c49284b6SBrandon Kim 
132c49284b6SBrandon Kim     size_t writtenSize = dataInterface->write(
133c49284b6SBrandon Kim         bmcFlagsPtrOffset, std::span<const uint8_t>{
134c49284b6SBrandon Kim                                littleNewBmcFlagPtr,
135c49284b6SBrandon Kim                                littleNewBmcFlagPtr + sizeof(little_uint32_t)});
136c49284b6SBrandon Kim     if (writtenSize != sizeof(little_uint32_t))
137c49284b6SBrandon Kim     {
138c49284b6SBrandon Kim         throw std::runtime_error(fmt::format(
139c49284b6SBrandon Kim             "[updateBmcFlags] Wrote '{}' bytes, instead of expected '{}'",
140c49284b6SBrandon Kim             writtenSize, sizeof(little_uint32_t)));
141c49284b6SBrandon Kim     }
142c49284b6SBrandon Kim     cachedBufferHeader.bmcFlags = littleNewBmcFlag;
143c49284b6SBrandon Kim }
144c49284b6SBrandon Kim 
14535d4335eSBrandon Kim std::vector<uint8_t> BufferImpl::wraparoundRead(const uint32_t relativeOffset,
14635d4335eSBrandon Kim                                                 const uint32_t length)
1479836cfa6SBrandon Kim {
1483def3c8eSBrandon Kim     const size_t maxOffset = getMaxOffset();
1499836cfa6SBrandon Kim 
1503def3c8eSBrandon Kim     if (relativeOffset > maxOffset)
15135d4335eSBrandon Kim     {
15235d4335eSBrandon Kim         throw std::runtime_error(
15335d4335eSBrandon Kim             fmt::format("[wraparoundRead] relativeOffset '{}' was bigger "
1543def3c8eSBrandon Kim                         "than maxOffset '{}'",
1553def3c8eSBrandon Kim                         relativeOffset, maxOffset));
15635d4335eSBrandon Kim     }
1573def3c8eSBrandon Kim     if (length > maxOffset)
1589836cfa6SBrandon Kim     {
1599836cfa6SBrandon Kim         throw std::runtime_error(fmt::format(
1603def3c8eSBrandon Kim             "[wraparoundRead] length '{}' was bigger than maxOffset '{}'",
1613def3c8eSBrandon Kim             length, maxOffset));
1629836cfa6SBrandon Kim     }
1639836cfa6SBrandon Kim 
16435d4335eSBrandon Kim     // Do a calculation to see if the read will wraparound
16535d4335eSBrandon Kim     const size_t queueOffset = getQueueOffset();
1663def3c8eSBrandon Kim     const size_t writableSpace = maxOffset - relativeOffset;
16735d4335eSBrandon Kim     size_t numWraparoundBytesToRead = 0;
1683def3c8eSBrandon Kim     if (length > writableSpace)
16935d4335eSBrandon Kim     {
17035d4335eSBrandon Kim         // This means we will wrap, count the bytes that are left to read
1713def3c8eSBrandon Kim         numWraparoundBytesToRead = length - writableSpace;
17235d4335eSBrandon Kim     }
17335d4335eSBrandon Kim     const size_t numBytesToReadTillQueueEnd = length - numWraparoundBytesToRead;
17435d4335eSBrandon Kim 
17535d4335eSBrandon Kim     std::vector<uint8_t> bytesRead = dataInterface->read(
17635d4335eSBrandon Kim         queueOffset + relativeOffset, numBytesToReadTillQueueEnd);
17735d4335eSBrandon Kim     if (bytesRead.size() != numBytesToReadTillQueueEnd)
17835d4335eSBrandon Kim     {
17935d4335eSBrandon Kim         throw std::runtime_error(
18035d4335eSBrandon Kim             fmt::format("[wraparoundRead] Read '{}' which was not "
18135d4335eSBrandon Kim                         "the requested length of '{}'",
18235d4335eSBrandon Kim                         bytesRead.size(), numBytesToReadTillQueueEnd));
18335d4335eSBrandon Kim     }
18435d4335eSBrandon Kim     size_t updatedReadPtr = relativeOffset + numBytesToReadTillQueueEnd;
1853def3c8eSBrandon Kim     if (updatedReadPtr == maxOffset)
1864662b1bdSBrandon Kim     {
1874662b1bdSBrandon Kim         // If we read all the way up to the end of the queue, we need to
1884662b1bdSBrandon Kim         // manually wrap the updateReadPtr around to 0
1894662b1bdSBrandon Kim         updatedReadPtr = 0;
1904662b1bdSBrandon Kim     }
1919836cfa6SBrandon Kim 
1929836cfa6SBrandon Kim     // If there are any more bytes to be read beyond the buffer, wrap around and
1939836cfa6SBrandon Kim     // read from the beginning of the buffer (offset by the queueOffset)
19435d4335eSBrandon Kim     if (numWraparoundBytesToRead > 0)
1959836cfa6SBrandon Kim     {
1969836cfa6SBrandon Kim         std::vector<uint8_t> wrappedBytesRead =
19735d4335eSBrandon Kim             dataInterface->read(queueOffset, numWraparoundBytesToRead);
19835d4335eSBrandon Kim         if (numWraparoundBytesToRead != wrappedBytesRead.size())
1999836cfa6SBrandon Kim         {
2009836cfa6SBrandon Kim             throw std::runtime_error(fmt::format(
20135d4335eSBrandon Kim                 "[wraparoundRead] Buffer wrapped around but read '{}' which "
20235d4335eSBrandon Kim                 "was not the requested lenght of '{}'",
20335d4335eSBrandon Kim                 wrappedBytesRead.size(), numWraparoundBytesToRead));
2049836cfa6SBrandon Kim         }
2059836cfa6SBrandon Kim         bytesRead.insert(bytesRead.end(), wrappedBytesRead.begin(),
2069836cfa6SBrandon Kim                          wrappedBytesRead.end());
20735d4335eSBrandon Kim         updatedReadPtr = numWraparoundBytesToRead;
2089836cfa6SBrandon Kim     }
20935d4335eSBrandon Kim     updateReadPtr(updatedReadPtr);
2109836cfa6SBrandon Kim 
2119836cfa6SBrandon Kim     return bytesRead;
2129836cfa6SBrandon Kim }
2139836cfa6SBrandon Kim 
214613ba537SBrandon Kim struct QueueEntryHeader BufferImpl::readEntryHeader()
2157bac2d69SBrandon Kim {
2167bac2d69SBrandon Kim     size_t headerSize = sizeof(struct QueueEntryHeader);
2177bac2d69SBrandon Kim     // wraparonudRead will throw if it did not read all the bytes, let it
2187bac2d69SBrandon Kim     // propagate up the stack
219613ba537SBrandon Kim     std::vector<uint8_t> bytesRead = wraparoundRead(
220613ba537SBrandon Kim         boost::endian::little_to_native(cachedBufferHeader.bmcReadPtr),
221613ba537SBrandon Kim         headerSize);
2227bac2d69SBrandon Kim 
2237bac2d69SBrandon Kim     return *reinterpret_cast<struct QueueEntryHeader*>(bytesRead.data());
2247bac2d69SBrandon Kim }
2257bac2d69SBrandon Kim 
226613ba537SBrandon Kim EntryPair BufferImpl::readEntry()
22740ce08e1SBrandon Kim {
228613ba537SBrandon Kim     struct QueueEntryHeader entryHeader = readEntryHeader();
22935d4335eSBrandon Kim     size_t entrySize = boost::endian::little_to_native(entryHeader.entrySize);
23040ce08e1SBrandon Kim 
23140ce08e1SBrandon Kim     // wraparonudRead may throw if entrySize was bigger than the buffer or if it
23226660e9bSBrandon Kim     // was not able to read all the bytes, let it propagate up the stack
23335d4335eSBrandon Kim     std::vector<uint8_t> entry = wraparoundRead(
234613ba537SBrandon Kim         boost::endian::little_to_native(cachedBufferHeader.bmcReadPtr),
235613ba537SBrandon Kim         entrySize);
23640ce08e1SBrandon Kim 
23740ce08e1SBrandon Kim     // Calculate the checksum
23840ce08e1SBrandon Kim     uint8_t* entryHeaderPtr = reinterpret_cast<uint8_t*>(&entryHeader);
239f0e4adc9SBrandon Kim     uint8_t checksum =
240f0e4adc9SBrandon Kim         std::accumulate(entryHeaderPtr,
241f0e4adc9SBrandon Kim                         entryHeaderPtr + sizeof(struct QueueEntryHeader), 0,
242f0e4adc9SBrandon Kim                         std::bit_xor<void>()) ^
243f0e4adc9SBrandon Kim         std::accumulate(entry.begin(), entry.end(), 0, std::bit_xor<void>());
244f0e4adc9SBrandon Kim 
24540ce08e1SBrandon Kim     if (checksum != 0)
24640ce08e1SBrandon Kim     {
24740ce08e1SBrandon Kim         throw std::runtime_error(fmt::format(
24840ce08e1SBrandon Kim             "[readEntry] Checksum was '{}', expected '0'", checksum));
24940ce08e1SBrandon Kim     }
25040ce08e1SBrandon Kim 
25140ce08e1SBrandon Kim     return {entryHeader, entry};
25240ce08e1SBrandon Kim }
25340ce08e1SBrandon Kim 
2544662b1bdSBrandon Kim std::vector<EntryPair> BufferImpl::readErrorLogs()
2554662b1bdSBrandon Kim {
2564662b1bdSBrandon Kim     // Reading the buffer header will update the cachedBufferHeader
2574662b1bdSBrandon Kim     readBufferHeader();
2584662b1bdSBrandon Kim 
2593def3c8eSBrandon Kim     const size_t maxOffset = getMaxOffset();
2604662b1bdSBrandon Kim     size_t currentBiosWritePtr =
2614662b1bdSBrandon Kim         boost::endian::little_to_native(cachedBufferHeader.biosWritePtr);
2623def3c8eSBrandon Kim     if (currentBiosWritePtr > maxOffset)
2634662b1bdSBrandon Kim     {
2644662b1bdSBrandon Kim         throw std::runtime_error(fmt::format(
2654662b1bdSBrandon Kim             "[readErrorLogs] currentBiosWritePtr was '{}' which was bigger "
2663def3c8eSBrandon Kim             "than maxOffset '{}'",
2673def3c8eSBrandon Kim             currentBiosWritePtr, maxOffset));
2684662b1bdSBrandon Kim     }
2694662b1bdSBrandon Kim     size_t currentReadPtr =
2704662b1bdSBrandon Kim         boost::endian::little_to_native(cachedBufferHeader.bmcReadPtr);
2713def3c8eSBrandon Kim     if (currentReadPtr > maxOffset)
2724662b1bdSBrandon Kim     {
2734662b1bdSBrandon Kim         throw std::runtime_error(fmt::format(
2744662b1bdSBrandon Kim             "[readErrorLogs] currentReadPtr was '{}' which was bigger "
2753def3c8eSBrandon Kim             "than maxOffset '{}'",
2763def3c8eSBrandon Kim             currentReadPtr, maxOffset));
2774662b1bdSBrandon Kim     }
2784662b1bdSBrandon Kim 
2794662b1bdSBrandon Kim     size_t bytesToRead;
2804662b1bdSBrandon Kim     if (currentBiosWritePtr == currentReadPtr)
2814662b1bdSBrandon Kim     {
2824662b1bdSBrandon Kim         // No new payload was detected, return an empty vector gracefully
2834662b1bdSBrandon Kim         return {};
2844662b1bdSBrandon Kim     }
2854662b1bdSBrandon Kim 
2864662b1bdSBrandon Kim     if (currentBiosWritePtr > currentReadPtr)
2874662b1bdSBrandon Kim     {
2884662b1bdSBrandon Kim         // Simply subtract in this case
2894662b1bdSBrandon Kim         bytesToRead = currentBiosWritePtr - currentReadPtr;
2904662b1bdSBrandon Kim     }
2914662b1bdSBrandon Kim     else
2924662b1bdSBrandon Kim     {
2933def3c8eSBrandon Kim         // Calculate the bytes to the "end" (maxOffset - ReadPtr) +
2944662b1bdSBrandon Kim         // bytes to read from the "beginning" (0 +  WritePtr)
2953def3c8eSBrandon Kim         bytesToRead = (maxOffset - currentReadPtr) + currentBiosWritePtr;
2964662b1bdSBrandon Kim     }
2974662b1bdSBrandon Kim 
2984662b1bdSBrandon Kim     size_t byteRead = 0;
2994662b1bdSBrandon Kim     std::vector<EntryPair> entryPairs;
3004662b1bdSBrandon Kim     while (byteRead < bytesToRead)
3014662b1bdSBrandon Kim     {
302613ba537SBrandon Kim         EntryPair entryPair = readEntry();
3034662b1bdSBrandon Kim         byteRead += sizeof(struct QueueEntryHeader) + entryPair.second.size();
3044662b1bdSBrandon Kim         entryPairs.push_back(entryPair);
3054662b1bdSBrandon Kim 
3064662b1bdSBrandon Kim         // Note: readEntry() will update cachedBufferHeader.bmcReadPtr
3074662b1bdSBrandon Kim         currentReadPtr =
3084662b1bdSBrandon Kim             boost::endian::little_to_native(cachedBufferHeader.bmcReadPtr);
3094662b1bdSBrandon Kim     }
3104662b1bdSBrandon Kim     if (currentBiosWritePtr != currentReadPtr)
3114662b1bdSBrandon Kim     {
3124662b1bdSBrandon Kim         throw std::runtime_error(fmt::format(
3134662b1bdSBrandon Kim             "[readErrorLogs] biosWritePtr '{}' and bmcReaddPtr '{}' "
3144662b1bdSBrandon Kim             "are not identical after reading through all the logs",
3154662b1bdSBrandon Kim             currentBiosWritePtr, currentReadPtr));
3164662b1bdSBrandon Kim     }
3174662b1bdSBrandon Kim     return entryPairs;
3184662b1bdSBrandon Kim }
3194662b1bdSBrandon Kim 
3203def3c8eSBrandon Kim size_t BufferImpl::getMaxOffset()
3213def3c8eSBrandon Kim {
3223def3c8eSBrandon Kim     size_t queueSize =
3233def3c8eSBrandon Kim         boost::endian::little_to_native(cachedBufferHeader.queueSize);
3243def3c8eSBrandon Kim     size_t ueRegionSize =
3253def3c8eSBrandon Kim         boost::endian::little_to_native(cachedBufferHeader.ueRegionSize);
3263def3c8eSBrandon Kim 
327*82ab8320SBrandon Kim     if (queueSize != QUEUE_REGION_SIZE)
328*82ab8320SBrandon Kim     {
329*82ab8320SBrandon Kim         throw std::runtime_error(fmt::format(
330*82ab8320SBrandon Kim             "[{}] runtime queueSize '{}' did not match compile-time queueSize "
331*82ab8320SBrandon Kim             "'{}'. This indicates that the buffer was corrupted",
332*82ab8320SBrandon Kim             __FUNCTION__, queueSize, QUEUE_REGION_SIZE));
333*82ab8320SBrandon Kim     }
334*82ab8320SBrandon Kim     if (ueRegionSize != UE_REGION_SIZE)
335*82ab8320SBrandon Kim     {
336*82ab8320SBrandon Kim         throw std::runtime_error(fmt::format(
337*82ab8320SBrandon Kim             "[{}] runtime ueRegionSize '{}' did not match compile-time "
338*82ab8320SBrandon Kim             "ueRegionSize '{}'. This indicates that the buffer was corrupted",
339*82ab8320SBrandon Kim             __FUNCTION__, ueRegionSize, UE_REGION_SIZE));
340*82ab8320SBrandon Kim     }
341*82ab8320SBrandon Kim 
3423def3c8eSBrandon Kim     return queueSize - ueRegionSize - sizeof(struct CircularBufferHeader);
3433def3c8eSBrandon Kim }
3443def3c8eSBrandon Kim 
345*82ab8320SBrandon Kim size_t BufferImpl::getQueueOffset()
346*82ab8320SBrandon Kim {
347*82ab8320SBrandon Kim     size_t ueRegionSize =
348*82ab8320SBrandon Kim         boost::endian::little_to_native(cachedBufferHeader.ueRegionSize);
349*82ab8320SBrandon Kim 
350*82ab8320SBrandon Kim     if (ueRegionSize != UE_REGION_SIZE)
351*82ab8320SBrandon Kim     {
352*82ab8320SBrandon Kim         throw std::runtime_error(fmt::format(
353*82ab8320SBrandon Kim             "[{}] runtime ueRegionSize '{}' did not match compile-time "
354*82ab8320SBrandon Kim             "ueRegionSize '{}'. This indicates that the buffer was corrupted",
355*82ab8320SBrandon Kim             __FUNCTION__, ueRegionSize, UE_REGION_SIZE));
356*82ab8320SBrandon Kim     }
357*82ab8320SBrandon Kim     return sizeof(struct CircularBufferHeader) + ueRegionSize;
358*82ab8320SBrandon Kim }
359*82ab8320SBrandon Kim 
360fcbc3db1SBrandon Kim } // namespace bios_bmc_smm_error_logger
361