11a3dc60dSBrandon Kim #include "config.h"
21a3dc60dSBrandon Kim 
31a3dc60dSBrandon Kim #include "buffer.hpp"
41a3dc60dSBrandon Kim #include "pci_handler.hpp"
51a3dc60dSBrandon Kim #include "rde/external_storer_file.hpp"
61a3dc60dSBrandon Kim #include "rde/external_storer_interface.hpp"
71a3dc60dSBrandon Kim #include "rde/rde_handler.hpp"
81a3dc60dSBrandon Kim 
9554fad0bSBrandon Kim #include <boost/asio.hpp>
101a3dc60dSBrandon Kim #include <boost/endian/conversion.hpp>
11a3b64fb6Skasunath #include <sdbusplus/asio/object_server.hpp>
121a3dc60dSBrandon Kim #include <stdplus/fd/create.hpp>
131a3dc60dSBrandon Kim #include <stdplus/fd/impl.hpp>
141a3dc60dSBrandon Kim #include <stdplus/fd/managed.hpp>
15*5de90619SPatrick Williams #include <stdplus/print.hpp>
16554fad0bSBrandon Kim 
17554fad0bSBrandon Kim #include <chrono>
181a3dc60dSBrandon Kim #include <filesystem>
19*5de90619SPatrick Williams #include <format>
201a3dc60dSBrandon Kim #include <fstream>
21554fad0bSBrandon Kim #include <functional>
221a3dc60dSBrandon Kim #include <memory>
23554fad0bSBrandon Kim 
24554fad0bSBrandon Kim namespace
25554fad0bSBrandon Kim {
261a3dc60dSBrandon Kim constexpr std::chrono::milliseconds readIntervalinMs(READ_INTERVAL_MS);
271a3dc60dSBrandon Kim constexpr std::size_t memoryRegionSize = MEMORY_REGION_SIZE;
281a3dc60dSBrandon Kim constexpr std::size_t memoryRegionOffset = MEMORY_REGION_OFFSET;
291a3dc60dSBrandon Kim constexpr uint32_t bmcInterfaceVersion = BMC_INTERFACE_VERSION;
301a3dc60dSBrandon Kim constexpr uint16_t queueSize = QUEUE_REGION_SIZE;
311a3dc60dSBrandon Kim constexpr uint16_t ueRegionSize = UE_REGION_SIZE;
321a3dc60dSBrandon Kim static constexpr std::array<uint32_t, 4> magicNumber = {
331a3dc60dSBrandon Kim     MAGIC_NUMBER_BYTE1, MAGIC_NUMBER_BYTE2, MAGIC_NUMBER_BYTE3,
341a3dc60dSBrandon Kim     MAGIC_NUMBER_BYTE4};
35554fad0bSBrandon Kim } // namespace
36554fad0bSBrandon Kim 
371a3dc60dSBrandon Kim using namespace bios_bmc_smm_error_logger;
381a3dc60dSBrandon Kim 
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)391a3dc60dSBrandon Kim void readLoop(boost::asio::steady_timer* t,
401a3dc60dSBrandon Kim               const std::shared_ptr<BufferInterface>& bufferInterface,
411a3dc60dSBrandon Kim               const std::shared_ptr<rde::RdeCommandHandler>& rdeCommandHandler,
421a3dc60dSBrandon Kim               const boost::system::error_code& error)
43554fad0bSBrandon Kim {
441a3dc60dSBrandon Kim     if (error)
451a3dc60dSBrandon Kim     {
46*5de90619SPatrick Williams         stdplus::print(stderr, "Async wait failed {}\n", error.message());
471a3dc60dSBrandon Kim         return;
481a3dc60dSBrandon Kim     }
491a3dc60dSBrandon Kim     std::vector<EntryPair> entryPairs = bufferInterface->readErrorLogs();
501a3dc60dSBrandon Kim     for (const auto& [entryHeader, entry] : entryPairs)
511a3dc60dSBrandon Kim     {
52*5de90619SPatrick Williams         stdplus::print(stderr, "Read an entry of '{}' bytes\n", entry.size());
531a3dc60dSBrandon Kim 
541a3dc60dSBrandon Kim         rde::RdeDecodeStatus rdeDecodeStatus =
551a3dc60dSBrandon Kim             rdeCommandHandler->decodeRdeCommand(
561a3dc60dSBrandon Kim                 entry,
571a3dc60dSBrandon Kim                 static_cast<rde::RdeCommandType>(entryHeader.rdeCommandType));
581a3dc60dSBrandon Kim         if (rdeDecodeStatus == rde::RdeDecodeStatus::RdeStopFlagReceived)
591a3dc60dSBrandon Kim         {
601a3dc60dSBrandon Kim             auto bufferHeader = bufferInterface->getCachedBufferHeader();
611a3dc60dSBrandon Kim             auto newbmcFlags =
621a3dc60dSBrandon Kim                 boost::endian::little_to_native(bufferHeader.bmcFlags) |
631a3dc60dSBrandon Kim                 static_cast<uint32_t>(BmcFlags::ready);
641a3dc60dSBrandon Kim             bufferInterface->updateBmcFlags(newbmcFlags);
651a3dc60dSBrandon Kim         }
661a3dc60dSBrandon Kim     }
671a3dc60dSBrandon Kim 
681a3dc60dSBrandon Kim     t->expires_from_now(readIntervalinMs);
691a3dc60dSBrandon Kim     t->async_wait(
701a3dc60dSBrandon Kim         std::bind_front(readLoop, t, bufferInterface, rdeCommandHandler));
71554fad0bSBrandon Kim }
72554fad0bSBrandon Kim 
main()73554fad0bSBrandon Kim int main()
74554fad0bSBrandon Kim {
75554fad0bSBrandon Kim     boost::asio::io_context io;
761a3dc60dSBrandon Kim     boost::asio::steady_timer t(io, readIntervalinMs);
77554fad0bSBrandon Kim 
781a3dc60dSBrandon Kim     // bufferHandler initialization
791a3dc60dSBrandon Kim     std::unique_ptr<stdplus::ManagedFd> managedFd =
801a3dc60dSBrandon Kim         std::make_unique<stdplus::ManagedFd>(stdplus::fd::open(
811a3dc60dSBrandon Kim             "/dev/mem",
821a3dc60dSBrandon Kim             stdplus::fd::OpenFlags(stdplus::fd::OpenAccess::ReadWrite)
831a3dc60dSBrandon Kim                 .set(stdplus::fd::OpenFlag::Sync)));
841a3dc60dSBrandon Kim     std::unique_ptr<DataInterface> pciDataHandler =
851a3dc60dSBrandon Kim         std::make_unique<PciDataHandler>(memoryRegionOffset, memoryRegionSize,
861a3dc60dSBrandon Kim                                          std::move(managedFd));
871a3dc60dSBrandon Kim     std::shared_ptr<BufferInterface> bufferHandler =
881a3dc60dSBrandon Kim         std::make_shared<BufferImpl>(std::move(pciDataHandler));
89554fad0bSBrandon Kim 
901a3dc60dSBrandon Kim     // rdeCommandHandler initialization
91a3b64fb6Skasunath     std::shared_ptr<sdbusplus::asio::connection> conn =
92a3b64fb6Skasunath         std::make_shared<sdbusplus::asio::connection>(io);
93a3b64fb6Skasunath     conn->request_name("xyz.openbmc_project.bios_bmc_smm_error_logger");
94bea36e22SPatrick Williams     sdbusplus::bus_t& bus = static_cast<sdbusplus::bus_t&>(*conn);
95a3b64fb6Skasunath 
961a3dc60dSBrandon Kim     std::unique_ptr<rde::FileHandlerInterface> fileIface =
971a3dc60dSBrandon Kim         std::make_unique<rde::ExternalStorerFileWriter>();
981a3dc60dSBrandon Kim     std::unique_ptr<rde::ExternalStorerInterface> exFileIface =
991a3dc60dSBrandon Kim         std::make_unique<rde::ExternalStorerFileInterface>(
100a3b64fb6Skasunath             bus, "/run/bmcweb", std::move(fileIface));
1011a3dc60dSBrandon Kim     std::shared_ptr<rde::RdeCommandHandler> rdeCommandHandler =
1021a3dc60dSBrandon Kim         std::make_unique<rde::RdeCommandHandler>(std::move(exFileIface));
1031a3dc60dSBrandon Kim 
1041a3dc60dSBrandon Kim     bufferHandler->initialize(bmcInterfaceVersion, queueSize, ueRegionSize,
1051a3dc60dSBrandon Kim                               magicNumber);
1061a3dc60dSBrandon Kim 
1071a3dc60dSBrandon Kim     t.async_wait(std::bind_front(readLoop, &t, std::move(bufferHandler),
1081a3dc60dSBrandon Kim                                  std::move(rdeCommandHandler)));
109554fad0bSBrandon Kim     io.run();
110554fad0bSBrandon Kim 
111554fad0bSBrandon Kim     return 0;
112554fad0bSBrandon Kim }
113