blob: 0254cac5cfc1af01db84cda8686245eb8043f87c [file] [log] [blame]
Brandon Kim82ab8322023-08-17 00:50:18 +00001#include "config.h"
2
Brandon Kimfcbc3db2022-06-06 21:26:18 -07003#include "buffer.hpp"
4
5#include "pci_handler.hpp"
6
Brandon Kim17ee1a92022-06-07 21:04:08 -07007#include <boost/endian/arithmetic.hpp>
8#include <boost/endian/conversion.hpp>
Brandon Kimaec99862025-06-08 22:41:40 +00009#include <stdplus/print.hpp>
Brandon Kim17ee1a92022-06-07 21:04:08 -070010
11#include <algorithm>
Brandon Kimfcbc3db2022-06-06 21:26:18 -070012#include <array>
Brandon Kimcf0b9752022-06-15 10:32:21 -070013#include <cstddef>
Brandon Kimfcbc3db2022-06-06 21:26:18 -070014#include <cstdint>
Patrick Williams5de90612024-02-13 21:31:53 -060015#include <format>
Brandon Kimfcbc3db2022-06-06 21:26:18 -070016#include <memory>
Brandon Kim40ce08e2022-06-15 16:58:44 -070017#include <numeric>
Brandon Kimfcbc3db2022-06-06 21:26:18 -070018#include <span>
19#include <vector>
20
21namespace bios_bmc_smm_error_logger
22{
23
24BufferImpl::BufferImpl(std::unique_ptr<DataInterface> dataInterface) :
Patrick Williams1a643562024-08-16 15:22:05 -040025 dataInterface(std::move(dataInterface)) {};
Brandon Kimfcbc3db2022-06-06 21:26:18 -070026
27void BufferImpl::initialize(uint32_t bmcInterfaceVersion, uint16_t queueSize,
28 uint16_t ueRegionSize,
29 const std::array<uint32_t, 4>& magicNumber)
30{
Brandon Kimfcbc3db2022-06-06 21:26:18 -070031 const size_t memoryRegionSize = dataInterface->getMemoryRegionSize();
Brandon Kim3def3c82022-09-13 05:29:20 +000032 if (queueSize > memoryRegionSize)
Brandon Kim26660e92022-06-15 16:58:44 -070033 {
Patrick Williams5de90612024-02-13 21:31:53 -060034 throw std::runtime_error(std::format(
Brandon Kim3def3c82022-09-13 05:29:20 +000035 "[initialize] Proposed queue size '{}' is bigger than the "
Brandon Kim26660e92022-06-15 16:58:44 -070036 "BMC's allocated MMIO region of '{}'",
Brandon Kim3def3c82022-09-13 05:29:20 +000037 queueSize, memoryRegionSize));
Brandon Kim26660e92022-06-15 16:58:44 -070038 }
39
40 // Initialize the whole buffer with 0x00
Brandon Kim3def3c82022-09-13 05:29:20 +000041 const std::vector<uint8_t> emptyVector(queueSize, 0);
Brandon Kimfcbc3db2022-06-06 21:26:18 -070042 size_t byteWritten = dataInterface->write(0, emptyVector);
Brandon Kim3def3c82022-09-13 05:29:20 +000043 if (byteWritten != queueSize)
Brandon Kimfcbc3db2022-06-06 21:26:18 -070044 {
45 throw std::runtime_error(
Patrick Williams5de90612024-02-13 21:31:53 -060046 std::format("[initialize] Only erased '{}'", byteWritten));
Brandon Kimfcbc3db2022-06-06 21:26:18 -070047 }
48
49 // Create an initial buffer header and write to it
50 struct CircularBufferHeader initializationHeader = {};
Brandon Kim17ee1a92022-06-07 21:04:08 -070051 initializationHeader.bmcInterfaceVersion =
52 boost::endian::native_to_little(bmcInterfaceVersion);
53 initializationHeader.queueSize = boost::endian::native_to_little(queueSize);
54 initializationHeader.ueRegionSize =
55 boost::endian::native_to_little(ueRegionSize);
56 std::transform(magicNumber.begin(), magicNumber.end(),
57 initializationHeader.magicNumber.begin(),
58 [](uint32_t number) -> little_uint32_t {
Patrick Williams1a643562024-08-16 15:22:05 -040059 return boost::endian::native_to_little(number);
60 });
Brandon Kimfcbc3db2022-06-06 21:26:18 -070061
62 uint8_t* initializationHeaderPtr =
63 reinterpret_cast<uint8_t*>(&initializationHeader);
64 size_t initializationHeaderSize = sizeof(initializationHeader);
65 byteWritten = dataInterface->write(
Patrick Williams1a643562024-08-16 15:22:05 -040066 0, std::span<const uint8_t>(
67 initializationHeaderPtr,
68 initializationHeaderPtr + initializationHeaderSize));
Brandon Kimfcbc3db2022-06-06 21:26:18 -070069 if (byteWritten != initializationHeaderSize)
70 {
Patrick Williams5de90612024-02-13 21:31:53 -060071 throw std::runtime_error(std::format(
Brandon Kim26660e92022-06-15 16:58:44 -070072 "[initialize] Only wrote '{}' bytes of the header", byteWritten));
Brandon Kimfcbc3db2022-06-06 21:26:18 -070073 }
Brandon Kim60cab572022-06-15 14:20:05 -070074 cachedBufferHeader = initializationHeader;
Brandon Kimfcbc3db2022-06-06 21:26:18 -070075}
76
Brandon Kim17ee1a92022-06-07 21:04:08 -070077void BufferImpl::readBufferHeader()
78{
79 size_t headerSize = sizeof(struct CircularBufferHeader);
Patrick Williams1a643562024-08-16 15:22:05 -040080 std::vector<uint8_t> bytesRead =
81 dataInterface->read(/*offset=*/0, headerSize);
Brandon Kim17ee1a92022-06-07 21:04:08 -070082
83 if (bytesRead.size() != headerSize)
84 {
85 throw std::runtime_error(
Patrick Williams5de90612024-02-13 21:31:53 -060086 std::format("Buffer header read only read '{}', expected '{}'",
Brandon Kim17ee1a92022-06-07 21:04:08 -070087 bytesRead.size(), headerSize));
88 }
89
90 cachedBufferHeader =
Brandon Kim60cab572022-06-15 14:20:05 -070091 *reinterpret_cast<struct CircularBufferHeader*>(bytesRead.data());
Brandon Kim17ee1a92022-06-07 21:04:08 -070092};
93
94struct CircularBufferHeader BufferImpl::getCachedBufferHeader() const
95{
96 return cachedBufferHeader;
97}
98
Brandon Kimcf0b9752022-06-15 10:32:21 -070099void BufferImpl::updateReadPtr(const uint32_t newReadPtr)
100{
Patrick Williams1a643562024-08-16 15:22:05 -0400101 constexpr uint8_t bmcReadPtrOffset =
102 offsetof(struct CircularBufferHeader, bmcReadPtr);
Brandon Kimcf0b9752022-06-15 10:32:21 -0700103
Brandon Kim271d2312022-09-02 16:34:55 +0000104 little_uint24_t truncatedReadPtr =
105 boost::endian::native_to_little(newReadPtr & 0xffffff);
Brandon Kimcf0b9752022-06-15 10:32:21 -0700106 uint8_t* truncatedReadPtrPtr =
107 reinterpret_cast<uint8_t*>(&truncatedReadPtr);
108
109 size_t writtenSize = dataInterface->write(
110 bmcReadPtrOffset, std::span<const uint8_t>{
111 truncatedReadPtrPtr,
Brandon Kim271d2312022-09-02 16:34:55 +0000112 truncatedReadPtrPtr + sizeof(truncatedReadPtr)});
113 if (writtenSize != sizeof(truncatedReadPtr))
Brandon Kimcf0b9752022-06-15 10:32:21 -0700114 {
Patrick Williams5de90612024-02-13 21:31:53 -0600115 throw std::runtime_error(std::format(
Brandon Kimcf0b9752022-06-15 10:32:21 -0700116 "[updateReadPtr] Wrote '{}' bytes, instead of expected '{}'",
Brandon Kim271d2312022-09-02 16:34:55 +0000117 writtenSize, sizeof(truncatedReadPtr)));
Brandon Kimcf0b9752022-06-15 10:32:21 -0700118 }
119 cachedBufferHeader.bmcReadPtr = truncatedReadPtr;
120}
121
Brandon Kimc49284b2022-06-17 09:55:26 -0700122void BufferImpl::updateBmcFlags(const uint32_t newBmcFlag)
123{
Patrick Williams1a643562024-08-16 15:22:05 -0400124 constexpr uint8_t bmcFlagsPtrOffset =
125 offsetof(struct CircularBufferHeader, bmcFlags);
Brandon Kimc49284b2022-06-17 09:55:26 -0700126
127 little_uint32_t littleNewBmcFlag =
128 boost::endian::native_to_little(newBmcFlag);
129 uint8_t* littleNewBmcFlagPtr =
130 reinterpret_cast<uint8_t*>(&littleNewBmcFlag);
131
132 size_t writtenSize = dataInterface->write(
133 bmcFlagsPtrOffset, std::span<const uint8_t>{
134 littleNewBmcFlagPtr,
135 littleNewBmcFlagPtr + sizeof(little_uint32_t)});
136 if (writtenSize != sizeof(little_uint32_t))
137 {
Patrick Williams5de90612024-02-13 21:31:53 -0600138 throw std::runtime_error(std::format(
Brandon Kimc49284b2022-06-17 09:55:26 -0700139 "[updateBmcFlags] Wrote '{}' bytes, instead of expected '{}'",
140 writtenSize, sizeof(little_uint32_t)));
141 }
142 cachedBufferHeader.bmcFlags = littleNewBmcFlag;
143}
144
Brandon Kim35d43352022-06-16 11:13:36 -0700145std::vector<uint8_t> BufferImpl::wraparoundRead(const uint32_t relativeOffset,
146 const uint32_t length)
Brandon Kim9836cfa2022-06-15 11:21:11 -0700147{
Brandon Kim3def3c82022-09-13 05:29:20 +0000148 const size_t maxOffset = getMaxOffset();
Brandon Kim9836cfa2022-06-15 11:21:11 -0700149
Brandon Kim3def3c82022-09-13 05:29:20 +0000150 if (relativeOffset > maxOffset)
Brandon Kim35d43352022-06-16 11:13:36 -0700151 {
152 throw std::runtime_error(
Patrick Williams5de90612024-02-13 21:31:53 -0600153 std::format("[wraparoundRead] relativeOffset '{}' was bigger "
Brandon Kim3def3c82022-09-13 05:29:20 +0000154 "than maxOffset '{}'",
155 relativeOffset, maxOffset));
Brandon Kim35d43352022-06-16 11:13:36 -0700156 }
Brandon Kim3def3c82022-09-13 05:29:20 +0000157 if (length > maxOffset)
Brandon Kim9836cfa2022-06-15 11:21:11 -0700158 {
Patrick Williams5de90612024-02-13 21:31:53 -0600159 throw std::runtime_error(std::format(
Brandon Kim3def3c82022-09-13 05:29:20 +0000160 "[wraparoundRead] length '{}' was bigger than maxOffset '{}'",
161 length, maxOffset));
Brandon Kim9836cfa2022-06-15 11:21:11 -0700162 }
163
Brandon Kim35d43352022-06-16 11:13:36 -0700164 // Do a calculation to see if the read will wraparound
165 const size_t queueOffset = getQueueOffset();
Brandon Kim3def3c82022-09-13 05:29:20 +0000166 const size_t writableSpace = maxOffset - relativeOffset;
Brandon Kim35d43352022-06-16 11:13:36 -0700167 size_t numWraparoundBytesToRead = 0;
Brandon Kim3def3c82022-09-13 05:29:20 +0000168 if (length > writableSpace)
Brandon Kim35d43352022-06-16 11:13:36 -0700169 {
170 // This means we will wrap, count the bytes that are left to read
Brandon Kim3def3c82022-09-13 05:29:20 +0000171 numWraparoundBytesToRead = length - writableSpace;
Brandon Kim35d43352022-06-16 11:13:36 -0700172 }
173 const size_t numBytesToReadTillQueueEnd = length - numWraparoundBytesToRead;
174
175 std::vector<uint8_t> bytesRead = dataInterface->read(
176 queueOffset + relativeOffset, numBytesToReadTillQueueEnd);
177 if (bytesRead.size() != numBytesToReadTillQueueEnd)
178 {
179 throw std::runtime_error(
Patrick Williams5de90612024-02-13 21:31:53 -0600180 std::format("[wraparoundRead] Read '{}' which was not "
Brandon Kim35d43352022-06-16 11:13:36 -0700181 "the requested length of '{}'",
182 bytesRead.size(), numBytesToReadTillQueueEnd));
183 }
184 size_t updatedReadPtr = relativeOffset + numBytesToReadTillQueueEnd;
Brandon Kim3def3c82022-09-13 05:29:20 +0000185 if (updatedReadPtr == maxOffset)
Brandon Kim4662b1b2022-06-16 21:38:02 -0700186 {
187 // If we read all the way up to the end of the queue, we need to
188 // manually wrap the updateReadPtr around to 0
189 updatedReadPtr = 0;
190 }
Brandon Kim9836cfa2022-06-15 11:21:11 -0700191
192 // If there are any more bytes to be read beyond the buffer, wrap around and
193 // read from the beginning of the buffer (offset by the queueOffset)
Brandon Kim35d43352022-06-16 11:13:36 -0700194 if (numWraparoundBytesToRead > 0)
Brandon Kim9836cfa2022-06-15 11:21:11 -0700195 {
196 std::vector<uint8_t> wrappedBytesRead =
Brandon Kim35d43352022-06-16 11:13:36 -0700197 dataInterface->read(queueOffset, numWraparoundBytesToRead);
198 if (numWraparoundBytesToRead != wrappedBytesRead.size())
Brandon Kim9836cfa2022-06-15 11:21:11 -0700199 {
Patrick Williams5de90612024-02-13 21:31:53 -0600200 throw std::runtime_error(std::format(
Brandon Kim35d43352022-06-16 11:13:36 -0700201 "[wraparoundRead] Buffer wrapped around but read '{}' which "
202 "was not the requested lenght of '{}'",
203 wrappedBytesRead.size(), numWraparoundBytesToRead));
Brandon Kim9836cfa2022-06-15 11:21:11 -0700204 }
205 bytesRead.insert(bytesRead.end(), wrappedBytesRead.begin(),
206 wrappedBytesRead.end());
Brandon Kim35d43352022-06-16 11:13:36 -0700207 updatedReadPtr = numWraparoundBytesToRead;
Brandon Kim9836cfa2022-06-15 11:21:11 -0700208 }
Brandon Kim35d43352022-06-16 11:13:36 -0700209 updateReadPtr(updatedReadPtr);
Brandon Kim9836cfa2022-06-15 11:21:11 -0700210
211 return bytesRead;
212}
213
Brandon Kim613ba532022-09-12 20:55:21 +0000214struct QueueEntryHeader BufferImpl::readEntryHeader()
Brandon Kim7bac2d62022-06-07 21:37:51 -0700215{
216 size_t headerSize = sizeof(struct QueueEntryHeader);
217 // wraparonudRead will throw if it did not read all the bytes, let it
218 // propagate up the stack
Brandon Kim613ba532022-09-12 20:55:21 +0000219 std::vector<uint8_t> bytesRead = wraparoundRead(
220 boost::endian::little_to_native(cachedBufferHeader.bmcReadPtr),
221 headerSize);
Brandon Kim7bac2d62022-06-07 21:37:51 -0700222
223 return *reinterpret_cast<struct QueueEntryHeader*>(bytesRead.data());
224}
225
Brandon Kimaec99862025-06-08 22:41:40 +0000226std::vector<uint8_t> BufferImpl::readUeLogFromReservedRegion()
227{
228 // Ensure cachedBufferHeader is up-to-date
229 readBufferHeader();
230
231 uint16_t currentUeRegionSize =
232 boost::endian::little_to_native(cachedBufferHeader.ueRegionSize);
233 if (currentUeRegionSize == 0)
234 {
235 stdplus::print(stderr,
236 "[readUeLogFromReservedRegion] UE Region size is 0\n");
237 return {};
238 }
239
240 uint32_t biosSideFlags =
241 boost::endian::little_to_native(cachedBufferHeader.biosFlags);
242 uint32_t bmcSideFlags =
243 boost::endian::little_to_native(cachedBufferHeader.bmcFlags);
244
245 // (BIOS_switch ^ BMC_switch) & BIT0 == BIT0 -> unread log
246 // This means if the ueSwitch bit differs, there's an unread log.
247 if (!((biosSideFlags ^ bmcSideFlags) &
248 static_cast<uint32_t>(BufferFlags::ueSwitch)))
249 {
250 return {};
251 }
252 // UE log should be present and unread by BMC, read from end of header
253 // (0x30) to the size of the UE region specified in the header.
254 size_t ueRegionOffset = sizeof(struct CircularBufferHeader);
255 std::vector<uint8_t> ueLogData =
256 dataInterface->read(ueRegionOffset, currentUeRegionSize);
257
258 if (ueLogData.size() == currentUeRegionSize)
259 {
260 return ueLogData;
261 }
262 stdplus::print(stderr,
263 "[readUeLogFromReservedRegion] Failed to read "
264 "full UE log. Expected {}, got {}\n",
265 currentUeRegionSize, ueLogData.size());
266 // Throwing an exception allows main loop to handle re-init.
267 throw std::runtime_error(
268 std::format("Failed to read full UE log. Expected {}, got {}",
269 currentUeRegionSize, ueLogData.size()));
270}
271
Brandon Kim613ba532022-09-12 20:55:21 +0000272EntryPair BufferImpl::readEntry()
Brandon Kim40ce08e2022-06-15 16:58:44 -0700273{
Brandon Kim613ba532022-09-12 20:55:21 +0000274 struct QueueEntryHeader entryHeader = readEntryHeader();
Brandon Kim35d43352022-06-16 11:13:36 -0700275 size_t entrySize = boost::endian::little_to_native(entryHeader.entrySize);
Brandon Kim40ce08e2022-06-15 16:58:44 -0700276
277 // wraparonudRead may throw if entrySize was bigger than the buffer or if it
Brandon Kim26660e92022-06-15 16:58:44 -0700278 // was not able to read all the bytes, let it propagate up the stack
Brandon Kim35d43352022-06-16 11:13:36 -0700279 std::vector<uint8_t> entry = wraparoundRead(
Brandon Kim613ba532022-09-12 20:55:21 +0000280 boost::endian::little_to_native(cachedBufferHeader.bmcReadPtr),
281 entrySize);
Brandon Kim40ce08e2022-06-15 16:58:44 -0700282
283 // Calculate the checksum
284 uint8_t* entryHeaderPtr = reinterpret_cast<uint8_t*>(&entryHeader);
Brandon Kimf0e4adc2022-06-16 23:14:25 -0700285 uint8_t checksum =
286 std::accumulate(entryHeaderPtr,
287 entryHeaderPtr + sizeof(struct QueueEntryHeader), 0,
288 std::bit_xor<void>()) ^
289 std::accumulate(entry.begin(), entry.end(), 0, std::bit_xor<void>());
290
Brandon Kim40ce08e2022-06-15 16:58:44 -0700291 if (checksum != 0)
292 {
Patrick Williams5de90612024-02-13 21:31:53 -0600293 throw std::runtime_error(std::format(
Brandon Kim40ce08e2022-06-15 16:58:44 -0700294 "[readEntry] Checksum was '{}', expected '0'", checksum));
295 }
296
297 return {entryHeader, entry};
298}
299
Brandon Kim4662b1b2022-06-16 21:38:02 -0700300std::vector<EntryPair> BufferImpl::readErrorLogs()
301{
302 // Reading the buffer header will update the cachedBufferHeader
303 readBufferHeader();
304
Brandon Kim3def3c82022-09-13 05:29:20 +0000305 const size_t maxOffset = getMaxOffset();
Brandon Kim4662b1b2022-06-16 21:38:02 -0700306 size_t currentBiosWritePtr =
307 boost::endian::little_to_native(cachedBufferHeader.biosWritePtr);
Brandon Kim3def3c82022-09-13 05:29:20 +0000308 if (currentBiosWritePtr > maxOffset)
Brandon Kim4662b1b2022-06-16 21:38:02 -0700309 {
Patrick Williams5de90612024-02-13 21:31:53 -0600310 throw std::runtime_error(std::format(
Brandon Kim4662b1b2022-06-16 21:38:02 -0700311 "[readErrorLogs] currentBiosWritePtr was '{}' which was bigger "
Brandon Kim3def3c82022-09-13 05:29:20 +0000312 "than maxOffset '{}'",
313 currentBiosWritePtr, maxOffset));
Brandon Kim4662b1b2022-06-16 21:38:02 -0700314 }
315 size_t currentReadPtr =
316 boost::endian::little_to_native(cachedBufferHeader.bmcReadPtr);
Brandon Kim3def3c82022-09-13 05:29:20 +0000317 if (currentReadPtr > maxOffset)
Brandon Kim4662b1b2022-06-16 21:38:02 -0700318 {
Patrick Williams5de90612024-02-13 21:31:53 -0600319 throw std::runtime_error(std::format(
Brandon Kim4662b1b2022-06-16 21:38:02 -0700320 "[readErrorLogs] currentReadPtr was '{}' which was bigger "
Brandon Kim3def3c82022-09-13 05:29:20 +0000321 "than maxOffset '{}'",
322 currentReadPtr, maxOffset));
Brandon Kim4662b1b2022-06-16 21:38:02 -0700323 }
324
325 size_t bytesToRead;
326 if (currentBiosWritePtr == currentReadPtr)
327 {
328 // No new payload was detected, return an empty vector gracefully
329 return {};
330 }
331
332 if (currentBiosWritePtr > currentReadPtr)
333 {
334 // Simply subtract in this case
335 bytesToRead = currentBiosWritePtr - currentReadPtr;
336 }
337 else
338 {
Brandon Kim3def3c82022-09-13 05:29:20 +0000339 // Calculate the bytes to the "end" (maxOffset - ReadPtr) +
Brandon Kim4662b1b2022-06-16 21:38:02 -0700340 // bytes to read from the "beginning" (0 + WritePtr)
Brandon Kim3def3c82022-09-13 05:29:20 +0000341 bytesToRead = (maxOffset - currentReadPtr) + currentBiosWritePtr;
Brandon Kim4662b1b2022-06-16 21:38:02 -0700342 }
343
344 size_t byteRead = 0;
345 std::vector<EntryPair> entryPairs;
346 while (byteRead < bytesToRead)
347 {
Brandon Kim613ba532022-09-12 20:55:21 +0000348 EntryPair entryPair = readEntry();
Brandon Kim4662b1b2022-06-16 21:38:02 -0700349 byteRead += sizeof(struct QueueEntryHeader) + entryPair.second.size();
350 entryPairs.push_back(entryPair);
351
352 // Note: readEntry() will update cachedBufferHeader.bmcReadPtr
353 currentReadPtr =
354 boost::endian::little_to_native(cachedBufferHeader.bmcReadPtr);
355 }
356 if (currentBiosWritePtr != currentReadPtr)
357 {
Patrick Williams5de90612024-02-13 21:31:53 -0600358 throw std::runtime_error(std::format(
Brandon Kim4662b1b2022-06-16 21:38:02 -0700359 "[readErrorLogs] biosWritePtr '{}' and bmcReaddPtr '{}' "
360 "are not identical after reading through all the logs",
361 currentBiosWritePtr, currentReadPtr));
362 }
363 return entryPairs;
364}
365
Brandon Kim3def3c82022-09-13 05:29:20 +0000366size_t BufferImpl::getMaxOffset()
367{
368 size_t queueSize =
369 boost::endian::little_to_native(cachedBufferHeader.queueSize);
370 size_t ueRegionSize =
371 boost::endian::little_to_native(cachedBufferHeader.ueRegionSize);
372
Brandon Kim82ab8322023-08-17 00:50:18 +0000373 if (queueSize != QUEUE_REGION_SIZE)
374 {
Patrick Williams5de90612024-02-13 21:31:53 -0600375 throw std::runtime_error(std::format(
Brandon Kim82ab8322023-08-17 00:50:18 +0000376 "[{}] runtime queueSize '{}' did not match compile-time queueSize "
377 "'{}'. This indicates that the buffer was corrupted",
378 __FUNCTION__, queueSize, QUEUE_REGION_SIZE));
379 }
380 if (ueRegionSize != UE_REGION_SIZE)
381 {
Patrick Williams5de90612024-02-13 21:31:53 -0600382 throw std::runtime_error(std::format(
Brandon Kim82ab8322023-08-17 00:50:18 +0000383 "[{}] runtime ueRegionSize '{}' did not match compile-time "
384 "ueRegionSize '{}'. This indicates that the buffer was corrupted",
385 __FUNCTION__, ueRegionSize, UE_REGION_SIZE));
386 }
387
Brandon Kim3def3c82022-09-13 05:29:20 +0000388 return queueSize - ueRegionSize - sizeof(struct CircularBufferHeader);
389}
390
Brandon Kim82ab8322023-08-17 00:50:18 +0000391size_t BufferImpl::getQueueOffset()
392{
393 size_t ueRegionSize =
394 boost::endian::little_to_native(cachedBufferHeader.ueRegionSize);
395
396 if (ueRegionSize != UE_REGION_SIZE)
397 {
Patrick Williams5de90612024-02-13 21:31:53 -0600398 throw std::runtime_error(std::format(
Brandon Kim82ab8322023-08-17 00:50:18 +0000399 "[{}] runtime ueRegionSize '{}' did not match compile-time "
400 "ueRegionSize '{}'. This indicates that the buffer was corrupted",
401 __FUNCTION__, ueRegionSize, UE_REGION_SIZE));
402 }
403 return sizeof(struct CircularBufferHeader) + ueRegionSize;
404}
405
Brandon Kimfcbc3db2022-06-06 21:26:18 -0700406} // namespace bios_bmc_smm_error_logger