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