xref: /openbmc/bios-bmc-smm-error-logger/src/buffer.cpp (revision 17ee1a93779feba7794d17fdf5d84267f3ad2056)
1fcbc3db1SBrandon Kim #include "buffer.hpp"
2fcbc3db1SBrandon Kim 
3fcbc3db1SBrandon Kim #include "pci_handler.hpp"
4fcbc3db1SBrandon Kim 
5fcbc3db1SBrandon Kim #include <fmt/format.h>
6fcbc3db1SBrandon Kim 
7*17ee1a93SBrandon Kim #include <boost/endian/arithmetic.hpp>
8*17ee1a93SBrandon Kim #include <boost/endian/conversion.hpp>
9*17ee1a93SBrandon Kim 
10*17ee1a93SBrandon Kim #include <algorithm>
11fcbc3db1SBrandon Kim #include <array>
12fcbc3db1SBrandon Kim #include <cstdint>
13fcbc3db1SBrandon Kim #include <memory>
14fcbc3db1SBrandon Kim #include <span>
15fcbc3db1SBrandon Kim #include <vector>
16fcbc3db1SBrandon Kim 
17fcbc3db1SBrandon Kim namespace bios_bmc_smm_error_logger
18fcbc3db1SBrandon Kim {
19fcbc3db1SBrandon Kim 
20fcbc3db1SBrandon Kim BufferImpl::BufferImpl(std::unique_ptr<DataInterface> dataInterface) :
21fcbc3db1SBrandon Kim     dataInterface(std::move(dataInterface)){};
22fcbc3db1SBrandon Kim 
23fcbc3db1SBrandon Kim void BufferImpl::initialize(uint32_t bmcInterfaceVersion, uint16_t queueSize,
24fcbc3db1SBrandon Kim                             uint16_t ueRegionSize,
25fcbc3db1SBrandon Kim                             const std::array<uint32_t, 4>& magicNumber)
26fcbc3db1SBrandon Kim {
27fcbc3db1SBrandon Kim     // Initialize the whole buffer with 0x00
28fcbc3db1SBrandon Kim     const size_t memoryRegionSize = dataInterface->getMemoryRegionSize();
29fcbc3db1SBrandon Kim     const std::vector<uint8_t> emptyVector(memoryRegionSize, 0);
30fcbc3db1SBrandon Kim     size_t byteWritten = dataInterface->write(0, emptyVector);
31fcbc3db1SBrandon Kim     if (byteWritten != memoryRegionSize)
32fcbc3db1SBrandon Kim     {
33fcbc3db1SBrandon Kim         throw std::runtime_error(
34fcbc3db1SBrandon Kim             fmt::format("Buffer initialization only erased '{}'", byteWritten));
35fcbc3db1SBrandon Kim     }
36fcbc3db1SBrandon Kim 
37fcbc3db1SBrandon Kim     // Create an initial buffer header and write to it
38fcbc3db1SBrandon Kim     struct CircularBufferHeader initializationHeader = {};
39*17ee1a93SBrandon Kim     initializationHeader.bmcInterfaceVersion =
40*17ee1a93SBrandon Kim         boost::endian::native_to_little(bmcInterfaceVersion);
41*17ee1a93SBrandon Kim     initializationHeader.queueSize = boost::endian::native_to_little(queueSize);
42*17ee1a93SBrandon Kim     initializationHeader.ueRegionSize =
43*17ee1a93SBrandon Kim         boost::endian::native_to_little(ueRegionSize);
44*17ee1a93SBrandon Kim     std::transform(magicNumber.begin(), magicNumber.end(),
45*17ee1a93SBrandon Kim                    initializationHeader.magicNumber.begin(),
46*17ee1a93SBrandon Kim                    [](uint32_t number) -> little_uint32_t {
47*17ee1a93SBrandon Kim                        return boost::endian::native_to_little(number);
48*17ee1a93SBrandon Kim                    });
49fcbc3db1SBrandon Kim 
50fcbc3db1SBrandon Kim     uint8_t* initializationHeaderPtr =
51fcbc3db1SBrandon Kim         reinterpret_cast<uint8_t*>(&initializationHeader);
52fcbc3db1SBrandon Kim     size_t initializationHeaderSize = sizeof(initializationHeader);
53fcbc3db1SBrandon Kim     byteWritten = dataInterface->write(
54fcbc3db1SBrandon Kim         0, std::span<const uint8_t>(initializationHeaderPtr,
55fcbc3db1SBrandon Kim                                     initializationHeaderPtr +
56fcbc3db1SBrandon Kim                                         initializationHeaderSize));
57fcbc3db1SBrandon Kim     if (byteWritten != initializationHeaderSize)
58fcbc3db1SBrandon Kim     {
59fcbc3db1SBrandon Kim         throw std::runtime_error(fmt::format(
60fcbc3db1SBrandon Kim             "Buffer initialization buffer header write only wrote '{}'",
61fcbc3db1SBrandon Kim             byteWritten));
62fcbc3db1SBrandon Kim     }
63fcbc3db1SBrandon Kim }
64fcbc3db1SBrandon Kim 
65*17ee1a93SBrandon Kim void BufferImpl::readBufferHeader()
66*17ee1a93SBrandon Kim {
67*17ee1a93SBrandon Kim     size_t headerSize = sizeof(struct CircularBufferHeader);
68*17ee1a93SBrandon Kim     std::vector<uint8_t> bytesRead =
69*17ee1a93SBrandon Kim         dataInterface->read(/* offset */ 0, headerSize);
70*17ee1a93SBrandon Kim 
71*17ee1a93SBrandon Kim     if (bytesRead.size() != headerSize)
72*17ee1a93SBrandon Kim     {
73*17ee1a93SBrandon Kim         throw std::runtime_error(
74*17ee1a93SBrandon Kim             fmt::format("Buffer header read only read '{}', expected '{}'",
75*17ee1a93SBrandon Kim                         bytesRead.size(), headerSize));
76*17ee1a93SBrandon Kim     }
77*17ee1a93SBrandon Kim 
78*17ee1a93SBrandon Kim     cachedBufferHeader =
79*17ee1a93SBrandon Kim         *reinterpret_cast<CircularBufferHeader*>(bytesRead.data());
80*17ee1a93SBrandon Kim };
81*17ee1a93SBrandon Kim 
82*17ee1a93SBrandon Kim struct CircularBufferHeader BufferImpl::getCachedBufferHeader() const
83*17ee1a93SBrandon Kim {
84*17ee1a93SBrandon Kim     return cachedBufferHeader;
85*17ee1a93SBrandon Kim }
86*17ee1a93SBrandon Kim 
87fcbc3db1SBrandon Kim } // namespace bios_bmc_smm_error_logger
88