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 <boost/asio.hpp>
10 #include <boost/endian/conversion.hpp>
11 #include <sdbusplus/asio/object_server.hpp>
12 #include <stdplus/fd/create.hpp>
13 #include <stdplus/fd/impl.hpp>
14 #include <stdplus/fd/managed.hpp>
15 #include <stdplus/print.hpp>
16 
17 #include <chrono>
18 #include <filesystem>
19 #include <format>
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 
readLoop(boost::asio::steady_timer * t,const std::shared_ptr<BufferInterface> & bufferInterface,const std::shared_ptr<rde::RdeCommandHandler> & rdeCommandHandler,const boost::system::error_code & error)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         stdplus::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         rde::RdeDecodeStatus rdeDecodeStatus =
53             rdeCommandHandler->decodeRdeCommand(
54                 entry,
55                 static_cast<rde::RdeCommandType>(entryHeader.rdeCommandType));
56         if (rdeDecodeStatus == rde::RdeDecodeStatus::RdeStopFlagReceived)
57         {
58             auto bufferHeader = bufferInterface->getCachedBufferHeader();
59             auto newbmcFlags =
60                 boost::endian::little_to_native(bufferHeader.bmcFlags) |
61                 static_cast<uint32_t>(BmcFlags::ready);
62             bufferInterface->updateBmcFlags(newbmcFlags);
63         }
64     }
65 
66     t->expires_from_now(readIntervalinMs);
67     t->async_wait(
68         std::bind_front(readLoop, t, bufferInterface, rdeCommandHandler));
69 }
70 
main()71 int main()
72 {
73     boost::asio::io_context io;
74     boost::asio::steady_timer t(io, readIntervalinMs);
75 
76     // bufferHandler initialization
77     std::unique_ptr<stdplus::ManagedFd> managedFd =
78         std::make_unique<stdplus::ManagedFd>(stdplus::fd::open(
79             "/dev/mem",
80             stdplus::fd::OpenFlags(stdplus::fd::OpenAccess::ReadWrite)
81                 .set(stdplus::fd::OpenFlag::Sync)));
82     std::unique_ptr<DataInterface> pciDataHandler =
83         std::make_unique<PciDataHandler>(memoryRegionOffset, memoryRegionSize,
84                                          std::move(managedFd));
85     std::shared_ptr<BufferInterface> bufferHandler =
86         std::make_shared<BufferImpl>(std::move(pciDataHandler));
87 
88     // rdeCommandHandler initialization
89     std::shared_ptr<sdbusplus::asio::connection> conn =
90         std::make_shared<sdbusplus::asio::connection>(io);
91     conn->request_name("xyz.openbmc_project.bios_bmc_smm_error_logger");
92 
93     std::unique_ptr<rde::FileHandlerInterface> fileIface =
94         std::make_unique<rde::ExternalStorerFileWriter>();
95     std::unique_ptr<rde::ExternalStorerInterface> exFileIface =
96         std::make_unique<rde::ExternalStorerFileInterface>(
97             conn, "/run/bmcweb", std::move(fileIface));
98     std::shared_ptr<rde::RdeCommandHandler> rdeCommandHandler =
99         std::make_unique<rde::RdeCommandHandler>(std::move(exFileIface));
100 
101     bufferHandler->initialize(bmcInterfaceVersion, queueSize, ueRegionSize,
102                               magicNumber);
103 
104     t.async_wait(std::bind_front(readLoop, &t, std::move(bufferHandler),
105                                  std::move(rdeCommandHandler)));
106     io.run();
107 
108     return 0;
109 }
110