1 #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 11 namespace bios_bmc_smm_error_logger 12 { 13 namespace rde 14 { 15 16 /** 17 * @brief Supported RDE commands. 18 * 19 * The values used are the same as what BIOS uses. 20 */ 21 enum 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 */ 33 enum class RdeDictTransferFlagState 34 { 35 RdeStateIdle, 36 RdeStateStartRecvd, 37 }; 38 39 /** 40 * @brief Status of RDE command processing. 41 */ 42 enum 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 */ 64 class 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 220