blob: a2b8ee488210ae00cad8d321342eaba9282a2ae6 [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>
12#include <cstdint>
13#include <memory>
14#include <span>
15#include <vector>
16
17namespace bios_bmc_smm_error_logger
18{
19
20BufferImpl::BufferImpl(std::unique_ptr<DataInterface> dataInterface) :
21 dataInterface(std::move(dataInterface)){};
22
23void BufferImpl::initialize(uint32_t bmcInterfaceVersion, uint16_t queueSize,
24 uint16_t ueRegionSize,
25 const std::array<uint32_t, 4>& magicNumber)
26{
27 // Initialize the whole buffer with 0x00
28 const size_t memoryRegionSize = dataInterface->getMemoryRegionSize();
29 const std::vector<uint8_t> emptyVector(memoryRegionSize, 0);
30 size_t byteWritten = dataInterface->write(0, emptyVector);
31 if (byteWritten != memoryRegionSize)
32 {
33 throw std::runtime_error(
34 fmt::format("Buffer initialization only erased '{}'", byteWritten));
35 }
36
37 // Create an initial buffer header and write to it
38 struct CircularBufferHeader initializationHeader = {};
Brandon Kim17ee1a92022-06-07 21:04:08 -070039 initializationHeader.bmcInterfaceVersion =
40 boost::endian::native_to_little(bmcInterfaceVersion);
41 initializationHeader.queueSize = boost::endian::native_to_little(queueSize);
42 initializationHeader.ueRegionSize =
43 boost::endian::native_to_little(ueRegionSize);
44 std::transform(magicNumber.begin(), magicNumber.end(),
45 initializationHeader.magicNumber.begin(),
46 [](uint32_t number) -> little_uint32_t {
47 return boost::endian::native_to_little(number);
48 });
Brandon Kimfcbc3db2022-06-06 21:26:18 -070049
50 uint8_t* initializationHeaderPtr =
51 reinterpret_cast<uint8_t*>(&initializationHeader);
52 size_t initializationHeaderSize = sizeof(initializationHeader);
53 byteWritten = dataInterface->write(
54 0, std::span<const uint8_t>(initializationHeaderPtr,
55 initializationHeaderPtr +
56 initializationHeaderSize));
57 if (byteWritten != initializationHeaderSize)
58 {
59 throw std::runtime_error(fmt::format(
60 "Buffer initialization buffer header write only wrote '{}'",
61 byteWritten));
62 }
63}
64
Brandon Kim17ee1a92022-06-07 21:04:08 -070065void BufferImpl::readBufferHeader()
66{
67 size_t headerSize = sizeof(struct CircularBufferHeader);
68 std::vector<uint8_t> bytesRead =
69 dataInterface->read(/* offset */ 0, headerSize);
70
71 if (bytesRead.size() != headerSize)
72 {
73 throw std::runtime_error(
74 fmt::format("Buffer header read only read '{}', expected '{}'",
75 bytesRead.size(), headerSize));
76 }
77
78 cachedBufferHeader =
79 *reinterpret_cast<CircularBufferHeader*>(bytesRead.data());
80};
81
82struct CircularBufferHeader BufferImpl::getCachedBufferHeader() const
83{
84 return cachedBufferHeader;
85}
86
Brandon Kimfcbc3db2022-06-06 21:26:18 -070087} // namespace bios_bmc_smm_error_logger