main: Integrating the buffer and rde handler

This will loop upon start up of the system and decode any incoming
payloads.

Tested:
Tested on a real hardware with a real BIOS

Change-Id: Iddbdafbf9a6e94d7a3556335ea59b935e1931c83
Signed-off-by: Brandon Kim <brandonkim@google.com>
Signed-off-by: Willy Tu <wltu@google.com>
diff --git a/src/main.cpp b/src/main.cpp
index 9db1969..0b520a9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,30 +1,105 @@
+#include "config.h"
+
+#include "buffer.hpp"
+#include "pci_handler.hpp"
+#include "rde/external_storer_file.hpp"
+#include "rde/external_storer_interface.hpp"
+#include "rde/rde_handler.hpp"
+
+#include <fmt/format.h>
+
 #include <boost/asio.hpp>
+#include <boost/endian/conversion.hpp>
+#include <stdplus/fd/create.hpp>
+#include <stdplus/fd/impl.hpp>
+#include <stdplus/fd/managed.hpp>
 
 #include <chrono>
+#include <filesystem>
+#include <fstream>
 #include <functional>
+#include <memory>
 
 namespace
 {
-// Set the read loop interval to be 1 second for now
-// TODO: Make this a configuration option
-static constexpr std::chrono::seconds readIntervalSec(1);
+constexpr std::chrono::milliseconds readIntervalinMs(READ_INTERVAL_MS);
+constexpr std::size_t memoryRegionSize = MEMORY_REGION_SIZE;
+constexpr std::size_t memoryRegionOffset = MEMORY_REGION_OFFSET;
+constexpr uint32_t bmcInterfaceVersion = BMC_INTERFACE_VERSION;
+constexpr uint16_t queueSize = QUEUE_REGION_SIZE;
+constexpr uint16_t ueRegionSize = UE_REGION_SIZE;
+static constexpr std::array<uint32_t, 4> magicNumber = {
+    MAGIC_NUMBER_BYTE1, MAGIC_NUMBER_BYTE2, MAGIC_NUMBER_BYTE3,
+    MAGIC_NUMBER_BYTE4};
 } // namespace
 
-// boost::async_wait requires `const boost::system::error_code&` parameter
-void readLoop(boost::asio::steady_timer* t, const boost::system::error_code&)
+using namespace bios_bmc_smm_error_logger;
+
+void 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)
 {
-    /* This will run every readIntervalSec second for now */
-    t->expires_from_now(readIntervalSec);
-    t->async_wait(std::bind_front(readLoop, t));
+    if (error)
+    {
+        fmt::print(stderr, "Async wait failed {}\n", error.message());
+        return;
+    }
+    std::vector<EntryPair> entryPairs = bufferInterface->readErrorLogs();
+    for (const auto& [entryHeader, entry] : entryPairs)
+    {
+        fmt::print(stderr, "Read an entry of '{}' bytes\n", entry.size());
+
+        rde::RdeDecodeStatus rdeDecodeStatus =
+            rdeCommandHandler->decodeRdeCommand(
+                entry,
+                static_cast<rde::RdeCommandType>(entryHeader.rdeCommandType));
+        if (rdeDecodeStatus == rde::RdeDecodeStatus::RdeStopFlagReceived)
+        {
+            auto bufferHeader = bufferInterface->getCachedBufferHeader();
+            auto newbmcFlags =
+                boost::endian::little_to_native(bufferHeader.bmcFlags) |
+                static_cast<uint32_t>(BmcFlags::ready);
+            bufferInterface->updateBmcFlags(newbmcFlags);
+        }
+    }
+
+    t->expires_from_now(readIntervalinMs);
+    t->async_wait(
+        std::bind_front(readLoop, t, bufferInterface, rdeCommandHandler));
 }
 
 int main()
 {
     boost::asio::io_context io;
-    boost::asio::steady_timer t(io, readIntervalSec);
+    boost::asio::steady_timer t(io, readIntervalinMs);
 
-    t.async_wait(std::bind_front(readLoop, &t));
+    // bufferHandler initialization
+    std::unique_ptr<stdplus::ManagedFd> managedFd =
+        std::make_unique<stdplus::ManagedFd>(stdplus::fd::open(
+            "/dev/mem",
+            stdplus::fd::OpenFlags(stdplus::fd::OpenAccess::ReadWrite)
+                .set(stdplus::fd::OpenFlag::Sync)));
+    std::unique_ptr<DataInterface> pciDataHandler =
+        std::make_unique<PciDataHandler>(memoryRegionOffset, memoryRegionSize,
+                                         std::move(managedFd));
+    std::shared_ptr<BufferInterface> bufferHandler =
+        std::make_shared<BufferImpl>(std::move(pciDataHandler));
 
+    // rdeCommandHandler initialization
+    std::unique_ptr<rde::FileHandlerInterface> fileIface =
+        std::make_unique<rde::ExternalStorerFileWriter>();
+    std::unique_ptr<rde::ExternalStorerInterface> exFileIface =
+        std::make_unique<rde::ExternalStorerFileInterface>(
+            "/run/bmcweb", std::move(fileIface));
+    std::shared_ptr<rde::RdeCommandHandler> rdeCommandHandler =
+        std::make_unique<rde::RdeCommandHandler>(std::move(exFileIface));
+
+    bufferHandler->initialize(bmcInterfaceVersion, queueSize, ueRegionSize,
+                              magicNumber);
+
+    t.async_wait(std::bind_front(readLoop, &t, std::move(bufferHandler),
+                                 std::move(rdeCommandHandler)));
     io.run();
 
     return 0;