blob: 65e936173eb94fa56e1831ca2817e8649e93cd0f [file] [log] [blame]
kasunathbac958d2022-06-07 18:15:24 -07001#pragma once
2
3#include "bej_decoder_json.hpp"
4#include "external_storer_interface.hpp"
5#include "rde_dictionary_manager.hpp"
6
7#include <cstdint>
8#include <span>
9#include <string_view>
10
11namespace bios_bmc_smm_error_logger
12{
13namespace rde
14{
15
16/**
17 * @brief Supported RDE commands.
18 *
19 * The values used are the same as what BIOS uses.
20 */
21enum class RdeCommandType : char
22{
23 // Used for RDE BEJ dictionary transfer.
24 RdeMultiPartReceiveResponse = 1,
25 // Used for RDE BEJ encoded data.
26 RdeOperationInitRequest = 2,
27};
28
29/**
30 * @brief Used to keep track of RdeMultiPartReceiveResponse START flag
31 * reception.
32 */
33enum class RdeDictTransferFlagState
34{
35 RdeStateIdle,
36 RdeStateStartRecvd,
37};
38
39/**
40 * @brief Status of RDE command processing.
41 */
42enum class RdeDecodeStatus
43{
44 RdeOk,
45 RdeInvalidCommand,
46 RdeUnsupportedOperation,
47 RdeNoDictionary,
48 RdePayloadOverflow,
49 RdeBejDecodingError,
50 RdeInvalidPktOrder,
51 RdeDictionaryError,
52 RdeFileCreationFailed,
53 RdeExternalStorerError,
54 // This implies that the stop flag has been received.
55 RdeInvalidChecksum,
56 // This implies that the checksum is correct.
57 RdeStopFlagReceived,
58};
59
60/**
61 * @brief Handles RDE messages from the BIOS - BMC circular buffer and updates
62 * ExternalStorer.
63 */
64class RdeCommandHandler
65{
66 public:
67 /**
68 * @brief Constructor for RdeExternalStorer.
69 *
70 * @param[in] exStorer - valid ExternalStorerInterface. This class will take
71 * the ownership of this object.
72 */
73 explicit RdeCommandHandler(
74 std::unique_ptr<ExternalStorerInterface> exStorer);
75
76 /**
77 * @brief Decode a RDE command.
78 *
79 * @param[in] rdeCommand - RDE command.
80 * @param[in] type - RDE command type.
81 * @return RdeDecodeStatus code.
82 */
83 RdeDecodeStatus decodeRdeCommand(std::span<const uint8_t> rdeCommand,
84 RdeCommandType type);
85
86 /**
87 * @brief Get the number of complete dictionaries received.
88 *
89 * @return number of complete dictionaries.
90 */
91 uint32_t getDictionaryCount();
92
93 private:
94 /**
95 * @brief This keeps track of whether we received the dictionary start flag
96 * or not.
97 */
98 RdeDictTransferFlagState flagState;
99
100 std::unique_ptr<ExternalStorerInterface> exStorer;
101
102 /**
103 * @brief We are using the prevDictResourceId to detect a new dictionary.
104 *
105 * BIOS-BMC buffer uses RdeMultiPartReceiveResponse START flag to indicate
106 * the first dictionary data chunk. BMC will not receive this flag at start
107 * of every new dictionary but only for the first data chunk. Therefore
108 * difference between resource ID is used to identify a new dictionary
109 * start. prevDictResourceId keeps track of the resource ID of the last
110 * dictionary data chunk.
111 */
112 uint32_t prevDictResourceId;
113
114 DictionaryManager dictionaryManager;
115 libbej::BejDecoderJson decoder;
116
117 uint32_t crc;
118 std::array<uint32_t, UINT8_MAX + 1> crcTable;
119
120 /**
121 * @brief Handles OperationInit request messages.
122 *
123 * @param[in] rdeCommand - RDE command.
124 * @return RdeDecodeStatus
125 */
126 RdeDecodeStatus operationInitRequest(std::span<const uint8_t> rdeCommand);
127
128 /**
129 * @brief Handles MultiPartReceive response messages.
130 *
131 * @param[in] rdeCommand - RDE command.
132 * @return RdeDecodeStatus
133 */
134 RdeDecodeStatus multiPartReceiveResp(std::span<const uint8_t> rdeCommand);
135
136 /**
137 * @brief Initializes the CRC table.
138 */
139 void calcCrcTable();
140
141 /**
142 * @brief Update the existing CRC using the provided byte stream.
143 *
144 * According to the RDE BEJ specification: "32-bit CRC for the entire block
145 * of data (all parts concatenated together, excluding this checksum)".
146 * Therefore when calculating the CRC whole RDEMultipartReceive Response
147 * data packet is considered, not just the dictionary data contained within
148 * it.
149 *
150 * @param[in] stream - a byte stream.
151 */
152 void updateCrc(std::span<const uint8_t> stream);
153
154 /**
155 * @brief Get the final checksum value.
156 *
157 * @return uint32_t - final checksum value.
158 */
159 uint32_t finalChecksum();
160
161 /**
162 * @brief Process received CRC field from a multi receive response command.
163 * END or START_AND_END flag should be set in the command.
164 *
165 * @param multiReceiveRespCmd - payload with a checksum field populated.
166 * @return RdeDecodeStatus
167 */
168 RdeDecodeStatus handleCrc(std::span<const uint8_t> multiReceiveRespCmd);
169
170 /**
171 * @brief Handle dictionary data with flag Start.
172 *
173 * @param[in] header - RDE header portion of the RDE command.
174 * @param[in] data - data portion of the RDE command.
175 * @param[in] resourceId - PDR resource ID of the dictionary.
176 */
177 void handleFlagStart(const MultipartReceiveResHeader* header,
178 const uint8_t* data, uint32_t resourceId);
179
180 /**
181 * @brief Handle dictionary data with flag Middle.
182 *
183 * @param[in] header - RDE header portion of the RDE command.
184 * @param[in] data - data portion of the RDE command.
185 * @param[in] resourceId - PDR resource ID of the dictionary.
186 * @return RdeDecodeStatus
187 */
188 RdeDecodeStatus handleFlagMiddle(const MultipartReceiveResHeader* header,
189 const uint8_t* data, uint32_t resourceId);
190 /**
191 * @brief Handle dictionary data with flag End.
192 *
193 * @param[in] rdeCommand - RDE command.
194 * @param[in] header - RDE header portion of the RDE command.
195 * @param[in] data - data portion of the RDE command.
196 * @param[in] resourceId - PDR resource ID of the dictionary.
197 * @return RdeDecodeStatus
198 */
199 RdeDecodeStatus handleFlagEnd(std::span<const uint8_t> rdeCommand,
200 const MultipartReceiveResHeader* header,
201 const uint8_t* data, uint32_t resourceId);
202
203 /**
204 * @brief Handle dictionary data with flag StartAndEnd.
205 *
206 * @param[in] rdeCommand - RDE command.
207 * @param[in] header - RDE header portion of the RDE command.
208 * @param[in] data - data portion of the RDE command.
209 * @param[in] resourceId - PDR resource ID of the dictionary.
210 * @return RdeDecodeStatus
211 */
212 RdeDecodeStatus
213 handleFlagStartAndEnd(std::span<const uint8_t> rdeCommand,
214 const MultipartReceiveResHeader* header,
215 const uint8_t* data, uint32_t resourceId);
216};
217
218} // namespace rde
219} // namespace bios_bmc_smm_error_logger