1 #include "buffer.hpp" 2 3 #include "pci_handler.hpp" 4 5 #include <fmt/format.h> 6 7 #include <boost/endian/arithmetic.hpp> 8 #include <boost/endian/conversion.hpp> 9 10 #include <algorithm> 11 #include <array> 12 #include <cstdint> 13 #include <memory> 14 #include <span> 15 #include <vector> 16 17 namespace bios_bmc_smm_error_logger 18 { 19 20 BufferImpl::BufferImpl(std::unique_ptr<DataInterface> dataInterface) : 21 dataInterface(std::move(dataInterface)){}; 22 23 void 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 = {}; 39 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 }); 49 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 65 void 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 82 struct CircularBufferHeader BufferImpl::getCachedBufferHeader() const 83 { 84 return cachedBufferHeader; 85 } 86 87 } // namespace bios_bmc_smm_error_logger 88