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