blob: 42ced0c642b01676a05c79095b9d9d51b32e7e42 [file] [log] [blame]
Matt Spinler367144c2019-09-19 15:33:52 -05001#include "registry.hpp"
2
3#include "pel_types.hpp"
4#include "pel_values.hpp"
5
6#include <fstream>
7#include <phosphor-logging/log.hpp>
8
9namespace openpower
10{
11namespace pels
12{
13namespace message
14{
15
16namespace pv = pel_values;
17namespace fs = std::filesystem;
18using namespace phosphor::logging;
19
20constexpr auto debugFilePath = "/etc/phosphor-logging/";
21
22namespace helper
23{
24
25uint8_t getSubsystem(const std::string& subsystemName)
26{
27 // Get the actual value to use in the PEL for the string name
28 auto ss = pv::findByName(subsystemName, pv::subsystemValues);
29 if (ss == pv::subsystemValues.end())
30 {
31 // Schema validation should be catching this.
32 log<level::ERR>("Invalid subsystem name used in message registry",
33 entry("SUBSYSTEM=%s", subsystemName.c_str()));
34
35 throw std::runtime_error("Invalid subsystem used in message registry");
36 }
37
38 return std::get<pv::fieldValuePos>(*ss);
39}
40
41uint8_t getSeverity(const std::string& severityName)
42{
43 auto s = pv::findByName(severityName, pv::severityValues);
44 if (s == pv::severityValues.end())
45 {
46 // Schema validation should be catching this.
47 log<level::ERR>("Invalid severity name used in message registry",
48 entry("SEVERITY=%s", severityName.c_str()));
49
50 throw std::runtime_error("Invalid severity used in message registry");
51 }
52
53 return std::get<pv::fieldValuePos>(*s);
54}
55
56uint16_t getActionFlags(const std::vector<std::string>& flags)
57{
58 uint16_t actionFlags = 0;
59
60 // Make the bitmask based on the array of flag names
61 for (const auto& flag : flags)
62 {
63 auto s = pv::findByName(flag, pv::actionFlagsValues);
64 if (s == pv::actionFlagsValues.end())
65 {
66 // Schema validation should be catching this.
67 log<level::ERR>("Invalid action flag name used in message registry",
68 entry("FLAG=%s", flag.c_str()));
69
70 throw std::runtime_error(
71 "Invalid action flag used in message registry");
72 }
73
74 actionFlags |= std::get<pv::fieldValuePos>(*s);
75 }
76
77 return actionFlags;
78}
79
80uint8_t getEventType(const std::string& eventTypeName)
81{
82 auto t = pv::findByName(eventTypeName, pv::eventTypeValues);
83 if (t == pv::eventTypeValues.end())
84 {
85 log<level::ERR>("Invalid event type used in message registry",
86 entry("EVENT_TYPE=%s", eventTypeName.c_str()));
87
88 throw std::runtime_error("Invalid event type used in message registry");
89 }
90 return std::get<pv::fieldValuePos>(*t);
91}
92
93uint8_t getEventScope(const std::string& eventScopeName)
94{
95 auto s = pv::findByName(eventScopeName, pv::eventScopeValues);
96 if (s == pv::eventScopeValues.end())
97 {
98 log<level::ERR>("Invalid event scope used in registry",
99 entry("EVENT_SCOPE=%s", eventScopeName.c_str()));
100
101 throw std::runtime_error(
102 "Invalid event scope used in message registry");
103 }
104 return std::get<pv::fieldValuePos>(*s);
105}
106
107} // namespace helper
108
109std::optional<Entry> Registry::lookup(const std::string& name)
110{
111 // Look in /etc first in case someone put a test file there
112 fs::path debugFile{fs::path{debugFilePath} / registryFileName};
113 nlohmann::json registry;
114 std::ifstream file;
115
116 if (fs::exists(debugFile))
117 {
118 log<level::INFO>("Using debug PEL message registry");
119 file.open(debugFile);
120 }
121 else
122 {
123 file.open(_registryFile);
124 }
125
126 try
127 {
128 registry = nlohmann::json::parse(file);
129 }
130 catch (std::exception& e)
131 {
132 log<level::ERR>("Error parsing message registry JSON",
133 entry("JSON_ERROR=%s", e.what()));
134 return std::nullopt;
135 }
136
137 // Find an entry with this name in the PEL array.
138 auto e = std::find_if(registry["PELs"].begin(), registry["PELs"].end(),
139 [&name](const auto& j) { return name == j["Name"]; });
140
141 if (e != registry["PELs"].end())
142 {
143 // Fill in the Entry structure from the JSON. Most, but not all, fields
144 // are optional.
145
146 try
147 {
148 Entry entry;
149 entry.name = (*e)["Name"];
150 entry.subsystem = helper::getSubsystem((*e)["Subsystem"]);
151 entry.actionFlags = helper::getActionFlags((*e)["ActionFlags"]);
152
153 if (e->find("MfgActionFlags") != e->end())
154 {
155 entry.mfgActionFlags =
156 helper::getActionFlags((*e)["MfgActionFlags"]);
157 }
158
159 if (e->find("Severity") != e->end())
160 {
161 entry.severity = helper::getSeverity((*e)["Severity"]);
162 }
163
164 if (e->find("MfgSeverity") != e->end())
165 {
166 entry.mfgSeverity = helper::getSeverity((*e)["MfgSeverity"]);
167 }
168
169 if (e->find("EventType") != e->end())
170 {
171 entry.eventType = helper::getEventType((*e)["EventType"]);
172 }
173
174 if (e->find("EventScope") != e->end())
175 {
176 entry.eventScope = helper::getEventScope((*e)["EventScope"]);
177 }
178
179 // TODO: SRC fields
180
181 return entry;
182 }
183 catch (std::exception& e)
184 {
185 log<level::ERR>("Found invalid message registry field",
186 entry("ERROR=%s", e.what()));
187 }
188 }
189
190 return std::nullopt;
191}
192
193} // namespace message
194} // namespace pels
195} // namespace openpower