diff options
Diffstat (limited to 'extensions/openpower-pels/src.hpp')
-rw-r--r-- | extensions/openpower-pels/src.hpp | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/extensions/openpower-pels/src.hpp b/extensions/openpower-pels/src.hpp new file mode 100644 index 0000000..2296f6f --- /dev/null +++ b/extensions/openpower-pels/src.hpp @@ -0,0 +1,385 @@ +#pragma once + +#include "additional_data.hpp" +#include "ascii_string.hpp" +#include "callouts.hpp" +#include "pel_types.hpp" +#include "registry.hpp" +#include "section.hpp" +#include "stream.hpp" + +namespace openpower +{ +namespace pels +{ + +constexpr uint8_t srcSectionVersion = 0x01; +constexpr uint8_t srcSectionSubtype = 0x01; +constexpr size_t numSRCHexDataWords = 8; +constexpr uint8_t srcVersion = 0x02; +constexpr uint8_t bmcSRCFormat = 0x55; +constexpr uint8_t primaryBMCPosition = 0x10; +constexpr size_t baseSRCSize = 72; + +enum class DetailLevel +{ + message = 0x01, + json = 0x02 +}; +/** + * @class SRC + * + * SRC stands for System Reference Code. + * + * This class represents the SRC sections in the PEL, of which there are 2: + * primary SRC and secondary SRC. These are the same structurally, the + * difference is that the primary SRC must be the 3rd section in the PEL if + * present and there is only one of them, and the secondary SRC sections are + * optional and there can be more than one (by definition, for there to be a + * secondary SRC, a primary SRC must also exist). + * + * This section consists of: + * - An 8B header (Has the version, flags, hexdata word count, and size fields) + * - 8 4B words of hex data + * - An ASCII character string + * - An optional subsection for Callouts + */ +class SRC : public Section +{ + public: + enum HeaderFlags + { + additionalSections = 0x01, + powerFaultEvent = 0x02, + hypDumpInit = 0x04, + i5OSServiceEventBit = 0x10, + virtualProgressSRC = 0x80 + }; + + SRC() = delete; + ~SRC() = default; + SRC(const SRC&) = delete; + SRC& operator=(const SRC&) = delete; + SRC(SRC&&) = delete; + SRC& operator=(SRC&&) = delete; + + /** + * @brief Constructor + * + * Fills in this class's data fields from the stream. + * + * @param[in] pel - the PEL data stream + */ + explicit SRC(Stream& pel); + + /** + * @brief Constructor + * + * Creates the section with data from the PEL message registry entry for + * this error, along with the AdditionalData property contents from the + * corresponding event log. + * + * @param[in] regEntry - The message registry entry for this event log + * @param[in] additionalData - The AdditionalData properties in this event + * log + */ + SRC(const message::Entry& regEntry, const AdditionalData& additionalData); + + /** + * @brief Flatten the section into the stream + * + * @param[in] stream - The stream to write to + */ + void flatten(Stream& stream) const override; + + /** + * @brief Returns the SRC version, which is a different field + * than the version byte in the section header. + * + * @return uint8_t + */ + uint8_t version() const + { + return _version; + } + + /** + * @brief Returns the flags byte + * + * @return uint8_t + */ + uint8_t flags() const + { + return _flags; + } + + /** + * @brief Returns the hex data word count. + * + * Even though there always 8 words, this returns 9 due to previous + * SRC version formats. + * + * @return uint8_t + */ + uint8_t hexWordCount() const + { + return _wordCount; + } + + /** + * @brief Returns the size of the SRC section, not including the header. + * + * @return uint16_t + */ + uint16_t size() const + { + return _size; + } + + /** + * @brief Returns the 8 hex data words. + * + * @return const std::array<uint32_t, numSRCHexDataWords>& + */ + const std::array<uint32_t, numSRCHexDataWords>& hexwordData() const + { + return _hexData; + } + + /** + * @brief Returns the ASCII string + * + * @return std::string + */ + std::string asciiString() const + { + return _asciiString->get(); + } + + /** + * @brief Returns the callouts subsection + * + * If no callouts, this unique_ptr will be empty + * + * @return const std::unique_ptr<src::Callouts>& + */ + const std::unique_ptr<src::Callouts>& callouts() const + { + return _callouts; + } + + /** + * @brief Returns the size of this section when flattened into a PEL + * + * @return size_t - the size of the section + */ + size_t flattenedSize() const + { + return _header.size; + } + + /** + * @brief Says if this SRC has additional subsections in it + * + * Note: The callouts section is the only possible subsection. + * + * @return bool + */ + inline bool hasAdditionalSections() const + { + return _flags & additionalSections; + } + + /** + * @brief Indicates if this event log is for a power fault. + * + * This comes from a field in the message registry for BMC + * generated PELs. + * + * @return bool + */ + inline bool isPowerFaultEvent() const + { + return _flags & powerFaultEvent; + } + + /** + * @brief Get the _hexData[] index to use based on the corresponding + * SRC word number. + * + * Converts the specification nomenclature to this data structure. + * See the _hexData documentation below for more information. + * + * @param[in] wordNum - The SRC word number, as defined by the spec. + * + * @return size_t The corresponding index into _hexData. + */ + inline size_t getWordIndexFromWordNum(size_t wordNum) const + { + assert(wordNum >= 2 && wordNum <= 9); + return wordNum - 2; + } + + /** + * @brief Get section in JSON. + * @return std::optional<std::string> - SRC section's JSON + */ + std::optional<std::string> getJSON() const override; + + /** + * @brief Get error details based on refcode and hexwords + * @param[in] registry - Registry object + * @param[in] type - detail level enum value : single message or full json + * @param[in] toCache - boolean to cache registry in memory, default=false + * @return std::optional<std::string> - Error details + */ + std::optional<std::string> getErrorDetails(message::Registry& registry, + DetailLevel type, + bool toCache = false) const; + + private: + /** + * @brief Fills in the user defined hex words from the + * AdditionalData fields. + * + * When creating this section from a message registry entry, + * that entry has a field that says which AdditionalData property + * fields to use to fill in the user defined hex data words 6-9 + * (which correspond to hexData words 4-7). + * + * For example, given that AdditionalData is a map of string keys + * to string values, find the AdditionalData value for AdditionalData + * key X, convert it to a uint32_t, and save it in user data word Y. + * + * @param[in] regEntry - The message registry entry for the error + * @param[in] additionalData - The AdditionalData map + */ + void setUserDefinedHexWords(const message::Entry& regEntry, + const AdditionalData& additionalData); + /** + * @brief Fills in the object from the stream data + * + * @param[in] stream - The stream to read from + */ + void unflatten(Stream& stream); + + /** + * @brief Says if the word number is in the range of user defined words. + * + * This is only used for BMC generated SRCs, where words 6 - 9 are the + * user defined ones, meaning that setUserDefinedHexWords() will be + * used to fill them in based on the contents of the OpenBMC event log. + * + * @param[in] wordNum - The SRC word number, as defined by the spec. + * + * @return bool - If this word number can be filled in by the creator. + */ + inline bool isUserDefinedWord(size_t wordNum) const + { + return (wordNum >= 6) && (wordNum <= 9); + } + + /** + * @brief Sets the SRC format byte in the hex word data. + */ + inline void setBMCFormat() + { + _hexData[0] |= bmcSRCFormat; + } + + /** + * @brief Sets the hex word field that specifies which BMC + * (primary vs backup) created the error. + * + * Can be hardcoded until there are systems with redundant BMCs. + */ + inline void setBMCPosition() + { + _hexData[1] |= primaryBMCPosition; + } + + /** + * @brief Validates the section contents + * + * Updates _valid (in Section) with the results. + */ + void validate() override; + + /** + * @brief Get error description from message registry + * @param[in] regEntry - The message registry entry for the error + * @return std::optional<std::string> - Error message + */ + std::optional<std::string> + getErrorMessage(const message::Entry& regEntry) const; + + /** + * @brief Get Callout info in JSON + * @return std::optional<std::string> - Callout details + */ + std::optional<std::string> getCallouts() const; + + /** + * @brief The SRC version field + */ + uint8_t _version; + + /** + * @brief The SRC flags field + */ + uint8_t _flags; + + /** + * @brief A byte of reserved data after the flags field + */ + uint8_t _reserved1B; + + /** + * @brief The hex data word count. + * + * To be compatible with previous versions of SRCs, this is + * number of hex words (8) + 1 = 9. + */ + uint8_t _wordCount; + + /** + * @brief Two bytes of reserved data after the hex word count + */ + uint16_t _reserved2B; + + /** + * @brief The total size of the SRC section, not including the section + * header. + */ + uint16_t _size; + + /** + * @brief The SRC 'hex words'. + * + * In the spec these are referred to as SRC words 2 - 9 as words 0 and 1 + * are filled by the 8 bytes of fields from above. + */ + std::array<uint32_t, numSRCHexDataWords> _hexData; + + /** + * @brief The 32 byte ASCII character string of the SRC + * + * It is padded with spaces to fill the 32 bytes. + * An example is: + * "BD8D1234 " + * + * That first word is what is commonly referred to as the refcode, and + * sometimes also called an SRC. + */ + std::unique_ptr<src::AsciiString> _asciiString; + + /** + * @brief The callouts subsection. + * + * Optional and only created if there are callouts. + */ + std::unique_ptr<src::Callouts> _callouts; +}; + +} // namespace pels +} // namespace openpower |