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