Coverage Report

Created: 2026-04-29 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bios-bmc-smm-error-logger/include/buffer.hpp
Line
Count
Source
1
#pragma once
2
3
#include "pci_handler.hpp"
4
5
#include <boost/endian/arithmetic.hpp>
6
7
#include <array>
8
#include <cstdint>
9
#include <memory>
10
#include <tuple>
11
12
namespace bios_bmc_smm_error_logger
13
{
14
15
/* Adding endianness */
16
using boost::endian::little_uint16_t;
17
using boost::endian::little_uint24_t;
18
using boost::endian::little_uint32_t;
19
using boost::endian::little_uint64_t;
20
21
// EntryPair.first = QueueEntryHeader
22
// EntryPair.second = Error entry in vector of bytes
23
using EntryPair = std::pair<struct QueueEntryHeader, std::vector<uint8_t>>;
24
25
enum class BufferFlags : uint32_t
26
{
27
    ueSwitch = 1 << 0,
28
    overflow = 1 << 1,
29
};
30
31
enum class BmcFlags : uint32_t
32
{
33
    ready = 1 << 2,
34
};
35
36
struct CircularBufferHeader
37
{
38
    little_uint32_t bmcInterfaceVersion;        // Offset 0x0
39
    little_uint32_t biosInterfaceVersion;       // Offset 0x4
40
    std::array<little_uint32_t, 4> magicNumber; // Offset 0x8
41
    little_uint24_t queueSize;                  // Offset 0x18
42
    little_uint16_t ueRegionSize;               // Offset 0x1b
43
    little_uint32_t bmcFlags;                   // Offset 0x1d
44
    little_uint24_t bmcReadPtr;                 // Offset 0x21
45
    std::array<uint8_t, 4> reserved1;           // Offset 0x24
46
    little_uint32_t biosFlags;                  // Offset 0x28
47
    little_uint24_t biosWritePtr;               // Offset 0x2c
48
    uint8_t reserved2;                          // Offset 0x2f
49
    // UE reserved region:                         Offset 0x30
50
    // Error log queue:       Offset 0x30 + UE reserved region
51
52
    bool operator==(const CircularBufferHeader& other) const
53
0
    {
54
0
        /* Skip comparing reserved1 and reserved2 */
55
0
        return std::tie(this->bmcInterfaceVersion, this->biosInterfaceVersion,
56
0
                        this->magicNumber, this->queueSize, this->ueRegionSize,
57
0
                        this->bmcFlags, this->bmcReadPtr, this->biosFlags,
58
0
                        this->biosWritePtr) ==
59
0
               std::tie(other.bmcInterfaceVersion, other.biosInterfaceVersion,
60
0
                        other.magicNumber, other.queueSize, other.ueRegionSize,
61
0
                        other.bmcFlags, other.bmcReadPtr, other.biosFlags,
62
0
                        other.biosWritePtr);
63
0
    }
64
};
65
static_assert(sizeof(CircularBufferHeader) == 0x30,
66
              "Size of CircularBufferHeader struct is incorrect.");
67
68
struct QueueEntryHeader
69
{
70
    little_uint16_t sequenceId; // Offset 0x0
71
    little_uint16_t entrySize;  // Offset 0x2
72
    uint8_t checksum;           // Offset 0x4
73
    uint8_t rdeCommandType;     // Offset 0x5
74
    // RDE Command                 Offset 0x6
75
    bool operator==(const QueueEntryHeader& other) const
76
0
    {
77
0
        return std::tie(this->sequenceId, this->entrySize, this->checksum,
78
0
                        this->rdeCommandType) ==
79
0
               std::tie(other.sequenceId, other.entrySize, other.checksum,
80
0
                        other.rdeCommandType);
81
0
    }
82
};
83
static_assert(sizeof(QueueEntryHeader) == 0x6,
84
              "Size of QueueEntryHeader struct is incorrect.");
85
86
/**
87
 * An interface class for the buffer helper APIs
88
 */
89
class BufferInterface
90
{
91
  public:
92
2.09k
    virtual ~BufferInterface() = default;
93
94
    /**
95
     * Zero out the buffer first before populating the header
96
     *
97
     * @param[in] bmcInterfaceVersion - Used to initialize the header
98
     * @param[in] queueSize - Used to initialize the header
99
     * @param[in] ueRegionSize - Used to initialize the header
100
     * @param[in] magicNumber - Used to initialize the header
101
     * @return true if successful
102
     */
103
    virtual void initialize(uint32_t bmcInterfaceVersion, uint16_t queueSize,
104
                            uint16_t ueRegionSize,
105
                            const std::array<uint32_t, 4>& magicNumber) = 0;
106
    /**
107
     * Check for unread Uncorrecatble Error (UE) logs and read them if present
108
     */
109
    virtual std::vector<uint8_t> readUeLogFromReservedRegion() = 0;
110
111
    /**
112
     * Check for overflow and ackknolwedge if not acked yet
113
     */
114
    virtual bool checkForOverflowAndAcknowledge() = 0;
115
116
    /**
117
     * Read the buffer header from shared buffer
118
     */
119
    virtual void readBufferHeader() = 0;
120
121
    /**
122
     * Getter API for the cached buffer header
123
     * @return cached CircularBufferHeader
124
     */
125
    virtual struct CircularBufferHeader getCachedBufferHeader() const = 0;
126
127
    /**
128
     * Write to the bufferHeader and update the read pointer
129
     * @param[in] newReadPtr - read pointer to update to
130
     */
131
    virtual void updateReadPtr(const uint32_t newReadPtr) = 0;
132
133
    /**
134
     * Write to the bufferHeader and update the BMC flags
135
     * @param[in] newBmcFlags - new flag to update to
136
     */
137
    virtual void updateBmcFlags(const uint32_t newBmcFlags) = 0;
138
139
    /**
140
     * Wrapper for the dataInterface->read, performs wraparound read
141
     *
142
     * @param[in] relativeOffset - offset relative the "Error Log
143
     *  Queue region" = (sizeof(CircularBufferHeader) + UE reserved region)
144
     * @param[in] length - bytes to read
145
     * @return the bytes read
146
     */
147
    virtual std::vector<uint8_t> wraparoundRead(const uint32_t relativeOffset,
148
                                                const uint32_t length) = 0;
149
    /**
150
     * Read the entry header from shared buffer from the read pointer
151
     *
152
     * @return the entry header
153
     */
154
    virtual struct QueueEntryHeader readEntryHeader() = 0;
155
156
    /**
157
     * Read the queue entry from the error log queue from the read pointer
158
     *
159
     * * @return entry header and entry pair read from buffer
160
     */
161
    virtual EntryPair readEntry() = 0;
162
163
    /**
164
     * Read the buffer - this API should be used instead of individual functions
165
     * above
166
     *
167
     * @return vector of EntryPair which consists of entry header and entry
168
     */
169
    virtual std::vector<EntryPair> readErrorLogs() = 0;
170
171
    /**
172
     * Get max offset for the queue
173
     *
174
     * * @return Queue size - UE region size - Queue header size
175
     */
176
    virtual size_t getMaxOffset() = 0;
177
178
    /** @brief The Error log queue starts after the UE region, which is where
179
     * the read and write pointers are offset from relatively
180
     *  @return relative offset for read and write pointers
181
     */
182
    virtual size_t getQueueOffset() = 0;
183
};
184
185
/**
186
 * Buffer implementation class
187
 */
188
class BufferImpl : public BufferInterface
189
{
190
  public:
191
    /** @brief Constructor for BufferImpl
192
     *  @param[in] dataInterface     - DataInterface for this object
193
     */
194
    explicit BufferImpl(std::unique_ptr<DataInterface> dataInterface);
195
    void initialize(uint32_t bmcInterfaceVersion, uint16_t queueSize,
196
                    uint16_t ueRegionSize,
197
                    const std::array<uint32_t, 4>& magicNumber) override;
198
    std::vector<uint8_t> readUeLogFromReservedRegion() override;
199
    bool checkForOverflowAndAcknowledge() override;
200
    void readBufferHeader() override;
201
    struct CircularBufferHeader getCachedBufferHeader() const override;
202
    void updateReadPtr(const uint32_t newReadPtr) override;
203
    void updateBmcFlags(const uint32_t newBmcFlag) override;
204
    std::vector<uint8_t> wraparoundRead(const uint32_t relativeOffset,
205
                                        const uint32_t length) override;
206
    struct QueueEntryHeader readEntryHeader() override;
207
    EntryPair readEntry() override;
208
    std::vector<EntryPair> readErrorLogs() override;
209
    size_t getMaxOffset() override;
210
    size_t getQueueOffset() override;
211
212
  private:
213
    /** @brief Calculate the checksum by XOR each bytes in the span
214
     *  @param[in] entry     - Span to calculate the checksum on
215
     *  @return calculated checksum
216
     */
217
    uint8_t calculateChecksum(std::span<uint8_t> entry);
218
219
    std::unique_ptr<DataInterface> dataInterface;
220
    struct CircularBufferHeader cachedBufferHeader = {};
221
};
222
223
} // namespace bios_bmc_smm_error_logger