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