blob: 09666f3d9de8df69956cf350f9bd147b7dfee1c6 [file] [log] [blame]
Matt Spinler367144c2019-09-19 15:33:52 -05001#pragma once
2#include <filesystem>
3#include <nlohmann/json.hpp>
4#include <optional>
5#include <string>
6#include <vector>
7
8namespace openpower
9{
10namespace pels
11{
12namespace message
13{
14
15constexpr auto registryFileName = "message_registry.json";
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +080016enum class LookupType
17{
18 name = 0,
19 reasonCode = 1
20};
21
22/**
23 * @brief Represents the Documentation related fields in the message registry.
24 * It is part of the 'Entry' structure that will be filled in when
25 * an error is looked up in the registry.
26 *
27 * If a field is wrapped by std::optional, it means the field is
28 * optional in the JSON and higher level code knows how to handle it.
29 */
30struct DOC
31{
32 /**
33 * @brief Description of error
34 */
35 std::string description;
36
37 /**
38 * @brief Error message field
39 */
40 std::string message;
41
42 /**
43 * @brief An optional vector of SRC word 6-9 to use as the source of the
44 * numeric arguments that will be substituted into any placeholder
45 * in the Message field.
46 */
47 std::optional<std::vector<std::string>> messageArgSources;
48};
Matt Spinler367144c2019-09-19 15:33:52 -050049
50/**
Matt Spinler93e29322019-09-20 11:16:15 -050051 * @brief Represents the SRC related fields in the message registry.
52 * It is part of the 'Entry' structure that will be filled in when
53 * an error is looked up in the registry.
54 *
55 * If a field is wrapped by std::optional, it means the field is
56 * optional in the JSON and higher level code knows how to handle it.
57 */
58struct SRC
59{
60 /**
61 * @brief SRC type - The first byte of the ASCII string
62 */
63 uint8_t type;
64
65 /**
66 * @brief The SRC reason code (2nd half of 4B 'ASCII string' word)
67 */
68 uint16_t reasonCode;
69
70 /**
71 * @brief Specifies if the SRC represents a power fault. Optional.
72 */
73 std::optional<bool> powerFault;
74
75 /**
76 * @brief An optional vector of SRC hexword numbers that should be used
77 * along with the SRC ASCII string to build the Symptom ID, which
78 * is a field in the Extended Header section.
79 */
80 using WordNum = size_t;
81 std::optional<std::vector<WordNum>> symptomID;
82
83 /**
84 * @brief Which AdditionalData fields to use to fill in the user defined
85 * SRC hexwords.
86 *
87 * For example, if the AdditionalData event log property contained
88 * "CHIPNUM=42" and this map contained {6, CHIPNUM}, then the code
89 * would put 42 into SRC hexword 6.
90 */
91 using AdditionalDataField = std::string;
92 std::optional<std::map<WordNum, AdditionalDataField>> hexwordADFields;
93
94 SRC() : type(0), reasonCode(0)
95 {
96 }
97};
98
99/**
Matt Spinler367144c2019-09-19 15:33:52 -0500100 * @brief Represents a message registry entry, which is used for creating a
101 * PEL from an OpenBMC event log.
102 */
103struct Entry
104{
105 /**
106 * @brief The error name, like "xyz.openbmc_project.Error.Foo".
107 */
108 std::string name;
109
110 /**
Matt Spinler93e29322019-09-20 11:16:15 -0500111 * @brief The component ID of the PEL creator.
112 */
113 uint16_t componentID;
114
115 /**
Matt Spinler367144c2019-09-19 15:33:52 -0500116 * @brief The PEL subsystem field.
117 */
118 uint8_t subsystem;
119
120 /**
121 * @brief The optional PEL severity field. If not specified, the PEL
122 * will use the severity of the OpenBMC event log.
123 */
124 std::optional<uint8_t> severity;
125
126 /**
127 * @brief The optional severity field to use when in manufacturing tolerance
128 * mode.
129 */
130 std::optional<uint8_t> mfgSeverity;
131
132 /**
133 * @brief The PEL action flags field.
134 */
Matt Spinlere07f9152019-11-01 10:48:36 -0500135 std::optional<uint16_t> actionFlags;
Matt Spinler367144c2019-09-19 15:33:52 -0500136
137 /**
138 * @brief The optional action flags to use instead when in manufacturing
139 * tolerance mode.
140 */
141 std::optional<uint16_t> mfgActionFlags;
142
143 /**
144 * @brief The PEL event type field. If not specified, higher level code
145 * will decide the value.
146 */
147 std::optional<uint8_t> eventType;
148
149 /**
150 * @brief The PEL event scope field. If not specified, higher level code
151 * will decide the value.
152 */
153 std::optional<uint8_t> eventScope;
154
Matt Spinler93e29322019-09-20 11:16:15 -0500155 /**
156 * The SRC related fields.
157 */
158 SRC src;
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800159
160 /**
161 * The Documentation related fields.
162 */
163 DOC doc;
Matt Spinlerd8e29002020-04-09 09:11:22 -0500164
165 /**
166 * @brief The callout JSON, if the entry has callouts.
167 */
168 std::optional<nlohmann::json> callouts;
Matt Spinler367144c2019-09-19 15:33:52 -0500169};
170
171/**
172 * @class Registry
173 *
174 * This class wraps the message registry JSON data and allows one to find
175 * the message registry entry pertaining to the error name.
176 *
177 * So that new registry files can easily be tested, the code will look for
178 * /etc/phosphor-logging/message_registry.json before looking for the real
179 * path.
180 */
181class Registry
182{
183 public:
184 Registry() = delete;
185 ~Registry() = default;
186 Registry(const Registry&) = default;
187 Registry& operator=(const Registry&) = default;
188 Registry(Registry&&) = default;
189 Registry& operator=(Registry&&) = default;
190
191 /**
192 * @brief Constructor
Matt Spinlerd8e29002020-04-09 09:11:22 -0500193 *
194 * Will load the callout JSON.
195 *
Matt Spinler367144c2019-09-19 15:33:52 -0500196 * @param[in] registryFile - The path to the file.
197 */
198 explicit Registry(const std::filesystem::path& registryFile) :
Matt Spinlerd8e29002020-04-09 09:11:22 -0500199 Registry(registryFile, true)
200 {
201 }
202
203 /**
204 * @brief Constructor
205 *
206 * This version contains a parameter that allows the callout JSON
207 * to be saved in the Entry struct or not, as it isn't needed at
208 * all in some cases.
209 *
210 * @param[in] registryFile - The path to the file.
211 * @param[in] loadCallouts - If the callout JSON should be saved.
212 */
213 explicit Registry(const std::filesystem::path& registryFile,
214 bool loadCallouts) :
215 _registryFile(registryFile),
216 _loadCallouts(loadCallouts)
Matt Spinler367144c2019-09-19 15:33:52 -0500217 {
218 }
219
220 /**
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800221 * @brief Find a registry entry based on its error name or reason code.
Matt Spinler367144c2019-09-19 15:33:52 -0500222 *
223 * This function does do some basic sanity checking on the JSON contents,
224 * but there is also an external program that enforces a schema on the
225 * registry JSON that should catch all of these problems ahead of time.
226 *
227 * @param[in] name - The error name, like xyz.openbmc_project.Error.Foo
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800228 * - OR
229 * - The reason code, like 0x1001
230 * @param[in] type - LookupType enum value
231 * @param[in] toCache - boolean to cache registry in memory
Matt Spinler367144c2019-09-19 15:33:52 -0500232 * @return optional<Entry> A filled in message registry structure if
233 * found, otherwise an empty optional object.
234 */
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800235 std::optional<Entry> lookup(const std::string& name, LookupType type,
236 bool toCache = false);
Matt Spinler367144c2019-09-19 15:33:52 -0500237
238 private:
239 /**
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800240 * @brief Parse message registry file using nlohmann::json
241 * @param[in] registryFile - The message registry JSON file
242 * @return optional<nlohmann::json> The full message registry object or an
243 * empty optional object upon failure.
244 */
245 std::optional<nlohmann::json>
246 readRegistry(const std::filesystem::path& registryFile);
247
248 /**
Matt Spinler367144c2019-09-19 15:33:52 -0500249 * @brief The path to the registry JSON file.
250 */
251 std::filesystem::path _registryFile;
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800252
253 /**
254 * @brief The full message registry object.
255 */
256 std::optional<nlohmann::json> _registry;
Matt Spinlerd8e29002020-04-09 09:11:22 -0500257
258 /**
259 * @brief If the callout JSON should be saved in the Entry on lookup.
260 */
261 bool _loadCallouts;
Matt Spinler367144c2019-09-19 15:33:52 -0500262};
263
264namespace helper
265{
266
267/**
268 * @brief A helper function to get the PEL subsystem value based on
269 * the registry subsystem name.
270 *
271 * @param[in] subsystemName - The registry name for the subsystem
272 *
273 * @return uint8_t The PEL subsystem value
274 */
275uint8_t getSubsystem(const std::string& subsystemName);
276
277/**
278 * @brief A helper function to get the PEL severity value based on
279 * the registry severity name.
280 *
281 * @param[in] severityName - The registry name for the severity
282 *
283 * @return uint8_t The PEL severity value
284 */
285uint8_t getSeverity(const std::string& severityName);
286
287/**
288 * @brief A helper function to get the action flags value based on
289 * the action flag names used in the registry.
290 *
291 * @param[in] flags - The list of flag names from the registry.
292 *
293 * @return uint16_t - The bitfield of flags used in the PEL.
294 */
295uint16_t getActionFlags(const std::vector<std::string>& flags);
296
297/**
298 * @brief A helper function to get the PEL event type value based on
299 * the registry event type name.
300 *
301 * @param[in] eventTypeName - The registry name for the event type
302 *
303 * @return uint8_t The PEL event type value
304 */
305uint8_t getEventType(const std::string& eventTypeName);
306
307/**
308 * @brief A helper function to get the PEL event scope value based on
309 * the registry event scope name.
310 *
311 * @param[in] eventScopeName - The registry name for the event scope
312 *
313 * @return uint8_t The PEL event scope value
314 */
315uint8_t getEventScope(const std::string& eventScopeName);
316
Matt Spinler93e29322019-09-20 11:16:15 -0500317/**
318 * @brief Reads the "ReasonCode" field out of JSON and converts the string value
319 * such as "0x5555" to a uint16 like 0x5555.
320 *
321 * @param[in] src - The message registry SRC dictionary to read from
322 * @param[in] name - The error name, to use in a trace if things go awry.
323 *
324 * @return uint16_t - The reason code
325 */
326uint16_t getSRCReasonCode(const nlohmann::json& src, const std::string& name);
327
328/**
329 * @brief Reads the "Type" field out of JSON and converts it to the SRC::Type
330 * value.
331 *
332 * @param[in] src - The message registry SRC dictionary to read from
333 * @param[in] name - The error name, to use in a trace if things go awry.
334 *
335 * @return uint8_t - The SRC type value, like 0x11
336 */
337uint8_t getSRCType(const nlohmann::json& src, const std::string& name);
338
339/**
340 * @brief Reads the "Words6To9" field out of JSON and converts it to a map
341 * of the SRC word number to the AdditionalData property field used
342 * to fill it in with.
343 *
344 * @param[in] src - The message registry SRC dictionary to read from
345 * @param[in] name - The error name, to use in a trace if things go awry.
346 *
347 * @return std::optional<std::map<SRC::WordNum, SRC::AdditionalDataField>>
348 */
349std::optional<std::map<SRC::WordNum, SRC::AdditionalDataField>>
350 getSRCHexwordFields(const nlohmann::json& src, const std::string& name);
351
352/**
353 * @brief Reads the "SymptomIDFields" field out of JSON and converts it to
354 * a vector of SRC word numbers.
355 *
356 * @param[in] src - The message registry SRC dictionary to read from
357 * @param[in] name - The error name, to use in a trace if things go awry.
358 *
359 * @return std::optional<std::vector<SRC::WordNum>>
360 */
361std::optional<std::vector<SRC::WordNum>>
362 getSRCSymptomIDFields(const nlohmann::json& src, const std::string& name);
363
364/**
365 * @brief Reads the "ComponentID" field out of JSON and converts it to a
366 * uint16_t like 0xFF00.
367 *
368 * The ComponentID JSON field is only required if the SRC type isn't a BD
369 * BMC SRC, because for those SRCs it can be inferred from the upper byte
370 * of the SRC reasoncode.
371 *
372 * @param[in] srcType - The SRC type
373 * @param[in] reasonCode - The SRC reason code
374 * @param[in] pelEntry - The PEL entry JSON
375 * @param[in] name - The error name, to use in a trace if things go awry.
376 *
377 * @return uin16_t - The component ID, like 0xFF00
378 */
379uint16_t getComponentID(uint8_t srcType, uint16_t reasonCode,
380 const nlohmann::json& pelEntry,
381 const std::string& name);
382
Matt Spinler367144c2019-09-19 15:33:52 -0500383} // namespace helper
384
385} // namespace message
386
387} // namespace pels
388} // namespace openpower