blob: c07bba6dc15dbbe187df8eea8dd979eb6c3f01b3 [file] [log] [blame]
Brandon Kimfcbc3db2022-06-06 21:26:18 -07001#include "buffer.hpp"
2
3#include "pci_handler.hpp"
4
5#include <fmt/format.h>
6
Brandon Kim17ee1a92022-06-07 21:04:08 -07007#include <boost/endian/arithmetic.hpp>
8#include <boost/endian/conversion.hpp>
9
10#include <algorithm>
Brandon Kimfcbc3db2022-06-06 21:26:18 -070011#include <array>
Brandon Kimcf0b9752022-06-15 10:32:21 -070012#include <cstddef>
Brandon Kimfcbc3db2022-06-06 21:26:18 -070013#include <cstdint>
14#include <memory>
15#include <span>
16#include <vector>
17
18namespace bios_bmc_smm_error_logger
19{
20
21BufferImpl::BufferImpl(std::unique_ptr<DataInterface> dataInterface) :
22 dataInterface(std::move(dataInterface)){};
23
24void BufferImpl::initialize(uint32_t bmcInterfaceVersion, uint16_t queueSize,
25 uint16_t ueRegionSize,
26 const std::array<uint32_t, 4>& magicNumber)
27{
28 // Initialize the whole buffer with 0x00
29 const size_t memoryRegionSize = dataInterface->getMemoryRegionSize();
30 const std::vector<uint8_t> emptyVector(memoryRegionSize, 0);
31 size_t byteWritten = dataInterface->write(0, emptyVector);
32 if (byteWritten != memoryRegionSize)
33 {
34 throw std::runtime_error(
35 fmt::format("Buffer initialization only erased '{}'", byteWritten));
36 }
37
38 // Create an initial buffer header and write to it
39 struct CircularBufferHeader initializationHeader = {};
Brandon Kim17ee1a92022-06-07 21:04:08 -070040 initializationHeader.bmcInterfaceVersion =
41 boost::endian::native_to_little(bmcInterfaceVersion);
42 initializationHeader.queueSize = boost::endian::native_to_little(queueSize);
43 initializationHeader.ueRegionSize =
44 boost::endian::native_to_little(ueRegionSize);
45 std::transform(magicNumber.begin(), magicNumber.end(),
46 initializationHeader.magicNumber.begin(),
47 [](uint32_t number) -> little_uint32_t {
48 return boost::endian::native_to_little(number);
49 });
Brandon Kimfcbc3db2022-06-06 21:26:18 -070050
51 uint8_t* initializationHeaderPtr =
52 reinterpret_cast<uint8_t*>(&initializationHeader);
53 size_t initializationHeaderSize = sizeof(initializationHeader);
54 byteWritten = dataInterface->write(
55 0, std::span<const uint8_t>(initializationHeaderPtr,
56 initializationHeaderPtr +
57 initializationHeaderSize));
58 if (byteWritten != initializationHeaderSize)
59 {
60 throw std::runtime_error(fmt::format(
61 "Buffer initialization buffer header write only wrote '{}'",
62 byteWritten));
63 }
Brandon Kim60cab572022-06-15 14:20:05 -070064 cachedBufferHeader = initializationHeader;
Brandon Kimfcbc3db2022-06-06 21:26:18 -070065}
66
Brandon Kim17ee1a92022-06-07 21:04:08 -070067void BufferImpl::readBufferHeader()
68{
69 size_t headerSize = sizeof(struct CircularBufferHeader);
70 std::vector<uint8_t> bytesRead =
71 dataInterface->read(/* offset */ 0, headerSize);
72
73 if (bytesRead.size() != headerSize)
74 {
75 throw std::runtime_error(
76 fmt::format("Buffer header read only read '{}', expected '{}'",
77 bytesRead.size(), headerSize));
78 }
79
80 cachedBufferHeader =
Brandon Kim60cab572022-06-15 14:20:05 -070081 *reinterpret_cast<struct CircularBufferHeader*>(bytesRead.data());
Brandon Kim17ee1a92022-06-07 21:04:08 -070082};
83
84struct CircularBufferHeader BufferImpl::getCachedBufferHeader() const
85{
86 return cachedBufferHeader;
87}
88
Brandon Kimcf0b9752022-06-15 10:32:21 -070089void BufferImpl::updateReadPtr(const uint32_t newReadPtr)
90{
91 constexpr uint8_t bmcReadPtrOffset =
92 offsetof(struct CircularBufferHeader, bmcReadPtr);
93
94 little_uint16_t truncatedReadPtr =
95 boost::endian::native_to_little(newReadPtr & 0xffff);
96 uint8_t* truncatedReadPtrPtr =
97 reinterpret_cast<uint8_t*>(&truncatedReadPtr);
98
99 size_t writtenSize = dataInterface->write(
100 bmcReadPtrOffset, std::span<const uint8_t>{
101 truncatedReadPtrPtr,
102 truncatedReadPtrPtr + sizeof(little_uint16_t)});
103 if (writtenSize != sizeof(little_uint16_t))
104 {
105 throw std::runtime_error(fmt::format(
106 "[updateReadPtr] Wrote '{}' bytes, instead of expected '{}'",
107 writtenSize, sizeof(little_uint16_t)));
108 }
109 cachedBufferHeader.bmcReadPtr = truncatedReadPtr;
110}
111
Brandon Kimfcbc3db2022-06-06 21:26:18 -0700112} // namespace bios_bmc_smm_error_logger