blob: 54d197e287a3d569d450a3528387b115deb16e75 [file] [log] [blame]
Brandon Kimfcbc3db2022-06-06 21:26:18 -07001#pragma once
2
3#include "pci_handler.hpp"
4
Brandon Kim17ee1a92022-06-07 21:04:08 -07005#include <boost/endian/arithmetic.hpp>
6
Brandon Kimfcbc3db2022-06-06 21:26:18 -07007#include <array>
8#include <cstdint>
9#include <memory>
Brandon Kim17ee1a92022-06-07 21:04:08 -070010#include <tuple>
Brandon Kimfcbc3db2022-06-06 21:26:18 -070011
12namespace bios_bmc_smm_error_logger
13{
14
Brandon Kim17ee1a92022-06-07 21:04:08 -070015/* Adding endianness */
16using boost::endian::little_uint16_t;
17using boost::endian::little_uint32_t;
18using boost::endian::little_uint64_t;
19
Brandon Kim40ce08e2022-06-15 16:58:44 -070020// EntryPair.first = QueueEntryHeader
21// EntryPair.second = Error entry in vector of bytes
22using EntryPair = std::pair<struct QueueEntryHeader, std::vector<uint8_t>>;
23
Brandon Kimc49284b2022-06-17 09:55:26 -070024enum class BmcFlags : uint32_t
25{
26 ueSwitch = 1,
27 overflow = 1 << 1,
28 ready = 1 << 2,
29};
30
Brandon Kimfcbc3db2022-06-06 21:26:18 -070031struct CircularBufferHeader
32{
Brandon Kim17ee1a92022-06-07 21:04:08 -070033 little_uint32_t bmcInterfaceVersion; // Offset 0x0
34 little_uint32_t biosInterfaceVersion; // Offset 0x4
35 std::array<little_uint32_t, 4> magicNumber; // Offset 0x8
36 little_uint16_t queueSize; // Offset 0x18
37 little_uint16_t ueRegionSize; // Offset 0x1a
38 little_uint32_t bmcFlags; // Offset 0x1c
39 little_uint16_t bmcReadPtr; // Offset 0x20
40 std::array<uint8_t, 6> reserved1; // Offset 0x22
41 little_uint32_t biosFlags; // Offset 0x28
42 little_uint16_t biosWritePtr; // Offset 0x2c
43 std::array<uint8_t, 2> reserved2; // Offset 0x2e
44 // UE reserved region: Offset 0x30
45 // Error log queue: Offset 0x30 + UE reserved region
Brandon Kimfcbc3db2022-06-06 21:26:18 -070046
47 bool operator==(const CircularBufferHeader& other) const
48 {
Brandon Kim17ee1a92022-06-07 21:04:08 -070049 /* Skip comparing reserved1 and reserved2 */
50 return std::tie(this->bmcInterfaceVersion, this->biosInterfaceVersion,
51 this->magicNumber, this->queueSize, this->ueRegionSize,
52 this->bmcFlags, this->bmcReadPtr, this->biosFlags,
53 this->biosWritePtr) ==
54 std::tie(other.bmcInterfaceVersion, other.biosInterfaceVersion,
55 other.magicNumber, other.queueSize, other.ueRegionSize,
56 other.bmcFlags, other.bmcReadPtr, other.biosFlags,
57 other.biosWritePtr);
Brandon Kimfcbc3db2022-06-06 21:26:18 -070058 }
Brandon Kim17ee1a92022-06-07 21:04:08 -070059};
60static_assert(sizeof(CircularBufferHeader) == 0x30,
61 "Size of CircularBufferHeader struct is incorrect.");
Brandon Kimfcbc3db2022-06-06 21:26:18 -070062
Brandon Kim7bac2d62022-06-07 21:37:51 -070063struct QueueEntryHeader
64{
65 little_uint16_t sequenceId; // Offset 0x0
66 little_uint16_t entrySize; // Offset 0x2
67 uint8_t checksum; // Offset 0x4
68 uint8_t rdeCommandType; // Offset 0x5
69 // RDE Command Offset 0x6
70 bool operator==(const QueueEntryHeader& other) const
71 {
72 return std::tie(this->sequenceId, this->entrySize, this->checksum,
73 this->rdeCommandType) ==
74 std::tie(other.sequenceId, other.entrySize, other.checksum,
75 other.rdeCommandType);
76 }
77};
78static_assert(sizeof(QueueEntryHeader) == 0x6,
79 "Size of QueueEntryHeader struct is incorrect.");
80
Brandon Kimfcbc3db2022-06-06 21:26:18 -070081/**
82 * An interface class for the buffer helper APIs
83 */
84class BufferInterface
85{
86 public:
87 virtual ~BufferInterface() = default;
88
89 /**
90 * Zero out the buffer first before populating the header
91 *
92 * @param[in] bmcInterfaceVersion - Used to initialize the header
93 * @param[in] queueSize - Used to initialize the header
94 * @param[in] ueRegionSize - Used to initialize the header
95 * @param[in] magicNumber - Used to initialize the header
96 * @return true if successful
97 */
98 virtual void initialize(uint32_t bmcInterfaceVersion, uint16_t queueSize,
99 uint16_t ueRegionSize,
100 const std::array<uint32_t, 4>& magicNumber) = 0;
Brandon Kim17ee1a92022-06-07 21:04:08 -0700101
102 /**
103 * Read the buffer header from shared buffer
104 */
105 virtual void readBufferHeader() = 0;
106
107 /**
108 * Getter API for the cached buffer header
109 * @return cached CircularBufferHeader
110 */
111 virtual struct CircularBufferHeader getCachedBufferHeader() const = 0;
Brandon Kimcf0b9752022-06-15 10:32:21 -0700112
113 /**
114 * Write to the bufferHeader and update the read pointer
Brandon Kim35d43352022-06-16 11:13:36 -0700115 * @param[in] newReadPtr - read pointer to update to
Brandon Kimcf0b9752022-06-15 10:32:21 -0700116 */
117 virtual void updateReadPtr(const uint32_t newReadPtr) = 0;
Brandon Kim9836cfa2022-06-15 11:21:11 -0700118
119 /**
Brandon Kimc49284b2022-06-17 09:55:26 -0700120 * Write to the bufferHeader and update the BMC flags
121 * @param[in] newBmcFlags - new flag to update to
122 */
123 virtual void updateBmcFlags(const uint32_t newBmcFlags) = 0;
124
125 /**
Brandon Kim9836cfa2022-06-15 11:21:11 -0700126 * Wrapper for the dataInterface->read, performs wraparound read
127 *
Brandon Kim35d43352022-06-16 11:13:36 -0700128 * @param[in] relativeOffset - offset relative the "Error Log
129 * Queue region" = (sizeof(CircularBufferHeader) + UE reserved region)
Brandon Kim9836cfa2022-06-15 11:21:11 -0700130 * @param[in] length - bytes to read
Brandon Kim9836cfa2022-06-15 11:21:11 -0700131 * @return the bytes read
132 */
Brandon Kim35d43352022-06-16 11:13:36 -0700133 virtual std::vector<uint8_t> wraparoundRead(const uint32_t relativeOffset,
134 const uint32_t length) = 0;
Brandon Kim7bac2d62022-06-07 21:37:51 -0700135 /**
136 * Read the entry header from shared buffer
137 *
Brandon Kim35d43352022-06-16 11:13:36 -0700138 * @param[in] relativeOffset - offset relative the "Error Log
139 * Queue region" = (sizeof(CircularBufferHeader) + UE reserved region)
Brandon Kim7bac2d62022-06-07 21:37:51 -0700140 * @return the entry header
141 */
Brandon Kim35d43352022-06-16 11:13:36 -0700142 virtual struct QueueEntryHeader readEntryHeader(size_t relativeOffset) = 0;
Brandon Kim40ce08e2022-06-15 16:58:44 -0700143
144 /**
145 * Read the queue entry from the error log queue
146 *
Brandon Kim35d43352022-06-16 11:13:36 -0700147 * @param[in] relativeOffset - offset relative the "Error Log
148 * Queue region" = (sizeof(CircularBufferHeader) + UE reserved region)
149 * * @return entry header and entry pair read from buffer
Brandon Kim40ce08e2022-06-15 16:58:44 -0700150 */
Brandon Kim35d43352022-06-16 11:13:36 -0700151 virtual EntryPair readEntry(size_t relativeOffset) = 0;
Brandon Kim4662b1b2022-06-16 21:38:02 -0700152
153 /**
154 * Read the buffer - this API should be used instead of individual functions
155 * above
156 *
157 * @return vector of EntryPair which consists of entry header and entry
158 */
159 virtual std::vector<EntryPair> readErrorLogs() = 0;
Brandon Kimfcbc3db2022-06-06 21:26:18 -0700160};
161
162/**
163 * Buffer implementation class
164 */
165class BufferImpl : public BufferInterface
166{
167 public:
168 /** @brief Constructor for BufferImpl
169 * @param[in] dataInterface - DataInterface for this object
170 */
171 explicit BufferImpl(std::unique_ptr<DataInterface> dataInterface);
172 void initialize(uint32_t bmcInterfaceVersion, uint16_t queueSize,
173 uint16_t ueRegionSize,
174 const std::array<uint32_t, 4>& magicNumber) override;
Brandon Kim17ee1a92022-06-07 21:04:08 -0700175 void readBufferHeader() override;
176 struct CircularBufferHeader getCachedBufferHeader() const override;
Brandon Kimcf0b9752022-06-15 10:32:21 -0700177 void updateReadPtr(const uint32_t newReadPtr) override;
Brandon Kimc49284b2022-06-17 09:55:26 -0700178 void updateBmcFlags(const uint32_t newBmcFlag) override;
Brandon Kim35d43352022-06-16 11:13:36 -0700179 std::vector<uint8_t> wraparoundRead(const uint32_t relativeOffset,
180 const uint32_t length) override;
181 struct QueueEntryHeader readEntryHeader(size_t relativeOffset) override;
182 EntryPair readEntry(size_t relativeOffset) override;
Brandon Kim4662b1b2022-06-16 21:38:02 -0700183 std::vector<EntryPair> readErrorLogs() override;
Brandon Kimfcbc3db2022-06-06 21:26:18 -0700184
185 private:
Brandon Kim9836cfa2022-06-15 11:21:11 -0700186 /** @brief The Error log queue starts after the UE region, which is where
187 * the read and write pointers are offset from relatively
188 * @return relative offset for read and write pointers
189 */
190 size_t getQueueOffset();
Brandon Kimf0e4adc2022-06-16 23:14:25 -0700191 /** @brief Calculate the checksum by XOR each bytes in the span
192 * @param[in] entry - Span to calculate the checksum on
193 * @return calculated checksum
194 */
195 uint8_t calculateChecksum(std::span<uint8_t> entry);
Brandon Kim9836cfa2022-06-15 11:21:11 -0700196
Brandon Kimfcbc3db2022-06-06 21:26:18 -0700197 std::unique_ptr<DataInterface> dataInterface;
Brandon Kim17ee1a92022-06-07 21:04:08 -0700198 struct CircularBufferHeader cachedBufferHeader = {};
Brandon Kimfcbc3db2022-06-06 21:26:18 -0700199};
200
201} // namespace bios_bmc_smm_error_logger