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