blob: 5363864dee708e52f0a14cb9e8ff4128e17ca9ce [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
Matt Spinlerafa2c792020-08-27 11:01:39 -050060 /**
61 * @brief Enums for the error status bits in hex word 5
62 * of BMC SRCs.
63 */
64 enum class ErrorStatusFlags
65 {
66 deconfigured = 0x02000000,
67 guarded = 0x01000000
68 };
69
Matt Spinlerf9bae182019-10-09 13:37:38 -050070 SRC() = delete;
71 ~SRC() = default;
72 SRC(const SRC&) = delete;
73 SRC& operator=(const SRC&) = delete;
74 SRC(SRC&&) = delete;
75 SRC& operator=(SRC&&) = delete;
76
77 /**
78 * @brief Constructor
79 *
80 * Fills in this class's data fields from the stream.
81 *
82 * @param[in] pel - the PEL data stream
83 */
84 explicit SRC(Stream& pel);
85
86 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -050087 * @brief Constructor
88 *
89 * Creates the section with data from the PEL message registry entry for
90 * this error, along with the AdditionalData property contents from the
91 * corresponding event log.
92 *
93 * @param[in] regEntry - The message registry entry for this event log
94 * @param[in] additionalData - The AdditionalData properties in this event
95 * log
Matt Spinler075e5ba2020-02-21 15:46:00 -060096 * @param[in] dataIface - The DataInterface object
Matt Spinlerbd716f02019-10-15 10:54:11 -050097 */
Matt Spinler075e5ba2020-02-21 15:46:00 -060098 SRC(const message::Entry& regEntry, const AdditionalData& additionalData,
Matt Spinler5a90a952020-08-27 09:39:03 -050099 const DataInterfaceBase& dataIface) :
100 SRC(regEntry, additionalData, nlohmann::json{}, dataIface)
101 {
102 }
103
104 /**
105 * @brief Constructor
106 *
107 * Creates the section with data from the PEL message registry entry for
108 * this error, along with the AdditionalData property contents from the
109 * corresponding event log, and a JSON array of callouts to add.
110 *
111 * @param[in] regEntry - The message registry entry for this event log
112 * @param[in] additionalData - The AdditionalData properties in this event
113 * log
114 * @param[in] jsonCallouts - The array of JSON callouts, or an empty object.
115 * @param[in] dataIface - The DataInterface object
116 */
117 SRC(const message::Entry& regEntry, const AdditionalData& additionalData,
118 const nlohmann::json& jsonCallouts, const DataInterfaceBase& dataIface);
Matt Spinlerbd716f02019-10-15 10:54:11 -0500119
120 /**
Matt Spinlerf9bae182019-10-09 13:37:38 -0500121 * @brief Flatten the section into the stream
122 *
123 * @param[in] stream - The stream to write to
124 */
Matt Spinler06885452019-11-06 10:35:42 -0600125 void flatten(Stream& stream) const override;
Matt Spinlerf9bae182019-10-09 13:37:38 -0500126
127 /**
128 * @brief Returns the SRC version, which is a different field
129 * than the version byte in the section header.
130 *
131 * @return uint8_t
132 */
133 uint8_t version() const
134 {
135 return _version;
136 }
137
138 /**
139 * @brief Returns the flags byte
140 *
141 * @return uint8_t
142 */
143 uint8_t flags() const
144 {
145 return _flags;
146 }
147
148 /**
149 * @brief Returns the hex data word count.
150 *
151 * Even though there always 8 words, this returns 9 due to previous
152 * SRC version formats.
153 *
154 * @return uint8_t
155 */
156 uint8_t hexWordCount() const
157 {
158 return _wordCount;
159 }
160
161 /**
162 * @brief Returns the size of the SRC section, not including the header.
163 *
164 * @return uint16_t
165 */
166 uint16_t size() const
167 {
168 return _size;
169 }
170
171 /**
172 * @brief Returns the 8 hex data words.
173 *
174 * @return const std::array<uint32_t, numSRCHexDataWords>&
175 */
176 const std::array<uint32_t, numSRCHexDataWords>& hexwordData() const
177 {
178 return _hexData;
179 }
180
181 /**
182 * @brief Returns the ASCII string
183 *
184 * @return std::string
185 */
186 std::string asciiString() const
187 {
188 return _asciiString->get();
189 }
190
191 /**
192 * @brief Returns the callouts subsection
193 *
194 * If no callouts, this unique_ptr will be empty
195 *
196 * @return const std::unique_ptr<src::Callouts>&
197 */
198 const std::unique_ptr<src::Callouts>& callouts() const
199 {
200 return _callouts;
201 }
202
Matt Spinlerf9bae182019-10-09 13:37:38 -0500203 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -0500204 * @brief Returns the size of this section when flattened into a PEL
Matt Spinlerf9bae182019-10-09 13:37:38 -0500205 *
Matt Spinlerbd716f02019-10-15 10:54:11 -0500206 * @return size_t - the size of the section
Matt Spinlerf9bae182019-10-09 13:37:38 -0500207 */
Matt Spinlerbd716f02019-10-15 10:54:11 -0500208 size_t flattenedSize() const
209 {
210 return _header.size;
211 }
Matt Spinlerf9bae182019-10-09 13:37:38 -0500212
213 /**
214 * @brief Says if this SRC has additional subsections in it
215 *
216 * Note: The callouts section is the only possible subsection.
217 *
218 * @return bool
219 */
220 inline bool hasAdditionalSections() const
221 {
Matt Spinlerbd716f02019-10-15 10:54:11 -0500222 return _flags & additionalSections;
223 }
224
225 /**
226 * @brief Indicates if this event log is for a power fault.
227 *
228 * This comes from a field in the message registry for BMC
229 * generated PELs.
230 *
231 * @return bool
232 */
233 inline bool isPowerFaultEvent() const
234 {
235 return _flags & powerFaultEvent;
236 }
237
Matt Spinlerc63e2e82019-12-02 15:50:12 -0600238 /**
239 * @brief Get the _hexData[] index to use based on the corresponding
240 * SRC word number.
241 *
242 * Converts the specification nomenclature to this data structure.
243 * See the _hexData documentation below for more information.
244 *
245 * @param[in] wordNum - The SRC word number, as defined by the spec.
246 *
247 * @return size_t The corresponding index into _hexData.
248 */
249 inline size_t getWordIndexFromWordNum(size_t wordNum) const
250 {
251 assert(wordNum >= 2 && wordNum <= 9);
252 return wordNum - 2;
253 }
254
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800255 /**
256 * @brief Get section in JSON.
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800257 * @param[in] registry - Registry object reference
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800258 * @param[in] plugins - Vector of strings of plugins found in filesystem
259 * @param[in] creatorID - Creator Subsystem ID from Private Header
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800260 * @return std::optional<std::string> - SRC section's JSON
261 */
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800262 std::optional<std::string> getJSON(message::Registry& registry,
263 const std::vector<std::string>& plugins,
264 uint8_t creatorID) const override;
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800265
266 /**
267 * @brief Get error details based on refcode and hexwords
268 * @param[in] registry - Registry object
269 * @param[in] type - detail level enum value : single message or full json
270 * @param[in] toCache - boolean to cache registry in memory, default=false
271 * @return std::optional<std::string> - Error details
272 */
273 std::optional<std::string> getErrorDetails(message::Registry& registry,
274 DetailLevel type,
275 bool toCache = false) const;
276
Matt Spinler075e5ba2020-02-21 15:46:00 -0600277 /**
278 * @brief Says if this SRC was created by the BMC (i.e. this code).
279 *
280 * @return bool - If created by the BMC or not
281 */
282 bool isBMCSRC() const;
283
Matt Spinlerbd716f02019-10-15 10:54:11 -0500284 private:
285 /**
286 * @brief Fills in the user defined hex words from the
287 * AdditionalData fields.
288 *
289 * When creating this section from a message registry entry,
290 * that entry has a field that says which AdditionalData property
291 * fields to use to fill in the user defined hex data words 6-9
292 * (which correspond to hexData words 4-7).
293 *
294 * For example, given that AdditionalData is a map of string keys
295 * to string values, find the AdditionalData value for AdditionalData
296 * key X, convert it to a uint32_t, and save it in user data word Y.
297 *
298 * @param[in] regEntry - The message registry entry for the error
299 * @param[in] additionalData - The AdditionalData map
300 */
301 void setUserDefinedHexWords(const message::Entry& regEntry,
302 const AdditionalData& additionalData);
303 /**
304 * @brief Fills in the object from the stream data
305 *
306 * @param[in] stream - The stream to read from
307 */
308 void unflatten(Stream& stream);
309
310 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -0500311 * @brief Says if the word number is in the range of user defined words.
312 *
313 * This is only used for BMC generated SRCs, where words 6 - 9 are the
314 * user defined ones, meaning that setUserDefinedHexWords() will be
315 * used to fill them in based on the contents of the OpenBMC event log.
316 *
317 * @param[in] wordNum - The SRC word number, as defined by the spec.
318 *
319 * @return bool - If this word number can be filled in by the creator.
320 */
321 inline bool isUserDefinedWord(size_t wordNum) const
322 {
323 return (wordNum >= 6) && (wordNum <= 9);
324 }
325
326 /**
327 * @brief Sets the SRC format byte in the hex word data.
328 */
329 inline void setBMCFormat()
330 {
331 _hexData[0] |= bmcSRCFormat;
332 }
333
334 /**
335 * @brief Sets the hex word field that specifies which BMC
336 * (primary vs backup) created the error.
337 *
338 * Can be hardcoded until there are systems with redundant BMCs.
339 */
340 inline void setBMCPosition()
341 {
342 _hexData[1] |= primaryBMCPosition;
Matt Spinlerf9bae182019-10-09 13:37:38 -0500343 }
344
345 /**
Matt Spinler075e5ba2020-02-21 15:46:00 -0600346 * @brief Sets the motherboard CCIN hex word field
347 *
348 * @param[in] dataIface - The DataInterface object
349 */
350 void setMotherboardCCIN(const DataInterfaceBase& dataIface);
351
352 /**
Matt Spinlerafa2c792020-08-27 11:01:39 -0500353 * @brief Sets an error status bit in the SRC.
354 *
355 * @param[in] flag - The flag to set
356 */
357 void setErrorStatusFlag(ErrorStatusFlags flag)
358 {
359 _hexData[3] |= static_cast<uint32_t>(flag);
360 }
361
362 /**
Matt Spinlerf9bae182019-10-09 13:37:38 -0500363 * @brief Validates the section contents
364 *
365 * Updates _valid (in Section) with the results.
366 */
367 void validate() override;
368
369 /**
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800370 * @brief Get error description from message registry
371 * @param[in] regEntry - The message registry entry for the error
372 * @return std::optional<std::string> - Error message
373 */
374 std::optional<std::string>
375 getErrorMessage(const message::Entry& regEntry) const;
376
377 /**
378 * @brief Get Callout info in JSON
379 * @return std::optional<std::string> - Callout details
380 */
381 std::optional<std::string> getCallouts() const;
382
383 /**
Matt Spinlered046852020-03-13 13:58:15 -0500384 * @brief Checks the AdditionalData property and the message registry
385 * JSON and adds any necessary callouts.
386 *
387 * The callout sources are the AdditionalData event log property
388 * and the message registry JSON.
389 *
Matt Spinler03984582020-04-09 13:17:58 -0500390 * @param[in] regEntry - The message registry entry for the error
391 * @param[in] additionalData - The AdditionalData values
Matt Spinler5a90a952020-08-27 09:39:03 -0500392 * @param[in] jsonCallouts - The array of JSON callouts, or an empty object
Matt Spinlered046852020-03-13 13:58:15 -0500393 * @param[in] dataIface - The DataInterface object
394 */
Matt Spinler03984582020-04-09 13:17:58 -0500395 void addCallouts(const message::Entry& regEntry,
396 const AdditionalData& additionalData,
Matt Spinler5a90a952020-08-27 09:39:03 -0500397 const nlohmann::json& jsonCallouts,
Matt Spinlered046852020-03-13 13:58:15 -0500398 const DataInterfaceBase& dataIface);
399
400 /**
401 * @brief Adds a FRU callout based on an inventory path
402 *
403 * @param[in] inventoryPath - The inventory item to call out
Matt Spinleraf191c72020-06-04 11:35:13 -0500404 * @param[in] priority - An optional priority (uses high if nullopt)
405 * @param[in] locationCode - The expanded location code (or look it up)
Matt Spinlered046852020-03-13 13:58:15 -0500406 * @param[in] dataIface - The DataInterface object
Matt Spinlerb8cb60f2020-08-27 10:55:55 -0500407 * @param[in] mrus - The MRUs to add to the callout
Matt Spinlered046852020-03-13 13:58:15 -0500408 */
Matt Spinlerb8cb60f2020-08-27 10:55:55 -0500409 void
410 addInventoryCallout(const std::string& inventoryPath,
411 const std::optional<CalloutPriority>& priority,
412 const std::optional<std::string>& locationCode,
413 const DataInterfaceBase& dataIface,
414 const std::vector<src::MRU::MRUCallout>& mrus = {});
Matt Spinlered046852020-03-13 13:58:15 -0500415
416 /**
Matt Spinlerf00f9d02020-10-23 09:14:22 -0500417 * @brief Returns the callouts to use from the registry entry.
418 *
Matt Spinler03984582020-04-09 13:17:58 -0500419 * @param[in] regEntry - The message registry entry for the error
Matt Spinlerf00f9d02020-10-23 09:14:22 -0500420 * @param[in] additionalData - The AdditionalData property
Matt Spinler03984582020-04-09 13:17:58 -0500421 * @param[in] dataIface - The DataInterface object
422 */
Matt Spinlerf00f9d02020-10-23 09:14:22 -0500423 std::vector<message::RegistryCallout>
424 getRegistryCallouts(const message::Entry& regEntry,
425 const AdditionalData& additionalData,
426 const DataInterfaceBase& dataIface);
427
428 /**
429 * @brief Adds the FRU callouts from the list of registry callouts
430 * passed in to the SRC.
431 *
432 * The last parameter is used only in a special case when the first
433 * callout is a symbolic FRU with a trusted location code. See the
434 * addRegistryCallout documentation.
435 *
436 * @param[in] callouts - The message registry callouts to add
437 * @param[in] dataIface - The DataInterface object
438 * @param[in] trustedSymbolicFRUInvPath - The optional inventory path used
439 * in the symbolic FRU case.
440 */
441 void addRegistryCallouts(
442 const std::vector<message::RegistryCallout>& callouts,
443 const DataInterfaceBase& dataIface,
444 std::optional<std::string> trustedSymbolicFRUInvPath);
Matt Spinler03984582020-04-09 13:17:58 -0500445
446 /**
447 * @brief Adds a single FRU callout from the message registry.
448 *
Matt Spinlerf00f9d02020-10-23 09:14:22 -0500449 * If the last parameter is filled in, and the registry callout is a
450 * symbolic FRU callout with a trusted location code, and it has the
451 * 'useInventoryLocCode' member set to true, then the location code of
452 * that inventory item will be what is used for that trusted location code.
453 *
Matt Spinler03984582020-04-09 13:17:58 -0500454 * @param[in] callout - The registry callout structure
455 * @param[in] dataIface - The DataInterface object
Matt Spinlerf00f9d02020-10-23 09:14:22 -0500456 * @param[in] trustedSymbolicFRUInvPath - The optional inventory path used
457 * in the symbolic FRU case.
Matt Spinler03984582020-04-09 13:17:58 -0500458 */
Matt Spinlerf00f9d02020-10-23 09:14:22 -0500459 void addRegistryCallout(
460 const message::RegistryCallout& callout,
461 const DataInterfaceBase& dataIface,
462 const std::optional<std::string>& trustedSymbolicFRUInvPath);
Matt Spinler03984582020-04-09 13:17:58 -0500463
464 /**
Matt Spinlered046852020-03-13 13:58:15 -0500465 * @brief Creates the Callouts object _callouts
466 * so that callouts can be added to it.
467 */
468 void createCalloutsObject()
469 {
470 if (!_callouts)
471 {
472 _callouts = std::make_unique<src::Callouts>();
473 _flags |= additionalSections;
474 }
475 }
476
477 /**
Matt Spinler717de422020-06-04 13:10:14 -0500478 * @brief Adds any FRU callouts based on a device path in the
479 * AdditionalData parameter.
480 *
481 * @param[in] additionalData - The AdditionalData values
482 * @param[in] dataIface - The DataInterface object
483 */
484 void addDevicePathCallouts(const AdditionalData& additionalData,
485 const DataInterfaceBase& dataIface);
486
487 /**
Matt Spinler5a90a952020-08-27 09:39:03 -0500488 * @brief Adds any FRU callouts specified in the incoming JSON.
489 *
490 * @param[in] jsonCallouts - The JSON array of callouts
491 * @param[in] dataIface - The DataInterface object
492 */
493 void addJSONCallouts(const nlohmann::json& jsonCallouts,
494 const DataInterfaceBase& dataIface);
495
496 /**
497 * @brief Adds a single callout based on the JSON
498 *
499 * @param[in] jsonCallouts - A single callout entry
500 * @param[in] dataIface - The DataInterface object
501 */
502 void addJSONCallout(const nlohmann::json& jsonCallout,
503 const DataInterfaceBase& dataIface);
Matt Spinler3bdd0112020-08-27 10:24:34 -0500504
505 /**
506 * @brief Extracts a CalloutPriority value from the json
507 * using the 'Priority' key.
508 *
509 * @param[in] json - A JSON object that contains the priority key
510 *
511 * @return CalloutPriority - The priority value
512 */
513 CalloutPriority getPriorityFromJSON(const nlohmann::json& json);
514
Matt Spinler5a90a952020-08-27 09:39:03 -0500515 /**
Matt Spinlerb8cb60f2020-08-27 10:55:55 -0500516 * @brief Exracts MRU values and their priorities from the
517 * input JSON array.
518 *
519 * @param[in] mruJSON - The JSON array
520 */
521 std::vector<src::MRU::MRUCallout>
522 getMRUsFromJSON(const nlohmann::json& mruJSON);
523
524 /**
Matt Spinlerf9bae182019-10-09 13:37:38 -0500525 * @brief The SRC version field
526 */
527 uint8_t _version;
528
529 /**
530 * @brief The SRC flags field
531 */
532 uint8_t _flags;
533
534 /**
535 * @brief A byte of reserved data after the flags field
536 */
537 uint8_t _reserved1B;
538
539 /**
540 * @brief The hex data word count.
541 *
542 * To be compatible with previous versions of SRCs, this is
543 * number of hex words (8) + 1 = 9.
544 */
545 uint8_t _wordCount;
546
547 /**
548 * @brief Two bytes of reserved data after the hex word count
549 */
550 uint16_t _reserved2B;
551
552 /**
553 * @brief The total size of the SRC section, not including the section
554 * header.
555 */
556 uint16_t _size;
557
558 /**
559 * @brief The SRC 'hex words'.
560 *
561 * In the spec these are referred to as SRC words 2 - 9 as words 0 and 1
562 * are filled by the 8 bytes of fields from above.
563 */
564 std::array<uint32_t, numSRCHexDataWords> _hexData;
565
566 /**
567 * @brief The 32 byte ASCII character string of the SRC
568 *
569 * It is padded with spaces to fill the 32 bytes.
570 * An example is:
571 * "BD8D1234 "
572 *
573 * That first word is what is commonly referred to as the refcode, and
574 * sometimes also called an SRC.
575 */
576 std::unique_ptr<src::AsciiString> _asciiString;
577
578 /**
579 * @brief The callouts subsection.
580 *
581 * Optional and only created if there are callouts.
582 */
583 std::unique_ptr<src::Callouts> _callouts;
584};
585
586} // namespace pels
587} // namespace openpower