1*1a3dc60dSBrandon Kim #include "config.h" 2*1a3dc60dSBrandon Kim 3*1a3dc60dSBrandon Kim #include "buffer.hpp" 4*1a3dc60dSBrandon Kim #include "pci_handler.hpp" 5*1a3dc60dSBrandon Kim #include "rde/external_storer_file.hpp" 6*1a3dc60dSBrandon Kim #include "rde/external_storer_interface.hpp" 7*1a3dc60dSBrandon Kim #include "rde/rde_handler.hpp" 8*1a3dc60dSBrandon Kim 9*1a3dc60dSBrandon Kim #include <fmt/format.h> 10*1a3dc60dSBrandon Kim 11554fad0bSBrandon Kim #include <boost/asio.hpp> 12*1a3dc60dSBrandon Kim #include <boost/endian/conversion.hpp> 13*1a3dc60dSBrandon Kim #include <stdplus/fd/create.hpp> 14*1a3dc60dSBrandon Kim #include <stdplus/fd/impl.hpp> 15*1a3dc60dSBrandon Kim #include <stdplus/fd/managed.hpp> 16554fad0bSBrandon Kim 17554fad0bSBrandon Kim #include <chrono> 18*1a3dc60dSBrandon Kim #include <filesystem> 19*1a3dc60dSBrandon Kim #include <fstream> 20554fad0bSBrandon Kim #include <functional> 21*1a3dc60dSBrandon Kim #include <memory> 22554fad0bSBrandon Kim 23554fad0bSBrandon Kim namespace 24554fad0bSBrandon Kim { 25*1a3dc60dSBrandon Kim constexpr std::chrono::milliseconds readIntervalinMs(READ_INTERVAL_MS); 26*1a3dc60dSBrandon Kim constexpr std::size_t memoryRegionSize = MEMORY_REGION_SIZE; 27*1a3dc60dSBrandon Kim constexpr std::size_t memoryRegionOffset = MEMORY_REGION_OFFSET; 28*1a3dc60dSBrandon Kim constexpr uint32_t bmcInterfaceVersion = BMC_INTERFACE_VERSION; 29*1a3dc60dSBrandon Kim constexpr uint16_t queueSize = QUEUE_REGION_SIZE; 30*1a3dc60dSBrandon Kim constexpr uint16_t ueRegionSize = UE_REGION_SIZE; 31*1a3dc60dSBrandon Kim static constexpr std::array<uint32_t, 4> magicNumber = { 32*1a3dc60dSBrandon Kim MAGIC_NUMBER_BYTE1, MAGIC_NUMBER_BYTE2, MAGIC_NUMBER_BYTE3, 33*1a3dc60dSBrandon Kim MAGIC_NUMBER_BYTE4}; 34554fad0bSBrandon Kim } // namespace 35554fad0bSBrandon Kim 36*1a3dc60dSBrandon Kim using namespace bios_bmc_smm_error_logger; 37*1a3dc60dSBrandon Kim 38*1a3dc60dSBrandon Kim void readLoop(boost::asio::steady_timer* t, 39*1a3dc60dSBrandon Kim const std::shared_ptr<BufferInterface>& bufferInterface, 40*1a3dc60dSBrandon Kim const std::shared_ptr<rde::RdeCommandHandler>& rdeCommandHandler, 41*1a3dc60dSBrandon Kim const boost::system::error_code& error) 42554fad0bSBrandon Kim { 43*1a3dc60dSBrandon Kim if (error) 44*1a3dc60dSBrandon Kim { 45*1a3dc60dSBrandon Kim fmt::print(stderr, "Async wait failed {}\n", error.message()); 46*1a3dc60dSBrandon Kim return; 47*1a3dc60dSBrandon Kim } 48*1a3dc60dSBrandon Kim std::vector<EntryPair> entryPairs = bufferInterface->readErrorLogs(); 49*1a3dc60dSBrandon Kim for (const auto& [entryHeader, entry] : entryPairs) 50*1a3dc60dSBrandon Kim { 51*1a3dc60dSBrandon Kim fmt::print(stderr, "Read an entry of '{}' bytes\n", entry.size()); 52*1a3dc60dSBrandon Kim 53*1a3dc60dSBrandon Kim rde::RdeDecodeStatus rdeDecodeStatus = 54*1a3dc60dSBrandon Kim rdeCommandHandler->decodeRdeCommand( 55*1a3dc60dSBrandon Kim entry, 56*1a3dc60dSBrandon Kim static_cast<rde::RdeCommandType>(entryHeader.rdeCommandType)); 57*1a3dc60dSBrandon Kim if (rdeDecodeStatus == rde::RdeDecodeStatus::RdeStopFlagReceived) 58*1a3dc60dSBrandon Kim { 59*1a3dc60dSBrandon Kim auto bufferHeader = bufferInterface->getCachedBufferHeader(); 60*1a3dc60dSBrandon Kim auto newbmcFlags = 61*1a3dc60dSBrandon Kim boost::endian::little_to_native(bufferHeader.bmcFlags) | 62*1a3dc60dSBrandon Kim static_cast<uint32_t>(BmcFlags::ready); 63*1a3dc60dSBrandon Kim bufferInterface->updateBmcFlags(newbmcFlags); 64*1a3dc60dSBrandon Kim } 65*1a3dc60dSBrandon Kim } 66*1a3dc60dSBrandon Kim 67*1a3dc60dSBrandon Kim t->expires_from_now(readIntervalinMs); 68*1a3dc60dSBrandon Kim t->async_wait( 69*1a3dc60dSBrandon Kim std::bind_front(readLoop, t, bufferInterface, rdeCommandHandler)); 70554fad0bSBrandon Kim } 71554fad0bSBrandon Kim 72554fad0bSBrandon Kim int main() 73554fad0bSBrandon Kim { 74554fad0bSBrandon Kim boost::asio::io_context io; 75*1a3dc60dSBrandon Kim boost::asio::steady_timer t(io, readIntervalinMs); 76554fad0bSBrandon Kim 77*1a3dc60dSBrandon Kim // bufferHandler initialization 78*1a3dc60dSBrandon Kim std::unique_ptr<stdplus::ManagedFd> managedFd = 79*1a3dc60dSBrandon Kim std::make_unique<stdplus::ManagedFd>(stdplus::fd::open( 80*1a3dc60dSBrandon Kim "/dev/mem", 81*1a3dc60dSBrandon Kim stdplus::fd::OpenFlags(stdplus::fd::OpenAccess::ReadWrite) 82*1a3dc60dSBrandon Kim .set(stdplus::fd::OpenFlag::Sync))); 83*1a3dc60dSBrandon Kim std::unique_ptr<DataInterface> pciDataHandler = 84*1a3dc60dSBrandon Kim std::make_unique<PciDataHandler>(memoryRegionOffset, memoryRegionSize, 85*1a3dc60dSBrandon Kim std::move(managedFd)); 86*1a3dc60dSBrandon Kim std::shared_ptr<BufferInterface> bufferHandler = 87*1a3dc60dSBrandon Kim std::make_shared<BufferImpl>(std::move(pciDataHandler)); 88554fad0bSBrandon Kim 89*1a3dc60dSBrandon Kim // rdeCommandHandler initialization 90*1a3dc60dSBrandon Kim std::unique_ptr<rde::FileHandlerInterface> fileIface = 91*1a3dc60dSBrandon Kim std::make_unique<rde::ExternalStorerFileWriter>(); 92*1a3dc60dSBrandon Kim std::unique_ptr<rde::ExternalStorerInterface> exFileIface = 93*1a3dc60dSBrandon Kim std::make_unique<rde::ExternalStorerFileInterface>( 94*1a3dc60dSBrandon Kim "/run/bmcweb", std::move(fileIface)); 95*1a3dc60dSBrandon Kim std::shared_ptr<rde::RdeCommandHandler> rdeCommandHandler = 96*1a3dc60dSBrandon Kim std::make_unique<rde::RdeCommandHandler>(std::move(exFileIface)); 97*1a3dc60dSBrandon Kim 98*1a3dc60dSBrandon Kim bufferHandler->initialize(bmcInterfaceVersion, queueSize, ueRegionSize, 99*1a3dc60dSBrandon Kim magicNumber); 100*1a3dc60dSBrandon Kim 101*1a3dc60dSBrandon Kim t.async_wait(std::bind_front(readLoop, &t, std::move(bufferHandler), 102*1a3dc60dSBrandon Kim std::move(rdeCommandHandler))); 103554fad0bSBrandon Kim io.run(); 104554fad0bSBrandon Kim 105554fad0bSBrandon Kim return 0; 106554fad0bSBrandon Kim } 107