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