xref: /openbmc/phosphor-logging/extensions/openpower-pels/registry.cpp (revision 0f717e1063154f0baec62f80e043d4d1c3317ce0)
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 
18367144cfSMatt Spinler #include "pel_types.hpp"
19367144cfSMatt Spinler #include "pel_values.hpp"
20367144cfSMatt Spinler 
21367144cfSMatt Spinler #include <fstream>
22367144cfSMatt Spinler #include <phosphor-logging/log.hpp>
23367144cfSMatt Spinler 
24367144cfSMatt Spinler namespace openpower
25367144cfSMatt Spinler {
26367144cfSMatt Spinler namespace pels
27367144cfSMatt Spinler {
28367144cfSMatt Spinler namespace message
29367144cfSMatt Spinler {
30367144cfSMatt Spinler 
31367144cfSMatt Spinler namespace pv = pel_values;
32367144cfSMatt Spinler namespace fs = std::filesystem;
33367144cfSMatt Spinler using namespace phosphor::logging;
34367144cfSMatt Spinler 
35367144cfSMatt Spinler constexpr auto debugFilePath = "/etc/phosphor-logging/";
36367144cfSMatt Spinler 
37367144cfSMatt Spinler namespace helper
38367144cfSMatt Spinler {
39367144cfSMatt Spinler 
40367144cfSMatt Spinler uint8_t getSubsystem(const std::string& subsystemName)
41367144cfSMatt Spinler {
42367144cfSMatt Spinler     // Get the actual value to use in the PEL for the string name
43367144cfSMatt Spinler     auto ss = pv::findByName(subsystemName, pv::subsystemValues);
44367144cfSMatt Spinler     if (ss == pv::subsystemValues.end())
45367144cfSMatt Spinler     {
46367144cfSMatt Spinler         // Schema validation should be catching this.
47367144cfSMatt Spinler         log<level::ERR>("Invalid subsystem name used in message registry",
48367144cfSMatt Spinler                         entry("SUBSYSTEM=%s", subsystemName.c_str()));
49367144cfSMatt Spinler 
50367144cfSMatt Spinler         throw std::runtime_error("Invalid subsystem used in message registry");
51367144cfSMatt Spinler     }
52367144cfSMatt Spinler 
53367144cfSMatt Spinler     return std::get<pv::fieldValuePos>(*ss);
54367144cfSMatt Spinler }
55367144cfSMatt Spinler 
56367144cfSMatt Spinler uint8_t getSeverity(const std::string& severityName)
57367144cfSMatt Spinler {
58367144cfSMatt Spinler     auto s = pv::findByName(severityName, pv::severityValues);
59367144cfSMatt Spinler     if (s == pv::severityValues.end())
60367144cfSMatt Spinler     {
61367144cfSMatt Spinler         // Schema validation should be catching this.
62367144cfSMatt Spinler         log<level::ERR>("Invalid severity name used in message registry",
63367144cfSMatt Spinler                         entry("SEVERITY=%s", severityName.c_str()));
64367144cfSMatt Spinler 
65367144cfSMatt Spinler         throw std::runtime_error("Invalid severity used in message registry");
66367144cfSMatt Spinler     }
67367144cfSMatt Spinler 
68367144cfSMatt Spinler     return std::get<pv::fieldValuePos>(*s);
69367144cfSMatt Spinler }
70367144cfSMatt Spinler 
71367144cfSMatt Spinler uint16_t getActionFlags(const std::vector<std::string>& flags)
72367144cfSMatt Spinler {
73367144cfSMatt Spinler     uint16_t actionFlags = 0;
74367144cfSMatt Spinler 
75367144cfSMatt Spinler     // Make the bitmask based on the array of flag names
76367144cfSMatt Spinler     for (const auto& flag : flags)
77367144cfSMatt Spinler     {
78367144cfSMatt Spinler         auto s = pv::findByName(flag, pv::actionFlagsValues);
79367144cfSMatt Spinler         if (s == pv::actionFlagsValues.end())
80367144cfSMatt Spinler         {
81367144cfSMatt Spinler             // Schema validation should be catching this.
82367144cfSMatt Spinler             log<level::ERR>("Invalid action flag name used in message registry",
83367144cfSMatt Spinler                             entry("FLAG=%s", flag.c_str()));
84367144cfSMatt Spinler 
85367144cfSMatt Spinler             throw std::runtime_error(
86367144cfSMatt Spinler                 "Invalid action flag used in message registry");
87367144cfSMatt Spinler         }
88367144cfSMatt Spinler 
89367144cfSMatt Spinler         actionFlags |= std::get<pv::fieldValuePos>(*s);
90367144cfSMatt Spinler     }
91367144cfSMatt Spinler 
92367144cfSMatt Spinler     return actionFlags;
93367144cfSMatt Spinler }
94367144cfSMatt Spinler 
95367144cfSMatt Spinler uint8_t getEventType(const std::string& eventTypeName)
96367144cfSMatt Spinler {
97367144cfSMatt Spinler     auto t = pv::findByName(eventTypeName, pv::eventTypeValues);
98367144cfSMatt Spinler     if (t == pv::eventTypeValues.end())
99367144cfSMatt Spinler     {
100367144cfSMatt Spinler         log<level::ERR>("Invalid event type used in message registry",
101367144cfSMatt Spinler                         entry("EVENT_TYPE=%s", eventTypeName.c_str()));
102367144cfSMatt Spinler 
103367144cfSMatt Spinler         throw std::runtime_error("Invalid event type used in message registry");
104367144cfSMatt Spinler     }
105367144cfSMatt Spinler     return std::get<pv::fieldValuePos>(*t);
106367144cfSMatt Spinler }
107367144cfSMatt Spinler 
108367144cfSMatt Spinler uint8_t getEventScope(const std::string& eventScopeName)
109367144cfSMatt Spinler {
110367144cfSMatt Spinler     auto s = pv::findByName(eventScopeName, pv::eventScopeValues);
111367144cfSMatt Spinler     if (s == pv::eventScopeValues.end())
112367144cfSMatt Spinler     {
113367144cfSMatt Spinler         log<level::ERR>("Invalid event scope used in registry",
114367144cfSMatt Spinler                         entry("EVENT_SCOPE=%s", eventScopeName.c_str()));
115367144cfSMatt Spinler 
116367144cfSMatt Spinler         throw std::runtime_error(
117367144cfSMatt Spinler             "Invalid event scope used in message registry");
118367144cfSMatt Spinler     }
119367144cfSMatt Spinler     return std::get<pv::fieldValuePos>(*s);
120367144cfSMatt Spinler }
121367144cfSMatt Spinler 
12293e2932fSMatt Spinler uint16_t getSRCReasonCode(const nlohmann::json& src, const std::string& name)
12393e2932fSMatt Spinler {
12493e2932fSMatt Spinler     std::string rc = src["ReasonCode"];
12593e2932fSMatt Spinler     uint16_t reasonCode = strtoul(rc.c_str(), nullptr, 16);
12693e2932fSMatt Spinler     if (reasonCode == 0)
12793e2932fSMatt Spinler     {
12893e2932fSMatt Spinler         log<phosphor::logging::level::ERR>(
12993e2932fSMatt Spinler             "Invalid reason code in message registry",
13093e2932fSMatt Spinler             entry("ERROR_NAME=%s", name.c_str()),
13193e2932fSMatt Spinler             entry("REASON_CODE=%s", rc.c_str()));
13293e2932fSMatt Spinler 
13393e2932fSMatt Spinler         throw std::runtime_error("Invalid reason code in message registry");
13493e2932fSMatt Spinler     }
13593e2932fSMatt Spinler     return reasonCode;
13693e2932fSMatt Spinler }
13793e2932fSMatt Spinler 
13893e2932fSMatt Spinler uint8_t getSRCType(const nlohmann::json& src, const std::string& name)
13993e2932fSMatt Spinler {
14093e2932fSMatt Spinler     // Looks like: "22"
14193e2932fSMatt Spinler     std::string srcType = src["Type"];
14293e2932fSMatt Spinler     size_t type = strtoul(srcType.c_str(), nullptr, 16);
14393e2932fSMatt Spinler     if ((type == 0) || (srcType.size() != 2)) // 1 hex byte
14493e2932fSMatt Spinler     {
14593e2932fSMatt Spinler         log<phosphor::logging::level::ERR>(
14693e2932fSMatt Spinler             "Invalid SRC Type in message registry",
14793e2932fSMatt Spinler             entry("ERROR_NAME=%s", name.c_str()),
14893e2932fSMatt Spinler             entry("SRC_TYPE=%s", srcType.c_str()));
14993e2932fSMatt Spinler 
15093e2932fSMatt Spinler         throw std::runtime_error("Invalid SRC Type in message registry");
15193e2932fSMatt Spinler     }
15293e2932fSMatt Spinler 
15393e2932fSMatt Spinler     return type;
15493e2932fSMatt Spinler }
15593e2932fSMatt Spinler 
15693e2932fSMatt Spinler std::optional<std::map<SRC::WordNum, SRC::AdditionalDataField>>
15793e2932fSMatt Spinler     getSRCHexwordFields(const nlohmann::json& src, const std::string& name)
15893e2932fSMatt Spinler {
15993e2932fSMatt Spinler     std::map<SRC::WordNum, SRC::AdditionalDataField> hexwordFields;
16093e2932fSMatt Spinler 
16193e2932fSMatt Spinler     // Build the map of which AdditionalData fields to use for which SRC words
16293e2932fSMatt Spinler 
16393e2932fSMatt Spinler     // Like:
16493e2932fSMatt Spinler     // {
16593e2932fSMatt Spinler     //   "8":
16693e2932fSMatt Spinler     //   {
16793e2932fSMatt Spinler     //     "AdditionalDataPropSource": "TEST"
16893e2932fSMatt Spinler     //   }
16993e2932fSMatt Spinler     //
17093e2932fSMatt Spinler     // }
17193e2932fSMatt Spinler 
17293e2932fSMatt Spinler     for (const auto& word : src["Words6To9"].items())
17393e2932fSMatt Spinler     {
17493e2932fSMatt Spinler         std::string num = word.key();
17593e2932fSMatt Spinler         size_t wordNum = std::strtoul(num.c_str(), nullptr, 10);
17693e2932fSMatt Spinler 
17793e2932fSMatt Spinler         if (wordNum == 0)
17893e2932fSMatt Spinler         {
17993e2932fSMatt Spinler             log<phosphor::logging::level::ERR>(
18093e2932fSMatt Spinler                 "Invalid SRC word number in message registry",
18193e2932fSMatt Spinler                 entry("ERROR_NAME=%s", name.c_str()),
18293e2932fSMatt Spinler                 entry("SRC_WORD_NUM=%s", num.c_str()));
18393e2932fSMatt Spinler 
18493e2932fSMatt Spinler             throw std::runtime_error("Invalid SRC word in message registry");
18593e2932fSMatt Spinler         }
18693e2932fSMatt Spinler 
18793e2932fSMatt Spinler         auto attributes = word.value();
18893e2932fSMatt Spinler         std::string adPropName = attributes["AdditionalDataPropSource"];
18993e2932fSMatt Spinler         hexwordFields[wordNum] = std::move(adPropName);
19093e2932fSMatt Spinler     }
19193e2932fSMatt Spinler 
19293e2932fSMatt Spinler     if (!hexwordFields.empty())
19393e2932fSMatt Spinler     {
19493e2932fSMatt Spinler         return hexwordFields;
19593e2932fSMatt Spinler     }
19693e2932fSMatt Spinler 
19793e2932fSMatt Spinler     return std::nullopt;
19893e2932fSMatt Spinler }
19993e2932fSMatt Spinler std::optional<std::vector<SRC::WordNum>>
20093e2932fSMatt Spinler     getSRCSymptomIDFields(const nlohmann::json& src, const std::string& name)
20193e2932fSMatt Spinler {
20293e2932fSMatt Spinler     std::vector<SRC::WordNum> symptomIDFields;
20393e2932fSMatt Spinler 
20493e2932fSMatt Spinler     // Looks like:
20593e2932fSMatt Spinler     // "SymptomIDFields": ["SRCWord3", "SRCWord6"],
20693e2932fSMatt Spinler 
20793e2932fSMatt Spinler     for (const std::string& field : src["SymptomIDFields"])
20893e2932fSMatt Spinler     {
20993e2932fSMatt Spinler         // Just need the last digit off the end, e.g. SRCWord6.
21093e2932fSMatt Spinler         // The schema enforces the format of these.
21193e2932fSMatt Spinler         auto srcWordNum = field.substr(field.size() - 1);
21293e2932fSMatt Spinler         size_t num = std::strtoul(srcWordNum.c_str(), nullptr, 10);
21393e2932fSMatt Spinler         if (num == 0)
21493e2932fSMatt Spinler         {
21593e2932fSMatt Spinler             log<phosphor::logging::level::ERR>(
21693e2932fSMatt Spinler                 "Invalid symptom ID field in message registry",
21793e2932fSMatt Spinler                 entry("ERROR_NAME=%s", name.c_str()),
21893e2932fSMatt Spinler                 entry("FIELD_NAME=%s", srcWordNum.c_str()));
21993e2932fSMatt Spinler 
22093e2932fSMatt Spinler             throw std::runtime_error("Invalid symptom ID in message registry");
22193e2932fSMatt Spinler         }
22293e2932fSMatt Spinler         symptomIDFields.push_back(num);
22393e2932fSMatt Spinler     }
22493e2932fSMatt Spinler     if (!symptomIDFields.empty())
22593e2932fSMatt Spinler     {
22693e2932fSMatt Spinler         return symptomIDFields;
22793e2932fSMatt Spinler     }
22893e2932fSMatt Spinler 
22993e2932fSMatt Spinler     return std::nullopt;
23093e2932fSMatt Spinler }
23193e2932fSMatt Spinler 
23293e2932fSMatt Spinler uint16_t getComponentID(uint8_t srcType, uint16_t reasonCode,
23393e2932fSMatt Spinler                         const nlohmann::json& pelEntry, const std::string& name)
23493e2932fSMatt Spinler {
23593e2932fSMatt Spinler     uint16_t id = 0;
23693e2932fSMatt Spinler 
23793e2932fSMatt Spinler     // If the ComponentID field is there, use that.  Otherwise, if it's a
23893e2932fSMatt Spinler     // 0xBD BMC error SRC, use the reasoncode.
23993e2932fSMatt Spinler     if (pelEntry.find("ComponentID") != pelEntry.end())
24093e2932fSMatt Spinler     {
24193e2932fSMatt Spinler         std::string componentID = pelEntry["ComponentID"];
24293e2932fSMatt Spinler         id = strtoul(componentID.c_str(), nullptr, 16);
24393e2932fSMatt Spinler     }
24493e2932fSMatt Spinler     else
24593e2932fSMatt Spinler     {
24693e2932fSMatt Spinler         // On BMC error SRCs (BD), can just get the component ID from
24793e2932fSMatt Spinler         // the first byte of the reason code.
24893e2932fSMatt Spinler         if (srcType == static_cast<uint8_t>(SRCType::bmcError))
24993e2932fSMatt Spinler         {
25093e2932fSMatt Spinler             id = reasonCode & 0xFF00;
25193e2932fSMatt Spinler         }
25293e2932fSMatt Spinler         else
25393e2932fSMatt Spinler         {
25493e2932fSMatt Spinler             log<level::ERR>("Missing component ID field in message registry",
25593e2932fSMatt Spinler                             entry("ERROR_NAME=%s", name.c_str()));
25693e2932fSMatt Spinler 
25793e2932fSMatt Spinler             throw std::runtime_error(
25893e2932fSMatt Spinler                 "Missing component ID field in message registry");
25993e2932fSMatt Spinler         }
26093e2932fSMatt Spinler     }
26193e2932fSMatt Spinler 
26293e2932fSMatt Spinler     return id;
26393e2932fSMatt Spinler }
26493e2932fSMatt Spinler 
265367144cfSMatt Spinler } // namespace helper
266367144cfSMatt Spinler 
267*0f717e10SHarisuddin Mohamed Isa std::optional<Entry> Registry::lookup(const std::string& name, LookupType type,
268*0f717e10SHarisuddin Mohamed Isa                                       bool toCache)
269367144cfSMatt Spinler {
270*0f717e10SHarisuddin Mohamed Isa     std::optional<nlohmann::json> registryTmp;
271*0f717e10SHarisuddin Mohamed Isa     auto& registryOpt = (_registry) ? _registry : registryTmp;
272*0f717e10SHarisuddin Mohamed Isa     if (!registryOpt)
273367144cfSMatt Spinler     {
274*0f717e10SHarisuddin Mohamed Isa         registryOpt = readRegistry(_registryFile);
275*0f717e10SHarisuddin Mohamed Isa         if (!registryOpt)
276367144cfSMatt Spinler         {
277367144cfSMatt Spinler             return std::nullopt;
278367144cfSMatt Spinler         }
279*0f717e10SHarisuddin Mohamed Isa         else if (toCache)
280*0f717e10SHarisuddin Mohamed Isa         {
281*0f717e10SHarisuddin Mohamed Isa             // Save message registry in memory for peltool
282*0f717e10SHarisuddin Mohamed Isa             _registry = std::move(registryTmp);
283*0f717e10SHarisuddin Mohamed Isa         }
284*0f717e10SHarisuddin Mohamed Isa     }
285*0f717e10SHarisuddin Mohamed Isa     auto& reg = (_registry) ? _registry : registryTmp;
286*0f717e10SHarisuddin Mohamed Isa     const auto& registry = reg.value();
287367144cfSMatt Spinler     // Find an entry with this name in the PEL array.
288*0f717e10SHarisuddin Mohamed Isa     auto e = std::find_if(
289*0f717e10SHarisuddin Mohamed Isa         registry["PELs"].begin(), registry["PELs"].end(),
290*0f717e10SHarisuddin Mohamed Isa         [&name, &type](const auto& j) {
291*0f717e10SHarisuddin Mohamed Isa             return ((name == j["Name"] && type == LookupType::name) ||
292*0f717e10SHarisuddin Mohamed Isa                     (name == j["SRC"]["ReasonCode"] &&
293*0f717e10SHarisuddin Mohamed Isa                      type == LookupType::reasonCode));
294*0f717e10SHarisuddin Mohamed Isa         });
295367144cfSMatt Spinler 
296367144cfSMatt Spinler     if (e != registry["PELs"].end())
297367144cfSMatt Spinler     {
298367144cfSMatt Spinler         // Fill in the Entry structure from the JSON.  Most, but not all, fields
299367144cfSMatt Spinler         // are optional.
300367144cfSMatt Spinler 
301367144cfSMatt Spinler         try
302367144cfSMatt Spinler         {
303367144cfSMatt Spinler             Entry entry;
304367144cfSMatt Spinler             entry.name = (*e)["Name"];
305367144cfSMatt Spinler             entry.subsystem = helper::getSubsystem((*e)["Subsystem"]);
306e07f915bSMatt Spinler 
307e07f915bSMatt Spinler             if (e->find("ActionFlags") != e->end())
308e07f915bSMatt Spinler             {
309367144cfSMatt Spinler                 entry.actionFlags = helper::getActionFlags((*e)["ActionFlags"]);
310e07f915bSMatt Spinler             }
311367144cfSMatt Spinler 
312367144cfSMatt Spinler             if (e->find("MfgActionFlags") != e->end())
313367144cfSMatt Spinler             {
314367144cfSMatt Spinler                 entry.mfgActionFlags =
315367144cfSMatt Spinler                     helper::getActionFlags((*e)["MfgActionFlags"]);
316367144cfSMatt Spinler             }
317367144cfSMatt Spinler 
318367144cfSMatt Spinler             if (e->find("Severity") != e->end())
319367144cfSMatt Spinler             {
320367144cfSMatt Spinler                 entry.severity = helper::getSeverity((*e)["Severity"]);
321367144cfSMatt Spinler             }
322367144cfSMatt Spinler 
323367144cfSMatt Spinler             if (e->find("MfgSeverity") != e->end())
324367144cfSMatt Spinler             {
325367144cfSMatt Spinler                 entry.mfgSeverity = helper::getSeverity((*e)["MfgSeverity"]);
326367144cfSMatt Spinler             }
327367144cfSMatt Spinler 
328367144cfSMatt Spinler             if (e->find("EventType") != e->end())
329367144cfSMatt Spinler             {
330367144cfSMatt Spinler                 entry.eventType = helper::getEventType((*e)["EventType"]);
331367144cfSMatt Spinler             }
332367144cfSMatt Spinler 
333367144cfSMatt Spinler             if (e->find("EventScope") != e->end())
334367144cfSMatt Spinler             {
335367144cfSMatt Spinler                 entry.eventScope = helper::getEventScope((*e)["EventScope"]);
336367144cfSMatt Spinler             }
337367144cfSMatt Spinler 
33893e2932fSMatt Spinler             auto& src = (*e)["SRC"];
33993e2932fSMatt Spinler             entry.src.reasonCode = helper::getSRCReasonCode(src, name);
34093e2932fSMatt Spinler 
34193e2932fSMatt Spinler             if (src.find("Type") != src.end())
34293e2932fSMatt Spinler             {
34393e2932fSMatt Spinler                 entry.src.type = helper::getSRCType(src, name);
34493e2932fSMatt Spinler             }
34593e2932fSMatt Spinler             else
34693e2932fSMatt Spinler             {
34793e2932fSMatt Spinler                 entry.src.type = static_cast<uint8_t>(SRCType::bmcError);
34893e2932fSMatt Spinler             }
34993e2932fSMatt Spinler 
35093e2932fSMatt Spinler             // Now that we know the SRC type and reason code,
35193e2932fSMatt Spinler             // we can get the component ID.
35293e2932fSMatt Spinler             entry.componentID = helper::getComponentID(
35393e2932fSMatt Spinler                 entry.src.type, entry.src.reasonCode, *e, name);
35493e2932fSMatt Spinler 
35593e2932fSMatt Spinler             if (src.find("Words6To9") != src.end())
35693e2932fSMatt Spinler             {
35793e2932fSMatt Spinler                 entry.src.hexwordADFields =
35893e2932fSMatt Spinler                     helper::getSRCHexwordFields(src, name);
35993e2932fSMatt Spinler             }
36093e2932fSMatt Spinler 
36193e2932fSMatt Spinler             if (src.find("SymptomIDFields") != src.end())
36293e2932fSMatt Spinler             {
36393e2932fSMatt Spinler                 entry.src.symptomID = helper::getSRCSymptomIDFields(src, name);
36493e2932fSMatt Spinler             }
36593e2932fSMatt Spinler 
36693e2932fSMatt Spinler             if (src.find("PowerFault") != src.end())
36793e2932fSMatt Spinler             {
36893e2932fSMatt Spinler                 entry.src.powerFault = src["PowerFault"];
36993e2932fSMatt Spinler             }
370367144cfSMatt Spinler 
371*0f717e10SHarisuddin Mohamed Isa             auto& doc = (*e)["Documentation"];
372*0f717e10SHarisuddin Mohamed Isa             entry.doc.message = doc["Message"];
373*0f717e10SHarisuddin Mohamed Isa             entry.doc.description = doc["Description"];
374*0f717e10SHarisuddin Mohamed Isa             if (doc.find("MessageArgSources") != doc.end())
375*0f717e10SHarisuddin Mohamed Isa             {
376*0f717e10SHarisuddin Mohamed Isa                 entry.doc.messageArgSources = doc["MessageArgSources"];
377*0f717e10SHarisuddin Mohamed Isa             }
378*0f717e10SHarisuddin Mohamed Isa 
379367144cfSMatt Spinler             return entry;
380367144cfSMatt Spinler         }
381367144cfSMatt Spinler         catch (std::exception& e)
382367144cfSMatt Spinler         {
383367144cfSMatt Spinler             log<level::ERR>("Found invalid message registry field",
384367144cfSMatt Spinler                             entry("ERROR=%s", e.what()));
385367144cfSMatt Spinler         }
386367144cfSMatt Spinler     }
387367144cfSMatt Spinler 
388367144cfSMatt Spinler     return std::nullopt;
389367144cfSMatt Spinler }
390367144cfSMatt Spinler 
391*0f717e10SHarisuddin Mohamed Isa std::optional<nlohmann::json>
392*0f717e10SHarisuddin Mohamed Isa     Registry::readRegistry(const std::filesystem::path& registryFile)
393*0f717e10SHarisuddin Mohamed Isa {
394*0f717e10SHarisuddin Mohamed Isa     // Look in /etc first in case someone put a test file there
395*0f717e10SHarisuddin Mohamed Isa     fs::path debugFile{fs::path{debugFilePath} / registryFileName};
396*0f717e10SHarisuddin Mohamed Isa     nlohmann::json registry;
397*0f717e10SHarisuddin Mohamed Isa     std::ifstream file;
398*0f717e10SHarisuddin Mohamed Isa 
399*0f717e10SHarisuddin Mohamed Isa     if (fs::exists(debugFile))
400*0f717e10SHarisuddin Mohamed Isa     {
401*0f717e10SHarisuddin Mohamed Isa         log<level::INFO>("Using debug PEL message registry");
402*0f717e10SHarisuddin Mohamed Isa         file.open(debugFile);
403*0f717e10SHarisuddin Mohamed Isa     }
404*0f717e10SHarisuddin Mohamed Isa     else
405*0f717e10SHarisuddin Mohamed Isa     {
406*0f717e10SHarisuddin Mohamed Isa         file.open(registryFile);
407*0f717e10SHarisuddin Mohamed Isa     }
408*0f717e10SHarisuddin Mohamed Isa 
409*0f717e10SHarisuddin Mohamed Isa     try
410*0f717e10SHarisuddin Mohamed Isa     {
411*0f717e10SHarisuddin Mohamed Isa         registry = nlohmann::json::parse(file);
412*0f717e10SHarisuddin Mohamed Isa     }
413*0f717e10SHarisuddin Mohamed Isa     catch (std::exception& e)
414*0f717e10SHarisuddin Mohamed Isa     {
415*0f717e10SHarisuddin Mohamed Isa         log<level::ERR>("Error parsing message registry JSON",
416*0f717e10SHarisuddin Mohamed Isa                         entry("JSON_ERROR=%s", e.what()));
417*0f717e10SHarisuddin Mohamed Isa         return std::nullopt;
418*0f717e10SHarisuddin Mohamed Isa     }
419*0f717e10SHarisuddin Mohamed Isa     return registry;
420*0f717e10SHarisuddin Mohamed Isa }
421*0f717e10SHarisuddin Mohamed Isa 
422367144cfSMatt Spinler } // namespace message
423367144cfSMatt Spinler } // namespace pels
424367144cfSMatt Spinler } // namespace openpower
425