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