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/meson.build b/meson.build
index 1b989ae..cda8014 100644
--- a/meson.build
+++ b/meson.build
@@ -13,8 +13,28 @@
 bios_bmc_smm_error_logger_inc = include_directories('include')
 rde_inc = include_directories('include')
 
-subdir('src')
+# Setting up config data
+conf_data = configuration_data()
+
+conf_data.set('READ_INTERVAL_MS', get_option('read-interval-ms'))
+
+conf_data.set('MEMORY_REGION_SIZE', get_option('memory-region-size'))
+conf_data.set('MEMORY_REGION_OFFSET', get_option('memory-region-offset'))
+conf_data.set('BMC_INTERFACE_VERSION', get_option('bmc-interface-version'))
+
+conf_data.set('QUEUE_REGION_SIZE', get_option('queue-region-size'))
+conf_data.set('UE_REGION_SIZE', get_option('ue-region-size'))
+conf_data.set('MAGIC_NUMBER_BYTE1', get_option('magic-number-byte1'))
+conf_data.set('MAGIC_NUMBER_BYTE2', get_option('magic-number-byte2'))
+conf_data.set('MAGIC_NUMBER_BYTE3', get_option('magic-number-byte3'))
+conf_data.set('MAGIC_NUMBER_BYTE4', get_option('magic-number-byte4'))
+
+conf_h = configure_file(
+  output: 'config.h',
+  configuration: conf_data)
+
 subdir('src/rde')
+subdir('src')
 if not get_option('tests').disabled()
   subdir('test')
 endif
diff --git a/meson_options.txt b/meson_options.txt
index 0fc2767..ec979e3 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1 +1,19 @@
 option('tests', type: 'feature', description: 'Build tests')
+
+# Tinmer constant
+option('read-interval-ms', type: 'integer', value: 10, description: 'Read loop interval in millisecond (ms)')
+
+# Memory constants
+option('memory-region-size', type: 'integer', value: 16384, description: 'Memory size allcated')
+# Default value 4035215360 is 0xF0848000 below
+option('memory-region-offset', type: 'integer', value: 4035215360, description: 'Where the memory region is located')
+
+# Circular Buffer header constants
+option('bmc-interface-version', type: 'integer', value: 0, description: 'BMC interface version to easily see compatibility')
+option('queue-region-size', type: 'integer', value: 0, description: 'Normal error queue region size')
+option('ue-region-size', type: 'integer', value: 0, description: 'Uncorrectable error region size')
+# Magic Number Array Constants
+option('magic-number-byte1', type: 'integer', value: 1, description: 'Magic Number array[0] for validity, consists of 4 * uint32_t')
+option('magic-number-byte2', type: 'integer', value: 2, description: 'Magic Number array[1] for validity, consists of 4 * uint32_t')
+option('magic-number-byte3', type: 'integer', value: 3, description: 'Magic Number array[2] for validity, consists of 4 * uint32_t')
+option('magic-number-byte4', type: 'integer', value: 4, description: 'Magic Number array[3] for validity, consists of 4 * uint32_t')
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;
diff --git a/src/meson.build b/src/meson.build
index fd0ead4..8e5a8ff 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -35,8 +35,9 @@
 executable(
   'bios-bmc-smm-error-logger',
   'main.cpp',
+  conf_h,
   implicit_include_directories: false,
-  dependencies: bios_bmc_smm_error_logger_dep,
+  dependencies: [bios_bmc_smm_error_logger_dep, rde_dep],
   install: true,
   install_dir: get_option('bindir')
 )
diff --git a/test/buffer_test.cpp b/test/buffer_test.cpp
index 0b3d8e2..712c801 100644
--- a/test/buffer_test.cpp
+++ b/test/buffer_test.cpp
@@ -655,7 +655,7 @@
     EXPECT_NO_THROW(entryPairs = bufferImpl->readErrorLogs());
 
     // Check that we only read one entryPair and that the content is correct
-    EXPECT_EQ(entryPairs.size(), 1);
+    EXPECT_EQ(entryPairs.size(), 1U);
     EXPECT_EQ(entryPairs[0].first, testEntryHeader);
     EXPECT_THAT(entryPairs[0].second, ElementsAreArray(testEntryVector));
 }