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