blob: 4465185b5e2f6c21c19ec43fcb5a3ecda59f60a2 [file] [log] [blame]
Brandon Kim1a3dc602022-06-17 11:34:33 -07001#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
Brandon Kim554fad02022-05-15 15:41:05 -07009#include <boost/asio.hpp>
Brandon Kim1a3dc602022-06-17 11:34:33 -070010#include <boost/endian/conversion.hpp>
kasunatha3b64fb2022-06-15 18:47:18 -070011#include <sdbusplus/asio/object_server.hpp>
Brandon Kim1a3dc602022-06-17 11:34:33 -070012#include <stdplus/fd/create.hpp>
13#include <stdplus/fd/impl.hpp>
14#include <stdplus/fd/managed.hpp>
Patrick Williams5de90612024-02-13 21:31:53 -060015#include <stdplus/print.hpp>
Brandon Kim554fad02022-05-15 15:41:05 -070016
17#include <chrono>
Brandon Kim1a3dc602022-06-17 11:34:33 -070018#include <filesystem>
Patrick Williams5de90612024-02-13 21:31:53 -060019#include <format>
Brandon Kim1a3dc602022-06-17 11:34:33 -070020#include <fstream>
Brandon Kim554fad02022-05-15 15:41:05 -070021#include <functional>
Brandon Kim1a3dc602022-06-17 11:34:33 -070022#include <memory>
Brandon Kim554fad02022-05-15 15:41:05 -070023
24namespace
25{
Brandon Kim1a3dc602022-06-17 11:34:33 -070026constexpr std::chrono::milliseconds readIntervalinMs(READ_INTERVAL_MS);
27constexpr std::size_t memoryRegionSize = MEMORY_REGION_SIZE;
28constexpr std::size_t memoryRegionOffset = MEMORY_REGION_OFFSET;
29constexpr uint32_t bmcInterfaceVersion = BMC_INTERFACE_VERSION;
30constexpr uint16_t queueSize = QUEUE_REGION_SIZE;
31constexpr uint16_t ueRegionSize = UE_REGION_SIZE;
32static constexpr std::array<uint32_t, 4> magicNumber = {
33 MAGIC_NUMBER_BYTE1, MAGIC_NUMBER_BYTE2, MAGIC_NUMBER_BYTE3,
34 MAGIC_NUMBER_BYTE4};
Brandon Kim554fad02022-05-15 15:41:05 -070035} // namespace
36
Brandon Kim1a3dc602022-06-17 11:34:33 -070037using namespace bios_bmc_smm_error_logger;
38
39void readLoop(boost::asio::steady_timer* t,
40 const std::shared_ptr<BufferInterface>& bufferInterface,
41 const std::shared_ptr<rde::RdeCommandHandler>& rdeCommandHandler,
42 const boost::system::error_code& error)
Brandon Kim554fad02022-05-15 15:41:05 -070043{
Brandon Kim1a3dc602022-06-17 11:34:33 -070044 if (error)
45 {
Patrick Williams5de90612024-02-13 21:31:53 -060046 stdplus::print(stderr, "Async wait failed {}\n", error.message());
Brandon Kim1a3dc602022-06-17 11:34:33 -070047 return;
48 }
Brandon Kimaec99862025-06-08 22:41:40 +000049
50 try
Brandon Kim1a3dc602022-06-17 11:34:33 -070051 {
Brandon Kimaec99862025-06-08 22:41:40 +000052 std::vector<uint8_t> ueLog =
53 bufferInterface->readUeLogFromReservedRegion();
54 if (!ueLog.empty())
Brandon Kim1a3dc602022-06-17 11:34:33 -070055 {
Brandon Kimaec99862025-06-08 22:41:40 +000056 stdplus::print(
57 stdout,
58 "UE log found in reserved region, attempting to process\n");
59
60 // UE log is BEJ encoded data, requiring RdeOperationInitRequest
61 rde::RdeDecodeStatus ueDecodeStatus =
62 rdeCommandHandler->decodeRdeCommand(
63 ueLog, rde::RdeCommandType::RdeOperationInitRequest);
64
65 if (ueDecodeStatus != rde::RdeDecodeStatus::RdeOk &&
66 ueDecodeStatus != rde::RdeDecodeStatus::RdeStopFlagReceived)
67 {
68 throw std::runtime_error(std::format(
69 "Corruption detected processing UE log from reserved region. RDE decode status: {}",
70 static_cast<int>(ueDecodeStatus)));
71 }
72 stdplus::print(stdout, "UE log processed successfully.\n");
73 // Successfully processed. Toggle BMC's view of ueSwitch flag.
Brandon Kim1a3dc602022-06-17 11:34:33 -070074 auto bufferHeader = bufferInterface->getCachedBufferHeader();
Brandon Kimaec99862025-06-08 22:41:40 +000075 uint32_t bmcSideFlags =
76 boost::endian::little_to_native(bufferHeader.bmcFlags);
77 uint32_t newBmcFlags =
78 bmcSideFlags ^ static_cast<uint32_t>(BufferFlags::ueSwitch);
79 bufferInterface->updateBmcFlags(newBmcFlags);
80 }
81
82 std::vector<EntryPair> entryPairs = bufferInterface->readErrorLogs();
83 for (const auto& [entryHeader, entry] : entryPairs)
84 {
85 rde::RdeDecodeStatus rdeDecodeStatus =
86 rdeCommandHandler->decodeRdeCommand(
87 entry, static_cast<rde::RdeCommandType>(
88 entryHeader.rdeCommandType));
89 if (rdeDecodeStatus == rde::RdeDecodeStatus::RdeStopFlagReceived)
90 {
91 auto bufferHeader = bufferInterface->getCachedBufferHeader();
92 auto newbmcFlags =
93 boost::endian::little_to_native(bufferHeader.bmcFlags) |
94 static_cast<uint32_t>(BmcFlags::ready);
95 bufferInterface->updateBmcFlags(newbmcFlags);
96 }
97 }
98 }
99 catch (const std::exception& e)
100 {
101 stdplus::print(
102 stderr,
103 "Error during log processing (std::exception): {}. Attempting to reinitialize buffer.\n",
104 e.what());
105 try
106 {
107 bufferInterface->initialize(bmcInterfaceVersion, queueSize,
108 ueRegionSize, magicNumber);
109 stdplus::print(
110 stdout,
111 "Buffer reinitialized successfully after std::exception.\n");
112 }
113 catch (const std::exception& reinit_e)
114 {
115 stdplus::print(
116 stderr,
117 "CRITICAL: Failed to reinitialize buffer (std::exception): {}. Terminating read loop.\n",
118 reinit_e.what());
119 return;
120 }
121 catch (...)
122 {
123 stdplus::print(
124 stderr,
125 "CRITICAL: Failed to reinitialize buffer (unknown exception). Terminating read loop.\n");
126 return;
127 }
128 }
129 catch (...)
130 {
131 stdplus::print(
132 stderr,
133 "Unknown error during log processing. Attempting to reinitialize buffer.\n");
134 try
135 {
136 bufferInterface->initialize(bmcInterfaceVersion, queueSize,
137 ueRegionSize, magicNumber);
138 stdplus::print(
139 stdout,
140 "Buffer reinitialized successfully after unknown error.\n");
141 }
142 catch (const std::exception& reinit_e)
143 {
144 stdplus::print(
145 stderr,
146 "CRITICAL: Failed to reinitialize buffer (std::exception): {}. Terminating read loop.\n",
147 reinit_e.what());
148 return;
149 }
150 catch (...)
151 {
152 stdplus::print(
153 stderr,
154 "CRITICAL: Failed to reinitialize buffer (unknown exception). Terminating read loop.\n");
155 return;
Brandon Kim1a3dc602022-06-17 11:34:33 -0700156 }
157 }
158
Brandon Kim07d92b12025-06-06 23:23:53 +0000159 t->expires_after(readIntervalinMs);
Brandon Kim1a3dc602022-06-17 11:34:33 -0700160 t->async_wait(
161 std::bind_front(readLoop, t, bufferInterface, rdeCommandHandler));
Brandon Kim554fad02022-05-15 15:41:05 -0700162}
163
164int main()
165{
166 boost::asio::io_context io;
Brandon Kim1a3dc602022-06-17 11:34:33 -0700167 boost::asio::steady_timer t(io, readIntervalinMs);
Brandon Kim554fad02022-05-15 15:41:05 -0700168
Brandon Kim1a3dc602022-06-17 11:34:33 -0700169 // bufferHandler initialization
170 std::unique_ptr<stdplus::ManagedFd> managedFd =
171 std::make_unique<stdplus::ManagedFd>(stdplus::fd::open(
172 "/dev/mem",
173 stdplus::fd::OpenFlags(stdplus::fd::OpenAccess::ReadWrite)
174 .set(stdplus::fd::OpenFlag::Sync)));
175 std::unique_ptr<DataInterface> pciDataHandler =
176 std::make_unique<PciDataHandler>(memoryRegionOffset, memoryRegionSize,
177 std::move(managedFd));
178 std::shared_ptr<BufferInterface> bufferHandler =
179 std::make_shared<BufferImpl>(std::move(pciDataHandler));
Brandon Kim554fad02022-05-15 15:41:05 -0700180
Brandon Kim1a3dc602022-06-17 11:34:33 -0700181 // rdeCommandHandler initialization
kasunatha3b64fb2022-06-15 18:47:18 -0700182 std::shared_ptr<sdbusplus::asio::connection> conn =
183 std::make_shared<sdbusplus::asio::connection>(io);
184 conn->request_name("xyz.openbmc_project.bios_bmc_smm_error_logger");
kasunatha3b64fb2022-06-15 18:47:18 -0700185
Brandon Kim1a3dc602022-06-17 11:34:33 -0700186 std::unique_ptr<rde::FileHandlerInterface> fileIface =
187 std::make_unique<rde::ExternalStorerFileWriter>();
188 std::unique_ptr<rde::ExternalStorerInterface> exFileIface =
189 std::make_unique<rde::ExternalStorerFileInterface>(
kasunath3d0cd552022-08-25 20:22:58 -0700190 conn, "/run/bmcweb", std::move(fileIface));
Brandon Kim1a3dc602022-06-17 11:34:33 -0700191 std::shared_ptr<rde::RdeCommandHandler> rdeCommandHandler =
192 std::make_unique<rde::RdeCommandHandler>(std::move(exFileIface));
193
194 bufferHandler->initialize(bmcInterfaceVersion, queueSize, ueRegionSize,
195 magicNumber);
196
197 t.async_wait(std::bind_front(readLoop, &t, std::move(bufferHandler),
198 std::move(rdeCommandHandler)));
Brandon Kim554fad02022-05-15 15:41:05 -0700199 io.run();
200
201 return 0;
202}