blob: 524984a8aa6ac18636b62b4b269049358763723e [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 }
Brandon Kim60cab572022-06-15 14:20:05 -070063 cachedBufferHeader = initializationHeader;
Brandon Kimfcbc3db2022-06-06 21:26:18 -070064}
65
Brandon Kim17ee1a92022-06-07 21:04:08 -070066void BufferImpl::readBufferHeader()
67{
68 size_t headerSize = sizeof(struct CircularBufferHeader);
69 std::vector<uint8_t> bytesRead =
70 dataInterface->read(/* offset */ 0, headerSize);
71
72 if (bytesRead.size() != headerSize)
73 {
74 throw std::runtime_error(
75 fmt::format("Buffer header read only read '{}', expected '{}'",
76 bytesRead.size(), headerSize));
77 }
78
79 cachedBufferHeader =
Brandon Kim60cab572022-06-15 14:20:05 -070080 *reinterpret_cast<struct CircularBufferHeader*>(bytesRead.data());
Brandon Kim17ee1a92022-06-07 21:04:08 -070081};
82
83struct CircularBufferHeader BufferImpl::getCachedBufferHeader() const
84{
85 return cachedBufferHeader;
86}
87
Brandon Kimfcbc3db2022-06-06 21:26:18 -070088} // namespace bios_bmc_smm_error_logger