diff options
Diffstat (limited to 'extensions/openpower-pels/registry.hpp')
-rw-r--r-- | extensions/openpower-pels/registry.hpp | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/extensions/openpower-pels/registry.hpp b/extensions/openpower-pels/registry.hpp new file mode 100644 index 0000000..0a75d8e --- /dev/null +++ b/extensions/openpower-pels/registry.hpp @@ -0,0 +1,358 @@ +#pragma once +#include <filesystem> +#include <nlohmann/json.hpp> +#include <optional> +#include <string> +#include <vector> + +namespace openpower +{ +namespace pels +{ +namespace message +{ + +constexpr auto registryFileName = "message_registry.json"; +enum class LookupType +{ + name = 0, + reasonCode = 1 +}; + +/** + * @brief Represents the Documentation related fields in the message registry. + * It is part of the 'Entry' structure that will be filled in when + * an error is looked up in the registry. + * + * If a field is wrapped by std::optional, it means the field is + * optional in the JSON and higher level code knows how to handle it. + */ +struct DOC +{ + /** + * @brief Description of error + */ + std::string description; + + /** + * @brief Error message field + */ + std::string message; + + /** + * @brief An optional vector of SRC word 6-9 to use as the source of the + * numeric arguments that will be substituted into any placeholder + * in the Message field. + */ + std::optional<std::vector<std::string>> messageArgSources; +}; + +/** + * @brief Represents the SRC related fields in the message registry. + * It is part of the 'Entry' structure that will be filled in when + * an error is looked up in the registry. + * + * If a field is wrapped by std::optional, it means the field is + * optional in the JSON and higher level code knows how to handle it. + */ +struct SRC +{ + /** + * @brief SRC type - The first byte of the ASCII string + */ + uint8_t type; + + /** + * @brief The SRC reason code (2nd half of 4B 'ASCII string' word) + */ + uint16_t reasonCode; + + /** + * @brief Specifies if the SRC represents a power fault. Optional. + */ + std::optional<bool> powerFault; + + /** + * @brief An optional vector of SRC hexword numbers that should be used + * along with the SRC ASCII string to build the Symptom ID, which + * is a field in the Extended Header section. + */ + using WordNum = size_t; + std::optional<std::vector<WordNum>> symptomID; + + /** + * @brief Which AdditionalData fields to use to fill in the user defined + * SRC hexwords. + * + * For example, if the AdditionalData event log property contained + * "CHIPNUM=42" and this map contained {6, CHIPNUM}, then the code + * would put 42 into SRC hexword 6. + */ + using AdditionalDataField = std::string; + std::optional<std::map<WordNum, AdditionalDataField>> hexwordADFields; + + SRC() : type(0), reasonCode(0) + { + } +}; + +/** + * @brief Represents a message registry entry, which is used for creating a + * PEL from an OpenBMC event log. + */ +struct Entry +{ + /** + * @brief The error name, like "xyz.openbmc_project.Error.Foo". + */ + std::string name; + + /** + * @brief The component ID of the PEL creator. + */ + uint16_t componentID; + + /** + * @brief The PEL subsystem field. + */ + uint8_t subsystem; + + /** + * @brief The optional PEL severity field. If not specified, the PEL + * will use the severity of the OpenBMC event log. + */ + std::optional<uint8_t> severity; + + /** + * @brief The optional severity field to use when in manufacturing tolerance + * mode. + */ + std::optional<uint8_t> mfgSeverity; + + /** + * @brief The PEL action flags field. + */ + std::optional<uint16_t> actionFlags; + + /** + * @brief The optional action flags to use instead when in manufacturing + * tolerance mode. + */ + std::optional<uint16_t> mfgActionFlags; + + /** + * @brief The PEL event type field. If not specified, higher level code + * will decide the value. + */ + std::optional<uint8_t> eventType; + + /** + * @brief The PEL event scope field. If not specified, higher level code + * will decide the value. + */ + std::optional<uint8_t> eventScope; + + /** + * The SRC related fields. + */ + SRC src; + + /** + * The Documentation related fields. + */ + DOC doc; +}; + +/** + * @class Registry + * + * This class wraps the message registry JSON data and allows one to find + * the message registry entry pertaining to the error name. + * + * So that new registry files can easily be tested, the code will look for + * /etc/phosphor-logging/message_registry.json before looking for the real + * path. + */ +class Registry +{ + public: + Registry() = delete; + ~Registry() = default; + Registry(const Registry&) = default; + Registry& operator=(const Registry&) = default; + Registry(Registry&&) = default; + Registry& operator=(Registry&&) = default; + + /** + * @brief Constructor + * @param[in] registryFile - The path to the file. + */ + explicit Registry(const std::filesystem::path& registryFile) : + _registryFile(registryFile) + { + } + + /** + * @brief Find a registry entry based on its error name or reason code. + * + * This function does do some basic sanity checking on the JSON contents, + * but there is also an external program that enforces a schema on the + * registry JSON that should catch all of these problems ahead of time. + * + * @param[in] name - The error name, like xyz.openbmc_project.Error.Foo + * - OR + * - The reason code, like 0x1001 + * @param[in] type - LookupType enum value + * @param[in] toCache - boolean to cache registry in memory + * @return optional<Entry> A filled in message registry structure if + * found, otherwise an empty optional object. + */ + std::optional<Entry> lookup(const std::string& name, LookupType type, + bool toCache = false); + + private: + /** + * @brief Parse message registry file using nlohmann::json + * @param[in] registryFile - The message registry JSON file + * @return optional<nlohmann::json> The full message registry object or an + * empty optional object upon failure. + */ + std::optional<nlohmann::json> + readRegistry(const std::filesystem::path& registryFile); + + /** + * @brief The path to the registry JSON file. + */ + std::filesystem::path _registryFile; + + /** + * @brief The full message registry object. + */ + std::optional<nlohmann::json> _registry; +}; + +namespace helper +{ + +/** + * @brief A helper function to get the PEL subsystem value based on + * the registry subsystem name. + * + * @param[in] subsystemName - The registry name for the subsystem + * + * @return uint8_t The PEL subsystem value + */ +uint8_t getSubsystem(const std::string& subsystemName); + +/** + * @brief A helper function to get the PEL severity value based on + * the registry severity name. + * + * @param[in] severityName - The registry name for the severity + * + * @return uint8_t The PEL severity value + */ +uint8_t getSeverity(const std::string& severityName); + +/** + * @brief A helper function to get the action flags value based on + * the action flag names used in the registry. + * + * @param[in] flags - The list of flag names from the registry. + * + * @return uint16_t - The bitfield of flags used in the PEL. + */ +uint16_t getActionFlags(const std::vector<std::string>& flags); + +/** + * @brief A helper function to get the PEL event type value based on + * the registry event type name. + * + * @param[in] eventTypeName - The registry name for the event type + * + * @return uint8_t The PEL event type value + */ +uint8_t getEventType(const std::string& eventTypeName); + +/** + * @brief A helper function to get the PEL event scope value based on + * the registry event scope name. + * + * @param[in] eventScopeName - The registry name for the event scope + * + * @return uint8_t The PEL event scope value + */ +uint8_t getEventScope(const std::string& eventScopeName); + +/** + * @brief Reads the "ReasonCode" field out of JSON and converts the string value + * such as "0x5555" to a uint16 like 0x5555. + * + * @param[in] src - The message registry SRC dictionary to read from + * @param[in] name - The error name, to use in a trace if things go awry. + * + * @return uint16_t - The reason code + */ +uint16_t getSRCReasonCode(const nlohmann::json& src, const std::string& name); + +/** + * @brief Reads the "Type" field out of JSON and converts it to the SRC::Type + * value. + * + * @param[in] src - The message registry SRC dictionary to read from + * @param[in] name - The error name, to use in a trace if things go awry. + * + * @return uint8_t - The SRC type value, like 0x11 + */ +uint8_t getSRCType(const nlohmann::json& src, const std::string& name); + +/** + * @brief Reads the "Words6To9" field out of JSON and converts it to a map + * of the SRC word number to the AdditionalData property field used + * to fill it in with. + * + * @param[in] src - The message registry SRC dictionary to read from + * @param[in] name - The error name, to use in a trace if things go awry. + * + * @return std::optional<std::map<SRC::WordNum, SRC::AdditionalDataField>> + */ +std::optional<std::map<SRC::WordNum, SRC::AdditionalDataField>> + getSRCHexwordFields(const nlohmann::json& src, const std::string& name); + +/** + * @brief Reads the "SymptomIDFields" field out of JSON and converts it to + * a vector of SRC word numbers. + * + * @param[in] src - The message registry SRC dictionary to read from + * @param[in] name - The error name, to use in a trace if things go awry. + * + * @return std::optional<std::vector<SRC::WordNum>> + */ +std::optional<std::vector<SRC::WordNum>> + getSRCSymptomIDFields(const nlohmann::json& src, const std::string& name); + +/** + * @brief Reads the "ComponentID" field out of JSON and converts it to a + * uint16_t like 0xFF00. + * + * The ComponentID JSON field is only required if the SRC type isn't a BD + * BMC SRC, because for those SRCs it can be inferred from the upper byte + * of the SRC reasoncode. + * + * @param[in] srcType - The SRC type + * @param[in] reasonCode - The SRC reason code + * @param[in] pelEntry - The PEL entry JSON + * @param[in] name - The error name, to use in a trace if things go awry. + * + * @return uin16_t - The component ID, like 0xFF00 + */ +uint16_t getComponentID(uint8_t srcType, uint16_t reasonCode, + const nlohmann::json& pelEntry, + const std::string& name); + +} // namespace helper + +} // namespace message + +} // namespace pels +} // namespace openpower |