1 #pragma once 2 3 #include "additional_data.hpp" 4 #include "ascii_string.hpp" 5 #include "callouts.hpp" 6 #include "data_interface.hpp" 7 #include "pel_types.hpp" 8 #include "registry.hpp" 9 #include "section.hpp" 10 #include "stream.hpp" 11 12 namespace openpower 13 { 14 namespace pels 15 { 16 17 constexpr uint8_t srcSectionVersion = 0x01; 18 constexpr uint8_t srcSectionSubtype = 0x01; 19 constexpr size_t numSRCHexDataWords = 8; 20 constexpr uint8_t srcVersion = 0x02; 21 constexpr uint8_t bmcSRCFormat = 0x55; 22 constexpr uint8_t primaryBMCPosition = 0x10; 23 constexpr size_t baseSRCSize = 72; 24 25 enum class DetailLevel 26 { 27 message = 0x01, 28 json = 0x02 29 }; 30 /** 31 * @class SRC 32 * 33 * SRC stands for System Reference Code. 34 * 35 * This class represents the SRC sections in the PEL, of which there are 2: 36 * primary SRC and secondary SRC. These are the same structurally, the 37 * difference is that the primary SRC must be the 3rd section in the PEL if 38 * present and there is only one of them, and the secondary SRC sections are 39 * optional and there can be more than one (by definition, for there to be a 40 * secondary SRC, a primary SRC must also exist). 41 * 42 * This section consists of: 43 * - An 8B header (Has the version, flags, hexdata word count, and size fields) 44 * - 8 4B words of hex data 45 * - An ASCII character string 46 * - An optional subsection for Callouts 47 */ 48 class SRC : public Section 49 { 50 public: 51 enum HeaderFlags 52 { 53 additionalSections = 0x01, 54 powerFaultEvent = 0x02, 55 hypDumpInit = 0x04, 56 i5OSServiceEventBit = 0x10, 57 virtualProgressSRC = 0x80 58 }; 59 60 SRC() = delete; 61 ~SRC() = default; 62 SRC(const SRC&) = delete; 63 SRC& operator=(const SRC&) = delete; 64 SRC(SRC&&) = delete; 65 SRC& operator=(SRC&&) = delete; 66 67 /** 68 * @brief Constructor 69 * 70 * Fills in this class's data fields from the stream. 71 * 72 * @param[in] pel - the PEL data stream 73 */ 74 explicit SRC(Stream& pel); 75 76 /** 77 * @brief Constructor 78 * 79 * Creates the section with data from the PEL message registry entry for 80 * this error, along with the AdditionalData property contents from the 81 * corresponding event log. 82 * 83 * @param[in] regEntry - The message registry entry for this event log 84 * @param[in] additionalData - The AdditionalData properties in this event 85 * log 86 * @param[in] dataIface - The DataInterface object 87 */ 88 SRC(const message::Entry& regEntry, const AdditionalData& additionalData, 89 const DataInterfaceBase& dataIface); 90 91 /** 92 * @brief Flatten the section into the stream 93 * 94 * @param[in] stream - The stream to write to 95 */ 96 void flatten(Stream& stream) const override; 97 98 /** 99 * @brief Returns the SRC version, which is a different field 100 * than the version byte in the section header. 101 * 102 * @return uint8_t 103 */ 104 uint8_t version() const 105 { 106 return _version; 107 } 108 109 /** 110 * @brief Returns the flags byte 111 * 112 * @return uint8_t 113 */ 114 uint8_t flags() const 115 { 116 return _flags; 117 } 118 119 /** 120 * @brief Returns the hex data word count. 121 * 122 * Even though there always 8 words, this returns 9 due to previous 123 * SRC version formats. 124 * 125 * @return uint8_t 126 */ 127 uint8_t hexWordCount() const 128 { 129 return _wordCount; 130 } 131 132 /** 133 * @brief Returns the size of the SRC section, not including the header. 134 * 135 * @return uint16_t 136 */ 137 uint16_t size() const 138 { 139 return _size; 140 } 141 142 /** 143 * @brief Returns the 8 hex data words. 144 * 145 * @return const std::array<uint32_t, numSRCHexDataWords>& 146 */ 147 const std::array<uint32_t, numSRCHexDataWords>& hexwordData() const 148 { 149 return _hexData; 150 } 151 152 /** 153 * @brief Returns the ASCII string 154 * 155 * @return std::string 156 */ 157 std::string asciiString() const 158 { 159 return _asciiString->get(); 160 } 161 162 /** 163 * @brief Returns the callouts subsection 164 * 165 * If no callouts, this unique_ptr will be empty 166 * 167 * @return const std::unique_ptr<src::Callouts>& 168 */ 169 const std::unique_ptr<src::Callouts>& callouts() const 170 { 171 return _callouts; 172 } 173 174 /** 175 * @brief Returns the size of this section when flattened into a PEL 176 * 177 * @return size_t - the size of the section 178 */ 179 size_t flattenedSize() const 180 { 181 return _header.size; 182 } 183 184 /** 185 * @brief Says if this SRC has additional subsections in it 186 * 187 * Note: The callouts section is the only possible subsection. 188 * 189 * @return bool 190 */ 191 inline bool hasAdditionalSections() const 192 { 193 return _flags & additionalSections; 194 } 195 196 /** 197 * @brief Indicates if this event log is for a power fault. 198 * 199 * This comes from a field in the message registry for BMC 200 * generated PELs. 201 * 202 * @return bool 203 */ 204 inline bool isPowerFaultEvent() const 205 { 206 return _flags & powerFaultEvent; 207 } 208 209 /** 210 * @brief Get the _hexData[] index to use based on the corresponding 211 * SRC word number. 212 * 213 * Converts the specification nomenclature to this data structure. 214 * See the _hexData documentation below for more information. 215 * 216 * @param[in] wordNum - The SRC word number, as defined by the spec. 217 * 218 * @return size_t The corresponding index into _hexData. 219 */ 220 inline size_t getWordIndexFromWordNum(size_t wordNum) const 221 { 222 assert(wordNum >= 2 && wordNum <= 9); 223 return wordNum - 2; 224 } 225 226 /** 227 * @brief Get section in JSON. 228 * @param[in] registry - Registry object reference 229 * @return std::optional<std::string> - SRC section's JSON 230 */ 231 std::optional<std::string> 232 getJSON(message::Registry& registry) const override; 233 234 /** 235 * @brief Get error details based on refcode and hexwords 236 * @param[in] registry - Registry object 237 * @param[in] type - detail level enum value : single message or full json 238 * @param[in] toCache - boolean to cache registry in memory, default=false 239 * @return std::optional<std::string> - Error details 240 */ 241 std::optional<std::string> getErrorDetails(message::Registry& registry, 242 DetailLevel type, 243 bool toCache = false) const; 244 245 /** 246 * @brief Says if this SRC was created by the BMC (i.e. this code). 247 * 248 * @return bool - If created by the BMC or not 249 */ 250 bool isBMCSRC() const; 251 252 private: 253 /** 254 * @brief Fills in the user defined hex words from the 255 * AdditionalData fields. 256 * 257 * When creating this section from a message registry entry, 258 * that entry has a field that says which AdditionalData property 259 * fields to use to fill in the user defined hex data words 6-9 260 * (which correspond to hexData words 4-7). 261 * 262 * For example, given that AdditionalData is a map of string keys 263 * to string values, find the AdditionalData value for AdditionalData 264 * key X, convert it to a uint32_t, and save it in user data word Y. 265 * 266 * @param[in] regEntry - The message registry entry for the error 267 * @param[in] additionalData - The AdditionalData map 268 */ 269 void setUserDefinedHexWords(const message::Entry& regEntry, 270 const AdditionalData& additionalData); 271 /** 272 * @brief Fills in the object from the stream data 273 * 274 * @param[in] stream - The stream to read from 275 */ 276 void unflatten(Stream& stream); 277 278 /** 279 * @brief Says if the word number is in the range of user defined words. 280 * 281 * This is only used for BMC generated SRCs, where words 6 - 9 are the 282 * user defined ones, meaning that setUserDefinedHexWords() will be 283 * used to fill them in based on the contents of the OpenBMC event log. 284 * 285 * @param[in] wordNum - The SRC word number, as defined by the spec. 286 * 287 * @return bool - If this word number can be filled in by the creator. 288 */ 289 inline bool isUserDefinedWord(size_t wordNum) const 290 { 291 return (wordNum >= 6) && (wordNum <= 9); 292 } 293 294 /** 295 * @brief Sets the SRC format byte in the hex word data. 296 */ 297 inline void setBMCFormat() 298 { 299 _hexData[0] |= bmcSRCFormat; 300 } 301 302 /** 303 * @brief Sets the hex word field that specifies which BMC 304 * (primary vs backup) created the error. 305 * 306 * Can be hardcoded until there are systems with redundant BMCs. 307 */ 308 inline void setBMCPosition() 309 { 310 _hexData[1] |= primaryBMCPosition; 311 } 312 313 /** 314 * @brief Sets the motherboard CCIN hex word field 315 * 316 * @param[in] dataIface - The DataInterface object 317 */ 318 void setMotherboardCCIN(const DataInterfaceBase& dataIface); 319 320 /** 321 * @brief Validates the section contents 322 * 323 * Updates _valid (in Section) with the results. 324 */ 325 void validate() override; 326 327 /** 328 * @brief Get error description from message registry 329 * @param[in] regEntry - The message registry entry for the error 330 * @return std::optional<std::string> - Error message 331 */ 332 std::optional<std::string> 333 getErrorMessage(const message::Entry& regEntry) const; 334 335 /** 336 * @brief Get Callout info in JSON 337 * @return std::optional<std::string> - Callout details 338 */ 339 std::optional<std::string> getCallouts() const; 340 341 /** 342 * @brief The SRC version field 343 */ 344 uint8_t _version; 345 346 /** 347 * @brief The SRC flags field 348 */ 349 uint8_t _flags; 350 351 /** 352 * @brief A byte of reserved data after the flags field 353 */ 354 uint8_t _reserved1B; 355 356 /** 357 * @brief The hex data word count. 358 * 359 * To be compatible with previous versions of SRCs, this is 360 * number of hex words (8) + 1 = 9. 361 */ 362 uint8_t _wordCount; 363 364 /** 365 * @brief Two bytes of reserved data after the hex word count 366 */ 367 uint16_t _reserved2B; 368 369 /** 370 * @brief The total size of the SRC section, not including the section 371 * header. 372 */ 373 uint16_t _size; 374 375 /** 376 * @brief The SRC 'hex words'. 377 * 378 * In the spec these are referred to as SRC words 2 - 9 as words 0 and 1 379 * are filled by the 8 bytes of fields from above. 380 */ 381 std::array<uint32_t, numSRCHexDataWords> _hexData; 382 383 /** 384 * @brief The 32 byte ASCII character string of the SRC 385 * 386 * It is padded with spaces to fill the 32 bytes. 387 * An example is: 388 * "BD8D1234 " 389 * 390 * That first word is what is commonly referred to as the refcode, and 391 * sometimes also called an SRC. 392 */ 393 std::unique_ptr<src::AsciiString> _asciiString; 394 395 /** 396 * @brief The callouts subsection. 397 * 398 * Optional and only created if there are callouts. 399 */ 400 std::unique_ptr<src::Callouts> _callouts; 401 }; 402 403 } // namespace pels 404 } // namespace openpower 405