xref: /openbmc/phosphor-logging/extensions/openpower-pels/registry.cpp (revision 075c79237505ea3b810a461f5f514e4d520a0c44)
1711d51d8SMatt Spinler /**
2711d51d8SMatt Spinler  * Copyright © 2019 IBM Corporation
3711d51d8SMatt Spinler  *
4711d51d8SMatt Spinler  * Licensed under the Apache License, Version 2.0 (the "License");
5711d51d8SMatt Spinler  * you may not use this file except in compliance with the License.
6711d51d8SMatt Spinler  * You may obtain a copy of the License at
7711d51d8SMatt Spinler  *
8711d51d8SMatt Spinler  *     http://www.apache.org/licenses/LICENSE-2.0
9711d51d8SMatt Spinler  *
10711d51d8SMatt Spinler  * Unless required by applicable law or agreed to in writing, software
11711d51d8SMatt Spinler  * distributed under the License is distributed on an "AS IS" BASIS,
12711d51d8SMatt Spinler  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13711d51d8SMatt Spinler  * See the License for the specific language governing permissions and
14711d51d8SMatt Spinler  * limitations under the License.
15711d51d8SMatt Spinler  */
16367144cfSMatt Spinler #include "registry.hpp"
17367144cfSMatt Spinler 
181a1b0dfbSHarisuddin Mohamed Isa #include "json_utils.hpp"
19367144cfSMatt Spinler #include "pel_types.hpp"
20367144cfSMatt Spinler #include "pel_values.hpp"
21367144cfSMatt Spinler 
224f460319SMatt Spinler #include <phosphor-logging/lg2.hpp>
23367144cfSMatt Spinler 
2415370292SArya K Padman #include <algorithm>
252544b419SPatrick Williams #include <fstream>
262544b419SPatrick Williams 
27367144cfSMatt Spinler namespace openpower
28367144cfSMatt Spinler {
29367144cfSMatt Spinler namespace pels
30367144cfSMatt Spinler {
31367144cfSMatt Spinler namespace message
32367144cfSMatt Spinler {
33367144cfSMatt Spinler 
34367144cfSMatt Spinler namespace pv = pel_values;
35367144cfSMatt Spinler namespace fs = std::filesystem;
36367144cfSMatt Spinler 
37367144cfSMatt Spinler constexpr auto debugFilePath = "/etc/phosphor-logging/";
38367144cfSMatt Spinler 
39367144cfSMatt Spinler namespace helper
40367144cfSMatt Spinler {
41367144cfSMatt Spinler 
getSubsystem(const std::string & subsystemName)42367144cfSMatt Spinler uint8_t getSubsystem(const std::string& subsystemName)
43367144cfSMatt Spinler {
44367144cfSMatt Spinler     // Get the actual value to use in the PEL for the string name
45367144cfSMatt Spinler     auto ss = pv::findByName(subsystemName, pv::subsystemValues);
46367144cfSMatt Spinler     if (ss == pv::subsystemValues.end())
47367144cfSMatt Spinler     {
48367144cfSMatt Spinler         // Schema validation should be catching this.
494f460319SMatt Spinler         lg2::error("Invalid subsystem name used in message registry: {SUBSYS}",
504f460319SMatt Spinler                    "SUBSYS", subsystemName);
51367144cfSMatt Spinler 
52367144cfSMatt Spinler         throw std::runtime_error("Invalid subsystem used in message registry");
53367144cfSMatt Spinler     }
54367144cfSMatt Spinler 
55367144cfSMatt Spinler     return std::get<pv::fieldValuePos>(*ss);
56367144cfSMatt Spinler }
57367144cfSMatt Spinler 
getSeverity(const std::string & severityName)58367144cfSMatt Spinler uint8_t getSeverity(const std::string& severityName)
59367144cfSMatt Spinler {
60367144cfSMatt Spinler     auto s = pv::findByName(severityName, pv::severityValues);
61367144cfSMatt Spinler     if (s == pv::severityValues.end())
62367144cfSMatt Spinler     {
63367144cfSMatt Spinler         // Schema validation should be catching this.
644f460319SMatt Spinler         lg2::error("Invalid severity name used in message registry: {SEV}",
654f460319SMatt Spinler                    "SEV", severityName);
66367144cfSMatt Spinler 
67367144cfSMatt Spinler         throw std::runtime_error("Invalid severity used in message registry");
68367144cfSMatt Spinler     }
69367144cfSMatt Spinler 
70367144cfSMatt Spinler     return std::get<pv::fieldValuePos>(*s);
71367144cfSMatt Spinler }
72367144cfSMatt Spinler 
getSeverities(const nlohmann::json & severity)73aadccc85SMatt Spinler std::vector<RegistrySeverity> getSeverities(const nlohmann::json& severity)
74aadccc85SMatt Spinler {
75aadccc85SMatt Spinler     std::vector<RegistrySeverity> severities;
76aadccc85SMatt Spinler 
77aadccc85SMatt Spinler     // The plain string value, like "unrecoverable"
78aadccc85SMatt Spinler     if (severity.is_string())
79aadccc85SMatt Spinler     {
80aadccc85SMatt Spinler         RegistrySeverity s;
81aadccc85SMatt Spinler         s.severity = getSeverity(severity.get<std::string>());
82aadccc85SMatt Spinler         severities.push_back(std::move(s));
83aadccc85SMatt Spinler     }
84aadccc85SMatt Spinler     else
85aadccc85SMatt Spinler     {
86aadccc85SMatt Spinler         // An array, with an element like:
87aadccc85SMatt Spinler         // {
88aadccc85SMatt Spinler         //    "SevValue": "unrecoverable",
89aadccc85SMatt Spinler         //    "System", "systemA"
90aadccc85SMatt Spinler         // }
91aadccc85SMatt Spinler         for (const auto& sev : severity)
92aadccc85SMatt Spinler         {
93aadccc85SMatt Spinler             RegistrySeverity s;
94aadccc85SMatt Spinler             s.severity = getSeverity(sev["SevValue"].get<std::string>());
95aadccc85SMatt Spinler 
96aadccc85SMatt Spinler             if (sev.contains("System"))
97aadccc85SMatt Spinler             {
98aadccc85SMatt Spinler                 s.system = sev["System"].get<std::string>();
99aadccc85SMatt Spinler             }
100aadccc85SMatt Spinler 
101aadccc85SMatt Spinler             severities.push_back(std::move(s));
102aadccc85SMatt Spinler         }
103aadccc85SMatt Spinler     }
104aadccc85SMatt Spinler 
105aadccc85SMatt Spinler     return severities;
106aadccc85SMatt Spinler }
107aadccc85SMatt Spinler 
getActionFlags(const std::vector<std::string> & flags)108367144cfSMatt Spinler uint16_t getActionFlags(const std::vector<std::string>& flags)
109367144cfSMatt Spinler {
110367144cfSMatt Spinler     uint16_t actionFlags = 0;
111367144cfSMatt Spinler 
112367144cfSMatt Spinler     // Make the bitmask based on the array of flag names
113367144cfSMatt Spinler     for (const auto& flag : flags)
114367144cfSMatt Spinler     {
115367144cfSMatt Spinler         auto s = pv::findByName(flag, pv::actionFlagsValues);
116367144cfSMatt Spinler         if (s == pv::actionFlagsValues.end())
117367144cfSMatt Spinler         {
118367144cfSMatt Spinler             // Schema validation should be catching this.
1194f460319SMatt Spinler             lg2::error(
1204f460319SMatt Spinler                 "Invalid action flag name used in message registry: {FLAG}",
1214f460319SMatt Spinler                 "FLAG", flag);
122367144cfSMatt Spinler 
123367144cfSMatt Spinler             throw std::runtime_error(
124367144cfSMatt Spinler                 "Invalid action flag used in message registry");
125367144cfSMatt Spinler         }
126367144cfSMatt Spinler 
127367144cfSMatt Spinler         actionFlags |= std::get<pv::fieldValuePos>(*s);
128367144cfSMatt Spinler     }
129367144cfSMatt Spinler 
130367144cfSMatt Spinler     return actionFlags;
131367144cfSMatt Spinler }
132367144cfSMatt Spinler 
getEventType(const std::string & eventTypeName)133367144cfSMatt Spinler uint8_t getEventType(const std::string& eventTypeName)
134367144cfSMatt Spinler {
135367144cfSMatt Spinler     auto t = pv::findByName(eventTypeName, pv::eventTypeValues);
136367144cfSMatt Spinler     if (t == pv::eventTypeValues.end())
137367144cfSMatt Spinler     {
1384f460319SMatt Spinler         lg2::error("Invalid event type used in message registry: {TYPE}",
1394f460319SMatt Spinler                    "TYPE", eventTypeName);
140367144cfSMatt Spinler 
141367144cfSMatt Spinler         throw std::runtime_error("Invalid event type used in message registry");
142367144cfSMatt Spinler     }
143367144cfSMatt Spinler     return std::get<pv::fieldValuePos>(*t);
144367144cfSMatt Spinler }
145367144cfSMatt Spinler 
getEventScope(const std::string & eventScopeName)146367144cfSMatt Spinler uint8_t getEventScope(const std::string& eventScopeName)
147367144cfSMatt Spinler {
148367144cfSMatt Spinler     auto s = pv::findByName(eventScopeName, pv::eventScopeValues);
149367144cfSMatt Spinler     if (s == pv::eventScopeValues.end())
150367144cfSMatt Spinler     {
1514f460319SMatt Spinler         lg2::error("Invalid event scope used in registry: {SCOPE}", "SCOPE",
1524f460319SMatt Spinler                    eventScopeName);
153367144cfSMatt Spinler 
154367144cfSMatt Spinler         throw std::runtime_error(
155367144cfSMatt Spinler             "Invalid event scope used in message registry");
156367144cfSMatt Spinler     }
157367144cfSMatt Spinler     return std::get<pv::fieldValuePos>(*s);
158367144cfSMatt Spinler }
159367144cfSMatt Spinler 
getSRCReasonCode(const nlohmann::json & src,const std::string & name)16093e2932fSMatt Spinler uint16_t getSRCReasonCode(const nlohmann::json& src, const std::string& name)
16193e2932fSMatt Spinler {
16293e2932fSMatt Spinler     std::string rc = src["ReasonCode"];
16393e2932fSMatt Spinler     uint16_t reasonCode = strtoul(rc.c_str(), nullptr, 16);
16493e2932fSMatt Spinler     if (reasonCode == 0)
16593e2932fSMatt Spinler     {
1664f460319SMatt Spinler         lg2::error(
1674f460319SMatt Spinler             "Invalid reason code {RC} in message registry, error name = {ERROR}",
1684f460319SMatt Spinler             "RC", rc, "ERROR", name);
16993e2932fSMatt Spinler 
17093e2932fSMatt Spinler         throw std::runtime_error("Invalid reason code in message registry");
17193e2932fSMatt Spinler     }
17293e2932fSMatt Spinler     return reasonCode;
17393e2932fSMatt Spinler }
17493e2932fSMatt Spinler 
getSRCType(const nlohmann::json & src,const std::string & name)17593e2932fSMatt Spinler uint8_t getSRCType(const nlohmann::json& src, const std::string& name)
17693e2932fSMatt Spinler {
17793e2932fSMatt Spinler     // Looks like: "22"
17893e2932fSMatt Spinler     std::string srcType = src["Type"];
17993e2932fSMatt Spinler     size_t type = strtoul(srcType.c_str(), nullptr, 16);
18093e2932fSMatt Spinler     if ((type == 0) || (srcType.size() != 2)) // 1 hex byte
18193e2932fSMatt Spinler     {
1824f460319SMatt Spinler         lg2::error(
1834f460319SMatt Spinler             "Invalid SRC Type {TYPE} in message registry, error name = {ERROR}",
1844f460319SMatt Spinler             "TYPE", srcType, "ERROR", name);
18593e2932fSMatt Spinler 
18693e2932fSMatt Spinler         throw std::runtime_error("Invalid SRC Type in message registry");
18793e2932fSMatt Spinler     }
18893e2932fSMatt Spinler 
18993e2932fSMatt Spinler     return type;
19093e2932fSMatt Spinler }
19193e2932fSMatt Spinler 
getSRCDeconfigFlag(const nlohmann::json & src)1923fe93e96SMatt Spinler bool getSRCDeconfigFlag(const nlohmann::json& src)
1933fe93e96SMatt Spinler {
1943fe93e96SMatt Spinler     return src["DeconfigFlag"].get<bool>();
1953fe93e96SMatt Spinler }
1963fe93e96SMatt Spinler 
getSRCCheckstopFlag(const nlohmann::json & src)197da5b76b2SMatt Spinler bool getSRCCheckstopFlag(const nlohmann::json& src)
198da5b76b2SMatt Spinler {
199da5b76b2SMatt Spinler     return src["CheckstopFlag"].get<bool>();
200da5b76b2SMatt Spinler }
201da5b76b2SMatt Spinler 
20293e2932fSMatt Spinler std::optional<std::map<SRC::WordNum, SRC::AdditionalDataField>>
getSRCHexwordFields(const nlohmann::json & src,const std::string & name)20393e2932fSMatt Spinler     getSRCHexwordFields(const nlohmann::json& src, const std::string& name)
20493e2932fSMatt Spinler {
20593e2932fSMatt Spinler     std::map<SRC::WordNum, SRC::AdditionalDataField> hexwordFields;
20693e2932fSMatt Spinler 
20793e2932fSMatt Spinler     // Build the map of which AdditionalData fields to use for which SRC words
20893e2932fSMatt Spinler 
20993e2932fSMatt Spinler     // Like:
21093e2932fSMatt Spinler     // {
21193e2932fSMatt Spinler     //   "8":
21293e2932fSMatt Spinler     //   {
21393e2932fSMatt Spinler     //     "AdditionalDataPropSource": "TEST"
21493e2932fSMatt Spinler     //   }
21593e2932fSMatt Spinler     //
21693e2932fSMatt Spinler     // }
21793e2932fSMatt Spinler 
21893e2932fSMatt Spinler     for (const auto& word : src["Words6To9"].items())
21993e2932fSMatt Spinler     {
22093e2932fSMatt Spinler         std::string num = word.key();
22193e2932fSMatt Spinler         size_t wordNum = std::strtoul(num.c_str(), nullptr, 10);
22293e2932fSMatt Spinler 
22393e2932fSMatt Spinler         if (wordNum == 0)
22493e2932fSMatt Spinler         {
2254f460319SMatt Spinler             lg2::error(
2264f460319SMatt Spinler                 "Invalid SRC word number {NUM} in message registry, error name = {ERROR}",
2274f460319SMatt Spinler                 "NUM", num, "ERROR", name);
22893e2932fSMatt Spinler 
22993e2932fSMatt Spinler             throw std::runtime_error("Invalid SRC word in message registry");
23093e2932fSMatt Spinler         }
23193e2932fSMatt Spinler 
23293e2932fSMatt Spinler         auto attributes = word.value();
233e8db29b3SZane Shelley 
234e8db29b3SZane Shelley         // Use an empty string for the description if it does not exist.
235e8db29b3SZane Shelley         auto itr = attributes.find("Description");
236e8db29b3SZane Shelley         std::string desc = (attributes.end() != itr) ? *itr : "";
237e8db29b3SZane Shelley 
2381a1b0dfbSHarisuddin Mohamed Isa         std::tuple<std::string, std::string> adPropSourceDesc(
239e8db29b3SZane Shelley             attributes["AdditionalDataPropSource"], desc);
2401a1b0dfbSHarisuddin Mohamed Isa         hexwordFields[wordNum] = std::move(adPropSourceDesc);
24193e2932fSMatt Spinler     }
24293e2932fSMatt Spinler 
24393e2932fSMatt Spinler     if (!hexwordFields.empty())
24493e2932fSMatt Spinler     {
24593e2932fSMatt Spinler         return hexwordFields;
24693e2932fSMatt Spinler     }
24793e2932fSMatt Spinler 
24893e2932fSMatt Spinler     return std::nullopt;
24993e2932fSMatt Spinler }
25093e2932fSMatt Spinler std::optional<std::vector<SRC::WordNum>>
getSRCSymptomIDFields(const nlohmann::json & src,const std::string & name)25193e2932fSMatt Spinler     getSRCSymptomIDFields(const nlohmann::json& src, const std::string& name)
25293e2932fSMatt Spinler {
25393e2932fSMatt Spinler     std::vector<SRC::WordNum> symptomIDFields;
25493e2932fSMatt Spinler 
25593e2932fSMatt Spinler     // Looks like:
25693e2932fSMatt Spinler     // "SymptomIDFields": ["SRCWord3", "SRCWord6"],
25793e2932fSMatt Spinler 
2589d59d585SMatt Spinler     for (const std::string field : src["SymptomIDFields"])
25993e2932fSMatt Spinler     {
26093e2932fSMatt Spinler         // Just need the last digit off the end, e.g. SRCWord6.
26193e2932fSMatt Spinler         // The schema enforces the format of these.
26293e2932fSMatt Spinler         auto srcWordNum = field.substr(field.size() - 1);
26393e2932fSMatt Spinler         size_t num = std::strtoul(srcWordNum.c_str(), nullptr, 10);
26493e2932fSMatt Spinler         if (num == 0)
26593e2932fSMatt Spinler         {
2664f460319SMatt Spinler             lg2::error(
2674f460319SMatt Spinler                 "Invalid symptom ID field {FIELD} in message registry, error name = {ERROR}",
2684f460319SMatt Spinler                 "FIELD", field, "ERROR", name);
26993e2932fSMatt Spinler 
27093e2932fSMatt Spinler             throw std::runtime_error("Invalid symptom ID in message registry");
27193e2932fSMatt Spinler         }
27293e2932fSMatt Spinler         symptomIDFields.push_back(num);
27393e2932fSMatt Spinler     }
27493e2932fSMatt Spinler     if (!symptomIDFields.empty())
27593e2932fSMatt Spinler     {
27693e2932fSMatt Spinler         return symptomIDFields;
27793e2932fSMatt Spinler     }
27893e2932fSMatt Spinler 
27993e2932fSMatt Spinler     return std::nullopt;
28093e2932fSMatt Spinler }
28193e2932fSMatt Spinler 
getComponentID(uint8_t srcType,uint16_t reasonCode,const nlohmann::json & pelEntry,const std::string & name)28293e2932fSMatt Spinler uint16_t getComponentID(uint8_t srcType, uint16_t reasonCode,
28393e2932fSMatt Spinler                         const nlohmann::json& pelEntry, const std::string& name)
28493e2932fSMatt Spinler {
28593e2932fSMatt Spinler     uint16_t id = 0;
28693e2932fSMatt Spinler 
28793e2932fSMatt Spinler     // If the ComponentID field is there, use that.  Otherwise, if it's a
28893e2932fSMatt Spinler     // 0xBD BMC error SRC, use the reasoncode.
2893ace0cf6SMatt Spinler     if (pelEntry.contains("ComponentID"))
29093e2932fSMatt Spinler     {
29193e2932fSMatt Spinler         std::string componentID = pelEntry["ComponentID"];
29293e2932fSMatt Spinler         id = strtoul(componentID.c_str(), nullptr, 16);
29393e2932fSMatt Spinler     }
29493e2932fSMatt Spinler     else
29593e2932fSMatt Spinler     {
29693e2932fSMatt Spinler         // On BMC error SRCs (BD), can just get the component ID from
29793e2932fSMatt Spinler         // the first byte of the reason code.
29893e2932fSMatt Spinler         if (srcType == static_cast<uint8_t>(SRCType::bmcError))
29993e2932fSMatt Spinler         {
30093e2932fSMatt Spinler             id = reasonCode & 0xFF00;
30193e2932fSMatt Spinler         }
30293e2932fSMatt Spinler         else
30393e2932fSMatt Spinler         {
3044f460319SMatt Spinler             lg2::error(
3054f460319SMatt Spinler                 "Missing component ID field in message registry, error name = {ERROR}",
3064f460319SMatt Spinler                 "ERROR", name);
30793e2932fSMatt Spinler 
30893e2932fSMatt Spinler             throw std::runtime_error(
30993e2932fSMatt Spinler                 "Missing component ID field in message registry");
31093e2932fSMatt Spinler         }
31193e2932fSMatt Spinler     }
31293e2932fSMatt Spinler 
31393e2932fSMatt Spinler     return id;
31493e2932fSMatt Spinler }
31593e2932fSMatt Spinler 
3166b427cc8SMatt Spinler /**
3176b427cc8SMatt Spinler  * @brief Says if the JSON is the format that contains AdditionalData keys
3186b427cc8SMatt Spinler  *        as in index into them.
3196b427cc8SMatt Spinler  *
3206b427cc8SMatt Spinler  * @param[in] json - The highest level callout JSON
3216b427cc8SMatt Spinler  *
3226b427cc8SMatt Spinler  * @return bool - If it is the AdditionalData format or not
3236b427cc8SMatt Spinler  */
calloutUsesAdditionalData(const nlohmann::json & json)3246b427cc8SMatt Spinler bool calloutUsesAdditionalData(const nlohmann::json& json)
3256b427cc8SMatt Spinler {
3266b427cc8SMatt Spinler     return (json.contains("ADName") &&
3276b427cc8SMatt Spinler             json.contains("CalloutsWithTheirADValues"));
3286b427cc8SMatt Spinler }
3296b427cc8SMatt Spinler 
3306b427cc8SMatt Spinler /**
3316b427cc8SMatt Spinler  * @brief Finds the callouts to use when there is no AdditionalData,
3326b427cc8SMatt Spinler  *        but the system type may be used as a key.
3336b427cc8SMatt Spinler  *
33415370292SArya K Padman  * A sample calloutList array looks like the following.  The System and Systems
33515370292SArya K Padman  * key are optional.
33615370292SArya K Padman  *
33715370292SArya K Padman  * System key - Value of the key will be the system name as a string. The
33815370292SArya K Padman  * callouts for a specific system can define under this key.
33915370292SArya K Padman  *
34015370292SArya K Padman  * Systems key - Value of the key will be an array of system names in the form
34115370292SArya K Padman  * of string. The callouts common to the systems mentioned in the array can
34215370292SArya K Padman  * define under this key.
34315370292SArya K Padman  *
34415370292SArya K Padman  * If both System and Systems not present it means that entry applies to every
34515370292SArya K Padman  * configuration that doesn't have another entry with a matching System and
34615370292SArya K Padman  * Systems key.
3476b427cc8SMatt Spinler  *
3486b427cc8SMatt Spinler  *    {
3496b427cc8SMatt Spinler  *        "System": "system1",
3506b427cc8SMatt Spinler  *        "CalloutList":
3516b427cc8SMatt Spinler  *        [
3526b427cc8SMatt Spinler  *            {
3536b427cc8SMatt Spinler  *                "Priority": "high",
3546b427cc8SMatt Spinler  *                "LocCode": "P1-C1"
3556b427cc8SMatt Spinler  *            },
3566b427cc8SMatt Spinler  *            {
3576b427cc8SMatt Spinler  *                "Priority": "low",
3586b427cc8SMatt Spinler  *                "LocCode": "P1"
3596b427cc8SMatt Spinler  *            }
3606b427cc8SMatt Spinler  *        ]
36115370292SArya K Padman  *    },
36215370292SArya K Padman  *    {
36315370292SArya K Padman  *        "Systems": ["system1", 'system2"],
36415370292SArya K Padman  *        "CalloutList":
36515370292SArya K Padman  *        [
36615370292SArya K Padman  *            {
36715370292SArya K Padman  *                "Priority": "high",
36815370292SArya K Padman  *                "LocCode": "P0-C1"
36915370292SArya K Padman  *            },
37015370292SArya K Padman  *            {
37115370292SArya K Padman  *                "Priority": "low",
37215370292SArya K Padman  *                "LocCode": "P0"
3736b427cc8SMatt Spinler  *            }
37415370292SArya K Padman  *        ]
37515370292SArya K Padman  *    }
37615370292SArya K Padman  *
37715370292SArya K Padman  * @param[in] json - The callout JSON
37815370292SArya K Padman  * @param[in] systemNames - List of compatible system type names
37915370292SArya K Padman  * @param[out] calloutLists - The JSON array which will hold the calloutlist to
38015370292SArya K Padman  * use specific to the system.
38115370292SArya K Padman  *
38215370292SArya K Padman  * @return - Throws runtime exception if json is not an array or if calloutLists
38315370292SArya K Padman  *           is empty.
3846b427cc8SMatt Spinler  */
findCalloutList(const nlohmann::json & json,const std::vector<std::string> & systemNames,nlohmann::json & calloutLists)38515370292SArya K Padman static void findCalloutList(const nlohmann::json& json,
38615370292SArya K Padman                             const std::vector<std::string>& systemNames,
38715370292SArya K Padman                             nlohmann::json& calloutLists)
3886b427cc8SMatt Spinler {
3896b427cc8SMatt Spinler     if (!json.is_array())
3906b427cc8SMatt Spinler     {
3916b427cc8SMatt Spinler         throw std::runtime_error{"findCalloutList was not passed a JSON array"};
3926b427cc8SMatt Spinler     }
3936b427cc8SMatt Spinler 
39415370292SArya K Padman     // Flag to indicate whether system specific callouts found or not
39515370292SArya K Padman     bool foundCallouts = false;
39615370292SArya K Padman 
39715370292SArya K Padman     for (const auto& callouts : json)
3986b427cc8SMatt Spinler     {
39915370292SArya K Padman         if (callouts.contains("System"))
4006b427cc8SMatt Spinler         {
40115370292SArya K Padman             if (std::ranges::find(systemNames,
40215370292SArya K Padman                                   callouts["System"].get<std::string>()) !=
4036ea4d5f7SMatt Spinler                 systemNames.end())
4046b427cc8SMatt Spinler             {
40515370292SArya K Padman                 calloutLists.insert(calloutLists.end(),
40615370292SArya K Padman                                     callouts["CalloutList"].begin(),
40715370292SArya K Padman                                     callouts["CalloutList"].end());
40815370292SArya K Padman                 foundCallouts = true;
4096b427cc8SMatt Spinler             }
41015370292SArya K Padman             continue;
4116b427cc8SMatt Spinler         }
4126b427cc8SMatt Spinler 
41315370292SArya K Padman         if (callouts.contains("Systems"))
41415370292SArya K Padman         {
41515370292SArya K Padman             std::vector<std::string> systems =
41615370292SArya K Padman                 callouts["Systems"].get<std::vector<std::string>>();
41715370292SArya K Padman             auto inSystemNames = [systemNames](const auto& system) {
41815370292SArya K Padman                 return (std::ranges::find(systemNames, system) !=
41915370292SArya K Padman                         systemNames.end());
42015370292SArya K Padman             };
42115370292SArya K Padman             if (std::ranges::any_of(systems, inSystemNames))
42215370292SArya K Padman             {
42315370292SArya K Padman                 calloutLists.insert(calloutLists.end(),
42415370292SArya K Padman                                     callouts["CalloutList"].begin(),
42515370292SArya K Padman                                     callouts["CalloutList"].end());
42615370292SArya K Padman                 foundCallouts = true;
42715370292SArya K Padman             }
42815370292SArya K Padman             continue;
42915370292SArya K Padman         }
43015370292SArya K Padman 
43115370292SArya K Padman         // Any entry if neither System/Systems key matches with system name
43215370292SArya K Padman         if (!foundCallouts)
43315370292SArya K Padman         {
43415370292SArya K Padman             calloutLists.insert(calloutLists.end(),
43515370292SArya K Padman                                 callouts["CalloutList"].begin(),
43615370292SArya K Padman                                 callouts["CalloutList"].end());
43715370292SArya K Padman         }
43815370292SArya K Padman     }
43915370292SArya K Padman     if (calloutLists.empty())
4406b427cc8SMatt Spinler     {
4416ea4d5f7SMatt Spinler         std::string types;
4426ea4d5f7SMatt Spinler         std::for_each(systemNames.begin(), systemNames.end(),
4436ea4d5f7SMatt Spinler                       [&types](const auto& t) { types += t + '|'; });
4444f460319SMatt Spinler         lg2::warning(
4456ea4d5f7SMatt Spinler             "No matching system name entry or default system name entry "
4464f460319SMatt Spinler             " for PEL callout list, names = {TYPES}",
4474f460319SMatt Spinler             "TYPES", types);
4486b427cc8SMatt Spinler 
4496b427cc8SMatt Spinler         throw std::runtime_error{
4506ea4d5f7SMatt Spinler             "Could not find a CalloutList JSON for this error and system name"};
4516b427cc8SMatt Spinler     }
4526b427cc8SMatt Spinler }
4536b427cc8SMatt Spinler 
4546b427cc8SMatt Spinler /**
4556b427cc8SMatt Spinler  * @brief Creates a RegistryCallout based on the input JSON.
4566b427cc8SMatt Spinler  *
4576b427cc8SMatt Spinler  * The JSON looks like:
4586b427cc8SMatt Spinler  *     {
4596b427cc8SMatt Spinler  *          "Priority": "high",
4606b427cc8SMatt Spinler  *          "LocCode": "E1"
4616b427cc8SMatt Spinler  *          ...
4626b427cc8SMatt Spinler  *     }
4636b427cc8SMatt Spinler  *
4646b427cc8SMatt Spinler  * Schema validation enforces what keys are present.
4656b427cc8SMatt Spinler  *
4666b427cc8SMatt Spinler  * @param[in] json - The JSON dictionary entry for a callout
4676b427cc8SMatt Spinler  *
4686b427cc8SMatt Spinler  * @return RegistryCallout - A filled in RegistryCallout
4696b427cc8SMatt Spinler  */
makeRegistryCallout(const nlohmann::json & json)4706b427cc8SMatt Spinler RegistryCallout makeRegistryCallout(const nlohmann::json& json)
4716b427cc8SMatt Spinler {
4726b427cc8SMatt Spinler     RegistryCallout callout;
4736b427cc8SMatt Spinler 
4746b427cc8SMatt Spinler     callout.priority = "high";
475f00f9d0fSMatt Spinler     callout.useInventoryLocCode = false;
4766b427cc8SMatt Spinler 
4776b427cc8SMatt Spinler     if (json.contains("Priority"))
4786b427cc8SMatt Spinler     {
4796b427cc8SMatt Spinler         callout.priority = json["Priority"].get<std::string>();
4806b427cc8SMatt Spinler     }
4816b427cc8SMatt Spinler 
4826b427cc8SMatt Spinler     if (json.contains("LocCode"))
4836b427cc8SMatt Spinler     {
4846b427cc8SMatt Spinler         callout.locCode = json["LocCode"].get<std::string>();
4856b427cc8SMatt Spinler     }
4866b427cc8SMatt Spinler 
4876b427cc8SMatt Spinler     if (json.contains("Procedure"))
4886b427cc8SMatt Spinler     {
4896b427cc8SMatt Spinler         callout.procedure = json["Procedure"].get<std::string>();
4906b427cc8SMatt Spinler     }
4916b427cc8SMatt Spinler     else if (json.contains("SymbolicFRU"))
4926b427cc8SMatt Spinler     {
4936b427cc8SMatt Spinler         callout.symbolicFRU = json["SymbolicFRU"].get<std::string>();
4946b427cc8SMatt Spinler     }
4956b427cc8SMatt Spinler     else if (json.contains("SymbolicFRUTrusted"))
4966b427cc8SMatt Spinler     {
4976b427cc8SMatt Spinler         callout.symbolicFRUTrusted =
4986b427cc8SMatt Spinler             json["SymbolicFRUTrusted"].get<std::string>();
4996b427cc8SMatt Spinler     }
5006b427cc8SMatt Spinler 
501f00f9d0fSMatt Spinler     if (json.contains("UseInventoryLocCode"))
502f00f9d0fSMatt Spinler     {
503f00f9d0fSMatt Spinler         callout.useInventoryLocCode = json["UseInventoryLocCode"].get<bool>();
504f00f9d0fSMatt Spinler     }
505f00f9d0fSMatt Spinler 
5066b427cc8SMatt Spinler     return callout;
5076b427cc8SMatt Spinler }
5086b427cc8SMatt Spinler 
5096b427cc8SMatt Spinler /**
5106b427cc8SMatt Spinler  * @brief Returns the callouts to use when an AdditionalData key is
5116b427cc8SMatt Spinler  *        required to find the correct entries.
5126b427cc8SMatt Spinler  *
5136b427cc8SMatt Spinler  *       The System property is used to find which CalloutList to use.
5146b427cc8SMatt Spinler  *       If System is missing, then that CalloutList is valid for
5156b427cc8SMatt Spinler  *       everything.
5166b427cc8SMatt Spinler  *
5176b427cc8SMatt Spinler  * The JSON looks like:
5186b427cc8SMatt Spinler  *    {
51915370292SArya K Padman  *        "System": "system1",
5206b427cc8SMatt Spinler  *        "CalloutList":
5216b427cc8SMatt Spinler  *        [
5226b427cc8SMatt Spinler  *            {
5236b427cc8SMatt Spinler  *                "Priority": "high",
52415370292SArya K Padman  *                "LocCode": "P1-C1"
52515370292SArya K Padman  *            },
52615370292SArya K Padman  *            {
52715370292SArya K Padman  *                "Priority": "low",
52815370292SArya K Padman  *                "LocCode": "P1"
52915370292SArya K Padman  *            }
53015370292SArya K Padman  *        ]
53115370292SArya K Padman  *    },
53215370292SArya K Padman  *    {
53315370292SArya K Padman  *        "Systems": ["system1", 'system2"],
53415370292SArya K Padman  *        "CalloutList":
53515370292SArya K Padman  *        [
53615370292SArya K Padman  *            {
53715370292SArya K Padman  *                "Priority": "high",
53815370292SArya K Padman  *                "LocCode": "P0-C1"
53915370292SArya K Padman  *            },
54015370292SArya K Padman  *            {
54115370292SArya K Padman  *                "Priority": "low",
54215370292SArya K Padman  *                "LocCode": "P0"
5436b427cc8SMatt Spinler  *            }
5446b427cc8SMatt Spinler  *        ]
5456b427cc8SMatt Spinler  *    }
5466b427cc8SMatt Spinler  *
5476b427cc8SMatt Spinler  * @param[in] json - The callout JSON
5486ea4d5f7SMatt Spinler  * @param[in] systemNames - List of compatible system type names
5496b427cc8SMatt Spinler  *
5506b427cc8SMatt Spinler  * @return std::vector<RegistryCallout> - The callouts to use
5516b427cc8SMatt Spinler  */
getCalloutsWithoutAD(const nlohmann::json & json,const std::vector<std::string> & systemNames)552*075c7923SPatrick Williams std::vector<RegistryCallout> getCalloutsWithoutAD(
553*075c7923SPatrick Williams     const nlohmann::json& json, const std::vector<std::string>& systemNames)
5546b427cc8SMatt Spinler {
5556b427cc8SMatt Spinler     std::vector<RegistryCallout> calloutEntries;
5566b427cc8SMatt Spinler 
55715370292SArya K Padman     nlohmann::json calloutLists = nlohmann::json::array();
55815370292SArya K Padman 
5596b427cc8SMatt Spinler     // Find the CalloutList to use based on the system type
56015370292SArya K Padman     findCalloutList(json, systemNames, calloutLists);
5616b427cc8SMatt Spinler 
5626b427cc8SMatt Spinler     // We finally found the callouts, make the objects.
56315370292SArya K Padman     for (const auto& callout : calloutLists)
5646b427cc8SMatt Spinler     {
5656b427cc8SMatt Spinler         calloutEntries.push_back(std::move(makeRegistryCallout(callout)));
5666b427cc8SMatt Spinler     }
5676b427cc8SMatt Spinler 
5686b427cc8SMatt Spinler     return calloutEntries;
5696b427cc8SMatt Spinler }
5706b427cc8SMatt Spinler 
5716b427cc8SMatt Spinler /**
5726b427cc8SMatt Spinler  * @brief Returns the callouts to use when an AdditionalData key is
5736b427cc8SMatt Spinler  *        required to find the correct entries.
5746b427cc8SMatt Spinler  *
5756b427cc8SMatt Spinler  * The JSON looks like:
5766b427cc8SMatt Spinler  *    {
5776b427cc8SMatt Spinler  *        "ADName": "PROC_NUM",
5786b427cc8SMatt Spinler  *        "CalloutsWithTheirADValues":
5796b427cc8SMatt Spinler  *        [
5806b427cc8SMatt Spinler  *            {
5816b427cc8SMatt Spinler  *                "ADValue": "0",
5826b427cc8SMatt Spinler  *                "Callouts":
5836b427cc8SMatt Spinler  *                [
5846b427cc8SMatt Spinler  *                    {
5856b427cc8SMatt Spinler  *                        "CalloutList":
5866b427cc8SMatt Spinler  *                        [
5876b427cc8SMatt Spinler  *                            {
5886b427cc8SMatt Spinler  *                                "Priority": "high",
5896b427cc8SMatt Spinler  *                                "LocCode": "P1-C5"
5906b427cc8SMatt Spinler  *                            }
5916b427cc8SMatt Spinler  *                        ]
5926b427cc8SMatt Spinler  *                    }
5936b427cc8SMatt Spinler  *                ]
5946b427cc8SMatt Spinler  *            }
5956b427cc8SMatt Spinler  *        ]
5966b427cc8SMatt Spinler  *     }
5976b427cc8SMatt Spinler  *
5986b427cc8SMatt Spinler  * Note that the "Callouts" entry above is the same as the top level
5996b427cc8SMatt Spinler  * entry used when there is no AdditionalData key.
6006b427cc8SMatt Spinler  *
6016b427cc8SMatt Spinler  * @param[in] json - The callout JSON
6026ea4d5f7SMatt Spinler  * @param[in] systemNames - List of compatible system type names
6036b427cc8SMatt Spinler  * @param[in] additionalData - The AdditionalData property
6046b427cc8SMatt Spinler  *
6056b427cc8SMatt Spinler  * @return std::vector<RegistryCallout> - The callouts to use
6066b427cc8SMatt Spinler  */
getCalloutsUsingAD(const nlohmann::json & json,const std::vector<std::string> & systemNames,const AdditionalData & additionalData)607*075c7923SPatrick Williams std::vector<RegistryCallout> getCalloutsUsingAD(
608*075c7923SPatrick Williams     const nlohmann::json& json, const std::vector<std::string>& systemNames,
6096b427cc8SMatt Spinler     const AdditionalData& additionalData)
6106b427cc8SMatt Spinler {
6116b427cc8SMatt Spinler     // This indicates which AD field we'll be using
6126b427cc8SMatt Spinler     auto keyName = json["ADName"].get<std::string>();
6136b427cc8SMatt Spinler 
6146b427cc8SMatt Spinler     // Get the actual value from the AD data
6156b427cc8SMatt Spinler     auto adValue = additionalData.getValue(keyName);
6166b427cc8SMatt Spinler 
6176b427cc8SMatt Spinler     if (!adValue)
6186b427cc8SMatt Spinler     {
6196b427cc8SMatt Spinler         // The AdditionalData did not contain the necessary key
6204f460319SMatt Spinler         lg2::warning("The PEL message registry callouts JSON "
6216b427cc8SMatt Spinler                      "said to use an AdditionalData key that isn't in the "
6224f460319SMatt Spinler                      "AdditionalData event log property, key = {KEY}",
6234f460319SMatt Spinler                      "KEY", keyName);
6246b427cc8SMatt Spinler         throw std::runtime_error{
6256b427cc8SMatt Spinler             "Missing AdditionalData entry for this callout"};
6266b427cc8SMatt Spinler     }
6276b427cc8SMatt Spinler 
6286b427cc8SMatt Spinler     const auto& callouts = json["CalloutsWithTheirADValues"];
6296b427cc8SMatt Spinler 
6306b427cc8SMatt Spinler     // find the entry with that AD value
631*075c7923SPatrick Williams     auto it = std::find_if(
632*075c7923SPatrick Williams         callouts.begin(), callouts.end(), [adValue](const nlohmann::json& j) {
6336b427cc8SMatt Spinler             return *adValue == j["ADValue"].get<std::string>();
6346b427cc8SMatt Spinler         });
6356b427cc8SMatt Spinler 
6366b427cc8SMatt Spinler     if (it == callouts.end())
6376b427cc8SMatt Spinler     {
638f397afccSMatt Spinler         // This can happen if not all possible values were in the
6393d923311SMatt Spinler         // message registry and that's fine.  There may be a
6403d923311SMatt Spinler         // "CalloutsWhenNoADMatch" section that contains callouts
6413d923311SMatt Spinler         // to use in this case.
6423d923311SMatt Spinler         if (json.contains("CalloutsWhenNoADMatch"))
6433d923311SMatt Spinler         {
6443d923311SMatt Spinler             return getCalloutsWithoutAD(json["CalloutsWhenNoADMatch"],
6453d923311SMatt Spinler                                         systemNames);
6463d923311SMatt Spinler         }
647f397afccSMatt Spinler         return std::vector<RegistryCallout>{};
6486b427cc8SMatt Spinler     }
6496b427cc8SMatt Spinler 
6506b427cc8SMatt Spinler     // Proceed to find the callouts possibly based on system type.
6516ea4d5f7SMatt Spinler     return getCalloutsWithoutAD((*it)["Callouts"], systemNames);
6526b427cc8SMatt Spinler }
6536b427cc8SMatt Spinler 
654711f1129SMatt Spinler /**
655711f1129SMatt Spinler  * @brief Returns the journal capture information
656711f1129SMatt Spinler  *
657711f1129SMatt Spinler  *  The JSON looks like:
658711f1129SMatt Spinler  *    "JournalCapture": {
659711f1129SMatt Spinler  *        "NumLines": 30
660711f1129SMatt Spinler  *    }
661711f1129SMatt Spinler  *
662711f1129SMatt Spinler  *    "JournalCapture":
663711f1129SMatt Spinler  *    {
664711f1129SMatt Spinler  *        "Sections": [
665711f1129SMatt Spinler  *            {
666711f1129SMatt Spinler  *                "SyslogID": "phosphor-log-manager",
667711f1129SMatt Spinler  *                "NumLines": 20
668711f1129SMatt Spinler  *            }
669711f1129SMatt Spinler  *        ]
670711f1129SMatt Spinler  *    }
671711f1129SMatt Spinler  *
672711f1129SMatt Spinler  * @param json - The journal capture JSON
673711f1129SMatt Spinler  * @return JournalCapture - The filled in variant
674711f1129SMatt Spinler  */
getJournalCapture(const nlohmann::json & json)675711f1129SMatt Spinler JournalCapture getJournalCapture(const nlohmann::json& json)
676711f1129SMatt Spinler {
677711f1129SMatt Spinler     JournalCapture capt;
678711f1129SMatt Spinler 
679711f1129SMatt Spinler     // Primary key is either NumLines or Sections.
680711f1129SMatt Spinler     if (json.contains("NumLines"))
681711f1129SMatt Spinler     {
682711f1129SMatt Spinler         capt = json.at("NumLines").get<size_t>();
683711f1129SMatt Spinler     }
684711f1129SMatt Spinler     else if (json.contains("Sections"))
685711f1129SMatt Spinler     {
686711f1129SMatt Spinler         AppCaptureList captures;
687711f1129SMatt Spinler         for (const auto& capture : json.at("Sections"))
688711f1129SMatt Spinler         {
689711f1129SMatt Spinler             AppCapture ac;
690711f1129SMatt Spinler             ac.syslogID = capture.at("SyslogID").get<std::string>();
691711f1129SMatt Spinler             ac.numLines = capture.at("NumLines").get<size_t>();
692711f1129SMatt Spinler             captures.push_back(std::move(ac));
693711f1129SMatt Spinler         }
694711f1129SMatt Spinler 
695711f1129SMatt Spinler         capt = captures;
696711f1129SMatt Spinler     }
697711f1129SMatt Spinler     else
698711f1129SMatt Spinler     {
6994f460319SMatt Spinler         lg2::error("JournalCapture section not the right format");
700711f1129SMatt Spinler         throw std::runtime_error{"JournalCapture section not the right format"};
701711f1129SMatt Spinler     }
702711f1129SMatt Spinler 
703711f1129SMatt Spinler     return capt;
704711f1129SMatt Spinler }
705711f1129SMatt Spinler 
706367144cfSMatt Spinler } // namespace helper
707367144cfSMatt Spinler 
lookup(const std::string & name,LookupType type,bool toCache)7080f717e10SHarisuddin Mohamed Isa std::optional<Entry> Registry::lookup(const std::string& name, LookupType type,
7090f717e10SHarisuddin Mohamed Isa                                       bool toCache)
710367144cfSMatt Spinler {
7110f717e10SHarisuddin Mohamed Isa     std::optional<nlohmann::json> registryTmp;
7120f717e10SHarisuddin Mohamed Isa     auto& registryOpt = (_registry) ? _registry : registryTmp;
7130f717e10SHarisuddin Mohamed Isa     if (!registryOpt)
714367144cfSMatt Spinler     {
7150f717e10SHarisuddin Mohamed Isa         registryOpt = readRegistry(_registryFile);
7160f717e10SHarisuddin Mohamed Isa         if (!registryOpt)
717367144cfSMatt Spinler         {
718367144cfSMatt Spinler             return std::nullopt;
719367144cfSMatt Spinler         }
7200f717e10SHarisuddin Mohamed Isa         else if (toCache)
7210f717e10SHarisuddin Mohamed Isa         {
7220f717e10SHarisuddin Mohamed Isa             // Save message registry in memory for peltool
7230f717e10SHarisuddin Mohamed Isa             _registry = std::move(registryTmp);
7240f717e10SHarisuddin Mohamed Isa         }
7250f717e10SHarisuddin Mohamed Isa     }
7260f717e10SHarisuddin Mohamed Isa     auto& reg = (_registry) ? _registry : registryTmp;
7270f717e10SHarisuddin Mohamed Isa     const auto& registry = reg.value();
728367144cfSMatt Spinler     // Find an entry with this name in the PEL array.
729*075c7923SPatrick Williams     auto e = std::find_if(
730*075c7923SPatrick Williams         registry["PELs"].begin(), registry["PELs"].end(),
73181bc5611SMatt Spinler         [&name, &type](const nlohmann::json& j) {
73281bc5611SMatt Spinler             return ((name == j.at("Name").get<std::string>() &&
73381bc5611SMatt Spinler                      type == LookupType::name) ||
73481bc5611SMatt Spinler                     (name == j.at("SRC").at("ReasonCode").get<std::string>() &&
73581bc5611SMatt Spinler                      type == LookupType::reasonCode));
7360f717e10SHarisuddin Mohamed Isa         });
737367144cfSMatt Spinler 
738367144cfSMatt Spinler     if (e != registry["PELs"].end())
739367144cfSMatt Spinler     {
740367144cfSMatt Spinler         // Fill in the Entry structure from the JSON.  Most, but not all, fields
741367144cfSMatt Spinler         // are optional.
742367144cfSMatt Spinler 
743367144cfSMatt Spinler         try
744367144cfSMatt Spinler         {
745367144cfSMatt Spinler             Entry entry;
746367144cfSMatt Spinler             entry.name = (*e)["Name"];
74723970b0dSMatt Spinler 
74823970b0dSMatt Spinler             if (e->contains("Subsystem"))
74923970b0dSMatt Spinler             {
750367144cfSMatt Spinler                 entry.subsystem = helper::getSubsystem((*e)["Subsystem"]);
75123970b0dSMatt Spinler             }
752e07f915bSMatt Spinler 
7533ace0cf6SMatt Spinler             if (e->contains("ActionFlags"))
754e07f915bSMatt Spinler             {
755367144cfSMatt Spinler                 entry.actionFlags = helper::getActionFlags((*e)["ActionFlags"]);
756e07f915bSMatt Spinler             }
757367144cfSMatt Spinler 
7583ace0cf6SMatt Spinler             if (e->contains("MfgActionFlags"))
759367144cfSMatt Spinler             {
760367144cfSMatt Spinler                 entry.mfgActionFlags =
761367144cfSMatt Spinler                     helper::getActionFlags((*e)["MfgActionFlags"]);
762367144cfSMatt Spinler             }
763367144cfSMatt Spinler 
7643ace0cf6SMatt Spinler             if (e->contains("Severity"))
765367144cfSMatt Spinler             {
766aadccc85SMatt Spinler                 entry.severity = helper::getSeverities((*e)["Severity"]);
767367144cfSMatt Spinler             }
768367144cfSMatt Spinler 
7693ace0cf6SMatt Spinler             if (e->contains("MfgSeverity"))
770367144cfSMatt Spinler             {
771aadccc85SMatt Spinler                 entry.mfgSeverity = helper::getSeverities((*e)["MfgSeverity"]);
772367144cfSMatt Spinler             }
773367144cfSMatt Spinler 
7743ace0cf6SMatt Spinler             if (e->contains("EventType"))
775367144cfSMatt Spinler             {
776367144cfSMatt Spinler                 entry.eventType = helper::getEventType((*e)["EventType"]);
777367144cfSMatt Spinler             }
778367144cfSMatt Spinler 
7793ace0cf6SMatt Spinler             if (e->contains("EventScope"))
780367144cfSMatt Spinler             {
781367144cfSMatt Spinler                 entry.eventScope = helper::getEventScope((*e)["EventScope"]);
782367144cfSMatt Spinler             }
783367144cfSMatt Spinler 
78493e2932fSMatt Spinler             auto& src = (*e)["SRC"];
78593e2932fSMatt Spinler             entry.src.reasonCode = helper::getSRCReasonCode(src, name);
78693e2932fSMatt Spinler 
7873ace0cf6SMatt Spinler             if (src.contains("Type"))
78893e2932fSMatt Spinler             {
78993e2932fSMatt Spinler                 entry.src.type = helper::getSRCType(src, name);
79093e2932fSMatt Spinler             }
79193e2932fSMatt Spinler             else
79293e2932fSMatt Spinler             {
79393e2932fSMatt Spinler                 entry.src.type = static_cast<uint8_t>(SRCType::bmcError);
79493e2932fSMatt Spinler             }
79593e2932fSMatt Spinler 
79693e2932fSMatt Spinler             // Now that we know the SRC type and reason code,
79793e2932fSMatt Spinler             // we can get the component ID.
79893e2932fSMatt Spinler             entry.componentID = helper::getComponentID(
79993e2932fSMatt Spinler                 entry.src.type, entry.src.reasonCode, *e, name);
80093e2932fSMatt Spinler 
8013ace0cf6SMatt Spinler             if (src.contains("Words6To9"))
80293e2932fSMatt Spinler             {
803*075c7923SPatrick Williams                 entry.src.hexwordADFields =
804*075c7923SPatrick Williams                     helper::getSRCHexwordFields(src, name);
80593e2932fSMatt Spinler             }
80693e2932fSMatt Spinler 
8073ace0cf6SMatt Spinler             if (src.contains("SymptomIDFields"))
80893e2932fSMatt Spinler             {
80993e2932fSMatt Spinler                 entry.src.symptomID = helper::getSRCSymptomIDFields(src, name);
81093e2932fSMatt Spinler             }
81193e2932fSMatt Spinler 
8123fe93e96SMatt Spinler             if (src.contains("DeconfigFlag"))
8133fe93e96SMatt Spinler             {
8143fe93e96SMatt Spinler                 entry.src.deconfigFlag = helper::getSRCDeconfigFlag(src);
8153fe93e96SMatt Spinler             }
8163fe93e96SMatt Spinler 
817da5b76b2SMatt Spinler             if (src.contains("CheckstopFlag"))
818da5b76b2SMatt Spinler             {
819da5b76b2SMatt Spinler                 entry.src.checkstopFlag = helper::getSRCCheckstopFlag(src);
820da5b76b2SMatt Spinler             }
821da5b76b2SMatt Spinler 
8220f717e10SHarisuddin Mohamed Isa             auto& doc = (*e)["Documentation"];
8230f717e10SHarisuddin Mohamed Isa             entry.doc.message = doc["Message"];
8240f717e10SHarisuddin Mohamed Isa             entry.doc.description = doc["Description"];
8253ace0cf6SMatt Spinler             if (doc.contains("MessageArgSources"))
8260f717e10SHarisuddin Mohamed Isa             {
8273bb15b9bSMatt Spinler                 entry.doc.messageArgSources = doc["MessageArgSources"];
8280f717e10SHarisuddin Mohamed Isa             }
8290f717e10SHarisuddin Mohamed Isa 
830d8e29000SMatt Spinler             // If there are callouts defined, save the JSON for later
831d8e29000SMatt Spinler             if (_loadCallouts)
832d8e29000SMatt Spinler             {
833d8e29000SMatt Spinler                 if (e->contains("Callouts"))
834d8e29000SMatt Spinler                 {
835d8e29000SMatt Spinler                     entry.callouts = (*e)["Callouts"];
836d8e29000SMatt Spinler                 }
837d8e29000SMatt Spinler                 else if (e->contains("CalloutsUsingAD"))
838d8e29000SMatt Spinler                 {
839d8e29000SMatt Spinler                     entry.callouts = (*e)["CalloutsUsingAD"];
840d8e29000SMatt Spinler                 }
841d8e29000SMatt Spinler             }
842d8e29000SMatt Spinler 
843711f1129SMatt Spinler             if (e->contains("JournalCapture"))
844711f1129SMatt Spinler             {
845711f1129SMatt Spinler                 entry.journalCapture =
846711f1129SMatt Spinler                     helper::getJournalCapture((*e)["JournalCapture"]);
847711f1129SMatt Spinler             }
848711f1129SMatt Spinler 
849367144cfSMatt Spinler             return entry;
850367144cfSMatt Spinler         }
85145796e82SMatt Spinler         catch (const std::exception& ex)
852367144cfSMatt Spinler         {
8534f460319SMatt Spinler             lg2::error("Found invalid message registry field. Error: {ERROR}",
8544f460319SMatt Spinler                        "ERROR", ex);
855367144cfSMatt Spinler         }
856367144cfSMatt Spinler     }
857367144cfSMatt Spinler 
858367144cfSMatt Spinler     return std::nullopt;
859367144cfSMatt Spinler }
860367144cfSMatt Spinler 
8610f717e10SHarisuddin Mohamed Isa std::optional<nlohmann::json>
readRegistry(const std::filesystem::path & registryFile)8620f717e10SHarisuddin Mohamed Isa     Registry::readRegistry(const std::filesystem::path& registryFile)
8630f717e10SHarisuddin Mohamed Isa {
8640f717e10SHarisuddin Mohamed Isa     // Look in /etc first in case someone put a test file there
8650f717e10SHarisuddin Mohamed Isa     fs::path debugFile{fs::path{debugFilePath} / registryFileName};
8660f717e10SHarisuddin Mohamed Isa     nlohmann::json registry;
8670f717e10SHarisuddin Mohamed Isa     std::ifstream file;
8680f717e10SHarisuddin Mohamed Isa 
8690f717e10SHarisuddin Mohamed Isa     if (fs::exists(debugFile))
8700f717e10SHarisuddin Mohamed Isa     {
8714f460319SMatt Spinler         lg2::info("Using debug PEL message registry");
8720f717e10SHarisuddin Mohamed Isa         file.open(debugFile);
8730f717e10SHarisuddin Mohamed Isa     }
8740f717e10SHarisuddin Mohamed Isa     else
8750f717e10SHarisuddin Mohamed Isa     {
8760f717e10SHarisuddin Mohamed Isa         file.open(registryFile);
8770f717e10SHarisuddin Mohamed Isa     }
8780f717e10SHarisuddin Mohamed Isa 
8790f717e10SHarisuddin Mohamed Isa     try
8800f717e10SHarisuddin Mohamed Isa     {
8810f717e10SHarisuddin Mohamed Isa         registry = nlohmann::json::parse(file);
8820f717e10SHarisuddin Mohamed Isa     }
88366491c61SPatrick Williams     catch (const std::exception& e)
8840f717e10SHarisuddin Mohamed Isa     {
8854f460319SMatt Spinler         lg2::error("Error parsing message registry JSON. Error: {ERROR}",
8864f460319SMatt Spinler                    "ERROR", e);
8870f717e10SHarisuddin Mohamed Isa         return std::nullopt;
8880f717e10SHarisuddin Mohamed Isa     }
8890f717e10SHarisuddin Mohamed Isa     return registry;
8900f717e10SHarisuddin Mohamed Isa }
8910f717e10SHarisuddin Mohamed Isa 
8926b427cc8SMatt Spinler std::vector<RegistryCallout>
getCallouts(const nlohmann::json & calloutJSON,const std::vector<std::string> & systemNames,const AdditionalData & additionalData)8936b427cc8SMatt Spinler     Registry::getCallouts(const nlohmann::json& calloutJSON,
8946ea4d5f7SMatt Spinler                           const std::vector<std::string>& systemNames,
8956b427cc8SMatt Spinler                           const AdditionalData& additionalData)
8966b427cc8SMatt Spinler {
8976b427cc8SMatt Spinler     // The JSON may either use an AdditionalData key
8986b427cc8SMatt Spinler     // as an index, or not.
8996b427cc8SMatt Spinler     if (helper::calloutUsesAdditionalData(calloutJSON))
9006b427cc8SMatt Spinler     {
9016ea4d5f7SMatt Spinler         return helper::getCalloutsUsingAD(calloutJSON, systemNames,
9026b427cc8SMatt Spinler                                           additionalData);
9036b427cc8SMatt Spinler     }
9046b427cc8SMatt Spinler 
9056ea4d5f7SMatt Spinler     return helper::getCalloutsWithoutAD(calloutJSON, systemNames);
9066b427cc8SMatt Spinler }
9076b427cc8SMatt Spinler 
908367144cfSMatt Spinler } // namespace message
909367144cfSMatt Spinler } // namespace pels
910367144cfSMatt Spinler } // namespace openpower
911