blob: 0ec01f68332a10b1b37fcb2145414580f3b53f7d [file] [log] [blame]
Matt Spinlerf9bae182019-10-09 13:37:38 -05001#pragma once
2
3#include "additional_data.hpp"
4#include "ascii_string.hpp"
5#include "callouts.hpp"
Matt Spinler075e5ba2020-02-21 15:46:00 -06006#include "data_interface.hpp"
Matt Spinlerf9bae182019-10-09 13:37:38 -05007#include "pel_types.hpp"
Matt Spinlerbd716f02019-10-15 10:54:11 -05008#include "registry.hpp"
Matt Spinlerf9bae182019-10-09 13:37:38 -05009#include "section.hpp"
10#include "stream.hpp"
11
12namespace openpower
13{
14namespace pels
15{
16
Matt Spinlerbd716f02019-10-15 10:54:11 -050017constexpr uint8_t srcSectionVersion = 0x01;
18constexpr uint8_t srcSectionSubtype = 0x01;
Matt Spinlerf9bae182019-10-09 13:37:38 -050019constexpr size_t numSRCHexDataWords = 8;
Matt Spinlerbd716f02019-10-15 10:54:11 -050020constexpr uint8_t srcVersion = 0x02;
21constexpr uint8_t bmcSRCFormat = 0x55;
22constexpr uint8_t primaryBMCPosition = 0x10;
23constexpr size_t baseSRCSize = 72;
Matt Spinlerf9bae182019-10-09 13:37:38 -050024
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +080025enum class DetailLevel
26{
27 message = 0x01,
28 json = 0x02
29};
Matt Spinlerf9bae182019-10-09 13:37:38 -050030/**
31 * @class SRC
32 *
33 * SRC stands for System Reference Code.
34 *
35 * This class represents the SRC sections in the PEL, of which there are 2:
36 * primary SRC and secondary SRC. These are the same structurally, the
37 * difference is that the primary SRC must be the 3rd section in the PEL if
38 * present and there is only one of them, and the secondary SRC sections are
39 * optional and there can be more than one (by definition, for there to be a
40 * secondary SRC, a primary SRC must also exist).
41 *
42 * This section consists of:
43 * - An 8B header (Has the version, flags, hexdata word count, and size fields)
44 * - 8 4B words of hex data
45 * - An ASCII character string
46 * - An optional subsection for Callouts
47 */
48class SRC : public Section
49{
50 public:
51 enum HeaderFlags
52 {
Matt Spinlerbd716f02019-10-15 10:54:11 -050053 additionalSections = 0x01,
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +080054 powerFaultEvent = 0x02,
55 hypDumpInit = 0x04,
56 i5OSServiceEventBit = 0x10,
57 virtualProgressSRC = 0x80
Matt Spinlerf9bae182019-10-09 13:37:38 -050058 };
59
60 SRC() = delete;
61 ~SRC() = default;
62 SRC(const SRC&) = delete;
63 SRC& operator=(const SRC&) = delete;
64 SRC(SRC&&) = delete;
65 SRC& operator=(SRC&&) = delete;
66
67 /**
68 * @brief Constructor
69 *
70 * Fills in this class's data fields from the stream.
71 *
72 * @param[in] pel - the PEL data stream
73 */
74 explicit SRC(Stream& pel);
75
76 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -050077 * @brief Constructor
78 *
79 * Creates the section with data from the PEL message registry entry for
80 * this error, along with the AdditionalData property contents from the
81 * corresponding event log.
82 *
83 * @param[in] regEntry - The message registry entry for this event log
84 * @param[in] additionalData - The AdditionalData properties in this event
85 * log
Matt Spinler075e5ba2020-02-21 15:46:00 -060086 * @param[in] dataIface - The DataInterface object
Matt Spinlerbd716f02019-10-15 10:54:11 -050087 */
Matt Spinler075e5ba2020-02-21 15:46:00 -060088 SRC(const message::Entry& regEntry, const AdditionalData& additionalData,
Matt Spinler5a90a952020-08-27 09:39:03 -050089 const DataInterfaceBase& dataIface) :
90 SRC(regEntry, additionalData, nlohmann::json{}, dataIface)
91 {
92 }
93
94 /**
95 * @brief Constructor
96 *
97 * Creates the section with data from the PEL message registry entry for
98 * this error, along with the AdditionalData property contents from the
99 * corresponding event log, and a JSON array of callouts to add.
100 *
101 * @param[in] regEntry - The message registry entry for this event log
102 * @param[in] additionalData - The AdditionalData properties in this event
103 * log
104 * @param[in] jsonCallouts - The array of JSON callouts, or an empty object.
105 * @param[in] dataIface - The DataInterface object
106 */
107 SRC(const message::Entry& regEntry, const AdditionalData& additionalData,
108 const nlohmann::json& jsonCallouts, const DataInterfaceBase& dataIface);
Matt Spinlerbd716f02019-10-15 10:54:11 -0500109
110 /**
Matt Spinlerf9bae182019-10-09 13:37:38 -0500111 * @brief Flatten the section into the stream
112 *
113 * @param[in] stream - The stream to write to
114 */
Matt Spinler06885452019-11-06 10:35:42 -0600115 void flatten(Stream& stream) const override;
Matt Spinlerf9bae182019-10-09 13:37:38 -0500116
117 /**
118 * @brief Returns the SRC version, which is a different field
119 * than the version byte in the section header.
120 *
121 * @return uint8_t
122 */
123 uint8_t version() const
124 {
125 return _version;
126 }
127
128 /**
129 * @brief Returns the flags byte
130 *
131 * @return uint8_t
132 */
133 uint8_t flags() const
134 {
135 return _flags;
136 }
137
138 /**
139 * @brief Returns the hex data word count.
140 *
141 * Even though there always 8 words, this returns 9 due to previous
142 * SRC version formats.
143 *
144 * @return uint8_t
145 */
146 uint8_t hexWordCount() const
147 {
148 return _wordCount;
149 }
150
151 /**
152 * @brief Returns the size of the SRC section, not including the header.
153 *
154 * @return uint16_t
155 */
156 uint16_t size() const
157 {
158 return _size;
159 }
160
161 /**
162 * @brief Returns the 8 hex data words.
163 *
164 * @return const std::array<uint32_t, numSRCHexDataWords>&
165 */
166 const std::array<uint32_t, numSRCHexDataWords>& hexwordData() const
167 {
168 return _hexData;
169 }
170
171 /**
172 * @brief Returns the ASCII string
173 *
174 * @return std::string
175 */
176 std::string asciiString() const
177 {
178 return _asciiString->get();
179 }
180
181 /**
182 * @brief Returns the callouts subsection
183 *
184 * If no callouts, this unique_ptr will be empty
185 *
186 * @return const std::unique_ptr<src::Callouts>&
187 */
188 const std::unique_ptr<src::Callouts>& callouts() const
189 {
190 return _callouts;
191 }
192
Matt Spinlerf9bae182019-10-09 13:37:38 -0500193 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -0500194 * @brief Returns the size of this section when flattened into a PEL
Matt Spinlerf9bae182019-10-09 13:37:38 -0500195 *
Matt Spinlerbd716f02019-10-15 10:54:11 -0500196 * @return size_t - the size of the section
Matt Spinlerf9bae182019-10-09 13:37:38 -0500197 */
Matt Spinlerbd716f02019-10-15 10:54:11 -0500198 size_t flattenedSize() const
199 {
200 return _header.size;
201 }
Matt Spinlerf9bae182019-10-09 13:37:38 -0500202
203 /**
204 * @brief Says if this SRC has additional subsections in it
205 *
206 * Note: The callouts section is the only possible subsection.
207 *
208 * @return bool
209 */
210 inline bool hasAdditionalSections() const
211 {
Matt Spinlerbd716f02019-10-15 10:54:11 -0500212 return _flags & additionalSections;
213 }
214
215 /**
216 * @brief Indicates if this event log is for a power fault.
217 *
218 * This comes from a field in the message registry for BMC
219 * generated PELs.
220 *
221 * @return bool
222 */
223 inline bool isPowerFaultEvent() const
224 {
225 return _flags & powerFaultEvent;
226 }
227
Matt Spinlerc63e2e82019-12-02 15:50:12 -0600228 /**
229 * @brief Get the _hexData[] index to use based on the corresponding
230 * SRC word number.
231 *
232 * Converts the specification nomenclature to this data structure.
233 * See the _hexData documentation below for more information.
234 *
235 * @param[in] wordNum - The SRC word number, as defined by the spec.
236 *
237 * @return size_t The corresponding index into _hexData.
238 */
239 inline size_t getWordIndexFromWordNum(size_t wordNum) const
240 {
241 assert(wordNum >= 2 && wordNum <= 9);
242 return wordNum - 2;
243 }
244
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800245 /**
246 * @brief Get section in JSON.
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800247 * @param[in] registry - Registry object reference
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800248 * @param[in] plugins - Vector of strings of plugins found in filesystem
249 * @param[in] creatorID - Creator Subsystem ID from Private Header
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800250 * @return std::optional<std::string> - SRC section's JSON
251 */
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800252 std::optional<std::string> getJSON(message::Registry& registry,
253 const std::vector<std::string>& plugins,
254 uint8_t creatorID) const override;
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800255
256 /**
257 * @brief Get error details based on refcode and hexwords
258 * @param[in] registry - Registry object
259 * @param[in] type - detail level enum value : single message or full json
260 * @param[in] toCache - boolean to cache registry in memory, default=false
261 * @return std::optional<std::string> - Error details
262 */
263 std::optional<std::string> getErrorDetails(message::Registry& registry,
264 DetailLevel type,
265 bool toCache = false) const;
266
Matt Spinler075e5ba2020-02-21 15:46:00 -0600267 /**
268 * @brief Says if this SRC was created by the BMC (i.e. this code).
269 *
270 * @return bool - If created by the BMC or not
271 */
272 bool isBMCSRC() const;
273
Matt Spinlerbd716f02019-10-15 10:54:11 -0500274 private:
275 /**
276 * @brief Fills in the user defined hex words from the
277 * AdditionalData fields.
278 *
279 * When creating this section from a message registry entry,
280 * that entry has a field that says which AdditionalData property
281 * fields to use to fill in the user defined hex data words 6-9
282 * (which correspond to hexData words 4-7).
283 *
284 * For example, given that AdditionalData is a map of string keys
285 * to string values, find the AdditionalData value for AdditionalData
286 * key X, convert it to a uint32_t, and save it in user data word Y.
287 *
288 * @param[in] regEntry - The message registry entry for the error
289 * @param[in] additionalData - The AdditionalData map
290 */
291 void setUserDefinedHexWords(const message::Entry& regEntry,
292 const AdditionalData& additionalData);
293 /**
294 * @brief Fills in the object from the stream data
295 *
296 * @param[in] stream - The stream to read from
297 */
298 void unflatten(Stream& stream);
299
300 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -0500301 * @brief Says if the word number is in the range of user defined words.
302 *
303 * This is only used for BMC generated SRCs, where words 6 - 9 are the
304 * user defined ones, meaning that setUserDefinedHexWords() will be
305 * used to fill them in based on the contents of the OpenBMC event log.
306 *
307 * @param[in] wordNum - The SRC word number, as defined by the spec.
308 *
309 * @return bool - If this word number can be filled in by the creator.
310 */
311 inline bool isUserDefinedWord(size_t wordNum) const
312 {
313 return (wordNum >= 6) && (wordNum <= 9);
314 }
315
316 /**
317 * @brief Sets the SRC format byte in the hex word data.
318 */
319 inline void setBMCFormat()
320 {
321 _hexData[0] |= bmcSRCFormat;
322 }
323
324 /**
325 * @brief Sets the hex word field that specifies which BMC
326 * (primary vs backup) created the error.
327 *
328 * Can be hardcoded until there are systems with redundant BMCs.
329 */
330 inline void setBMCPosition()
331 {
332 _hexData[1] |= primaryBMCPosition;
Matt Spinlerf9bae182019-10-09 13:37:38 -0500333 }
334
335 /**
Matt Spinler075e5ba2020-02-21 15:46:00 -0600336 * @brief Sets the motherboard CCIN hex word field
337 *
338 * @param[in] dataIface - The DataInterface object
339 */
340 void setMotherboardCCIN(const DataInterfaceBase& dataIface);
341
342 /**
Matt Spinlerf9bae182019-10-09 13:37:38 -0500343 * @brief Validates the section contents
344 *
345 * Updates _valid (in Section) with the results.
346 */
347 void validate() override;
348
349 /**
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800350 * @brief Get error description from message registry
351 * @param[in] regEntry - The message registry entry for the error
352 * @return std::optional<std::string> - Error message
353 */
354 std::optional<std::string>
355 getErrorMessage(const message::Entry& regEntry) const;
356
357 /**
358 * @brief Get Callout info in JSON
359 * @return std::optional<std::string> - Callout details
360 */
361 std::optional<std::string> getCallouts() const;
362
363 /**
Matt Spinlered046852020-03-13 13:58:15 -0500364 * @brief Checks the AdditionalData property and the message registry
365 * JSON and adds any necessary callouts.
366 *
367 * The callout sources are the AdditionalData event log property
368 * and the message registry JSON.
369 *
Matt Spinler03984582020-04-09 13:17:58 -0500370 * @param[in] regEntry - The message registry entry for the error
371 * @param[in] additionalData - The AdditionalData values
Matt Spinler5a90a952020-08-27 09:39:03 -0500372 * @param[in] jsonCallouts - The array of JSON callouts, or an empty object
Matt Spinlered046852020-03-13 13:58:15 -0500373 * @param[in] dataIface - The DataInterface object
374 */
Matt Spinler03984582020-04-09 13:17:58 -0500375 void addCallouts(const message::Entry& regEntry,
376 const AdditionalData& additionalData,
Matt Spinler5a90a952020-08-27 09:39:03 -0500377 const nlohmann::json& jsonCallouts,
Matt Spinlered046852020-03-13 13:58:15 -0500378 const DataInterfaceBase& dataIface);
379
380 /**
381 * @brief Adds a FRU callout based on an inventory path
382 *
383 * @param[in] inventoryPath - The inventory item to call out
Matt Spinleraf191c72020-06-04 11:35:13 -0500384 * @param[in] priority - An optional priority (uses high if nullopt)
385 * @param[in] locationCode - The expanded location code (or look it up)
Matt Spinlered046852020-03-13 13:58:15 -0500386 * @param[in] dataIface - The DataInterface object
387 */
388 void addInventoryCallout(const std::string& inventoryPath,
Matt Spinleraf191c72020-06-04 11:35:13 -0500389 const std::optional<CalloutPriority>& priority,
390 const std::optional<std::string>& locationCode,
Matt Spinlered046852020-03-13 13:58:15 -0500391 const DataInterfaceBase& dataIface);
392
393 /**
Matt Spinler03984582020-04-09 13:17:58 -0500394 * @brief Adds FRU callouts based on the registry entry JSON
395 * for this error.
396 * @param[in] regEntry - The message registry entry for the error
397 * @param[in] additionalData - The AdditionalData values
398 * @param[in] dataIface - The DataInterface object
399 */
400 void addRegistryCallouts(const message::Entry& regEntry,
401 const AdditionalData& additionalData,
402 const DataInterfaceBase& dataIface);
403
404 /**
405 * @brief Adds a single FRU callout from the message registry.
406 *
407 * @param[in] callout - The registry callout structure
408 * @param[in] dataIface - The DataInterface object
409 */
410 void addRegistryCallout(const message::RegistryCallout& callout,
411 const DataInterfaceBase& dataIface);
412
413 /**
Matt Spinlered046852020-03-13 13:58:15 -0500414 * @brief Creates the Callouts object _callouts
415 * so that callouts can be added to it.
416 */
417 void createCalloutsObject()
418 {
419 if (!_callouts)
420 {
421 _callouts = std::make_unique<src::Callouts>();
422 _flags |= additionalSections;
423 }
424 }
425
426 /**
Matt Spinler717de422020-06-04 13:10:14 -0500427 * @brief Adds any FRU callouts based on a device path in the
428 * AdditionalData parameter.
429 *
430 * @param[in] additionalData - The AdditionalData values
431 * @param[in] dataIface - The DataInterface object
432 */
433 void addDevicePathCallouts(const AdditionalData& additionalData,
434 const DataInterfaceBase& dataIface);
435
436 /**
Matt Spinler5a90a952020-08-27 09:39:03 -0500437 * @brief Adds any FRU callouts specified in the incoming JSON.
438 *
439 * @param[in] jsonCallouts - The JSON array of callouts
440 * @param[in] dataIface - The DataInterface object
441 */
442 void addJSONCallouts(const nlohmann::json& jsonCallouts,
443 const DataInterfaceBase& dataIface);
444
445 /**
446 * @brief Adds a single callout based on the JSON
447 *
448 * @param[in] jsonCallouts - A single callout entry
449 * @param[in] dataIface - The DataInterface object
450 */
451 void addJSONCallout(const nlohmann::json& jsonCallout,
452 const DataInterfaceBase& dataIface);
Matt Spinler3bdd0112020-08-27 10:24:34 -0500453
454 /**
455 * @brief Extracts a CalloutPriority value from the json
456 * using the 'Priority' key.
457 *
458 * @param[in] json - A JSON object that contains the priority key
459 *
460 * @return CalloutPriority - The priority value
461 */
462 CalloutPriority getPriorityFromJSON(const nlohmann::json& json);
463
Matt Spinler5a90a952020-08-27 09:39:03 -0500464 /**
Matt Spinlerf9bae182019-10-09 13:37:38 -0500465 * @brief The SRC version field
466 */
467 uint8_t _version;
468
469 /**
470 * @brief The SRC flags field
471 */
472 uint8_t _flags;
473
474 /**
475 * @brief A byte of reserved data after the flags field
476 */
477 uint8_t _reserved1B;
478
479 /**
480 * @brief The hex data word count.
481 *
482 * To be compatible with previous versions of SRCs, this is
483 * number of hex words (8) + 1 = 9.
484 */
485 uint8_t _wordCount;
486
487 /**
488 * @brief Two bytes of reserved data after the hex word count
489 */
490 uint16_t _reserved2B;
491
492 /**
493 * @brief The total size of the SRC section, not including the section
494 * header.
495 */
496 uint16_t _size;
497
498 /**
499 * @brief The SRC 'hex words'.
500 *
501 * In the spec these are referred to as SRC words 2 - 9 as words 0 and 1
502 * are filled by the 8 bytes of fields from above.
503 */
504 std::array<uint32_t, numSRCHexDataWords> _hexData;
505
506 /**
507 * @brief The 32 byte ASCII character string of the SRC
508 *
509 * It is padded with spaces to fill the 32 bytes.
510 * An example is:
511 * "BD8D1234 "
512 *
513 * That first word is what is commonly referred to as the refcode, and
514 * sometimes also called an SRC.
515 */
516 std::unique_ptr<src::AsciiString> _asciiString;
517
518 /**
519 * @brief The callouts subsection.
520 *
521 * Optional and only created if there are callouts.
522 */
523 std::unique_ptr<src::Callouts> _callouts;
524};
525
526} // namespace pels
527} // namespace openpower