blob: 44540b0031336c92d2e096fa3061d3e479e4b3c7 [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,
89 const DataInterfaceBase& dataIface);
Matt Spinlerbd716f02019-10-15 10:54:11 -050090
91 /**
Matt Spinlerf9bae182019-10-09 13:37:38 -050092 * @brief Flatten the section into the stream
93 *
94 * @param[in] stream - The stream to write to
95 */
Matt Spinler06885452019-11-06 10:35:42 -060096 void flatten(Stream& stream) const override;
Matt Spinlerf9bae182019-10-09 13:37:38 -050097
98 /**
99 * @brief Returns the SRC version, which is a different field
100 * than the version byte in the section header.
101 *
102 * @return uint8_t
103 */
104 uint8_t version() const
105 {
106 return _version;
107 }
108
109 /**
110 * @brief Returns the flags byte
111 *
112 * @return uint8_t
113 */
114 uint8_t flags() const
115 {
116 return _flags;
117 }
118
119 /**
120 * @brief Returns the hex data word count.
121 *
122 * Even though there always 8 words, this returns 9 due to previous
123 * SRC version formats.
124 *
125 * @return uint8_t
126 */
127 uint8_t hexWordCount() const
128 {
129 return _wordCount;
130 }
131
132 /**
133 * @brief Returns the size of the SRC section, not including the header.
134 *
135 * @return uint16_t
136 */
137 uint16_t size() const
138 {
139 return _size;
140 }
141
142 /**
143 * @brief Returns the 8 hex data words.
144 *
145 * @return const std::array<uint32_t, numSRCHexDataWords>&
146 */
147 const std::array<uint32_t, numSRCHexDataWords>& hexwordData() const
148 {
149 return _hexData;
150 }
151
152 /**
153 * @brief Returns the ASCII string
154 *
155 * @return std::string
156 */
157 std::string asciiString() const
158 {
159 return _asciiString->get();
160 }
161
162 /**
163 * @brief Returns the callouts subsection
164 *
165 * If no callouts, this unique_ptr will be empty
166 *
167 * @return const std::unique_ptr<src::Callouts>&
168 */
169 const std::unique_ptr<src::Callouts>& callouts() const
170 {
171 return _callouts;
172 }
173
Matt Spinlerf9bae182019-10-09 13:37:38 -0500174 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -0500175 * @brief Returns the size of this section when flattened into a PEL
Matt Spinlerf9bae182019-10-09 13:37:38 -0500176 *
Matt Spinlerbd716f02019-10-15 10:54:11 -0500177 * @return size_t - the size of the section
Matt Spinlerf9bae182019-10-09 13:37:38 -0500178 */
Matt Spinlerbd716f02019-10-15 10:54:11 -0500179 size_t flattenedSize() const
180 {
181 return _header.size;
182 }
Matt Spinlerf9bae182019-10-09 13:37:38 -0500183
184 /**
185 * @brief Says if this SRC has additional subsections in it
186 *
187 * Note: The callouts section is the only possible subsection.
188 *
189 * @return bool
190 */
191 inline bool hasAdditionalSections() const
192 {
Matt Spinlerbd716f02019-10-15 10:54:11 -0500193 return _flags & additionalSections;
194 }
195
196 /**
197 * @brief Indicates if this event log is for a power fault.
198 *
199 * This comes from a field in the message registry for BMC
200 * generated PELs.
201 *
202 * @return bool
203 */
204 inline bool isPowerFaultEvent() const
205 {
206 return _flags & powerFaultEvent;
207 }
208
Matt Spinlerc63e2e82019-12-02 15:50:12 -0600209 /**
210 * @brief Get the _hexData[] index to use based on the corresponding
211 * SRC word number.
212 *
213 * Converts the specification nomenclature to this data structure.
214 * See the _hexData documentation below for more information.
215 *
216 * @param[in] wordNum - The SRC word number, as defined by the spec.
217 *
218 * @return size_t The corresponding index into _hexData.
219 */
220 inline size_t getWordIndexFromWordNum(size_t wordNum) const
221 {
222 assert(wordNum >= 2 && wordNum <= 9);
223 return wordNum - 2;
224 }
225
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800226 /**
227 * @brief Get section in JSON.
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800228 * @param[in] registry - Registry object reference
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800229 * @param[in] plugins - Vector of strings of plugins found in filesystem
230 * @param[in] creatorID - Creator Subsystem ID from Private Header
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800231 * @return std::optional<std::string> - SRC section's JSON
232 */
Harisuddin Mohamed Isac8d6cc62020-08-19 22:47:19 +0800233 std::optional<std::string> getJSON(message::Registry& registry,
234 const std::vector<std::string>& plugins,
235 uint8_t creatorID) const override;
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800236
237 /**
238 * @brief Get error details based on refcode and hexwords
239 * @param[in] registry - Registry object
240 * @param[in] type - detail level enum value : single message or full json
241 * @param[in] toCache - boolean to cache registry in memory, default=false
242 * @return std::optional<std::string> - Error details
243 */
244 std::optional<std::string> getErrorDetails(message::Registry& registry,
245 DetailLevel type,
246 bool toCache = false) const;
247
Matt Spinler075e5ba2020-02-21 15:46:00 -0600248 /**
249 * @brief Says if this SRC was created by the BMC (i.e. this code).
250 *
251 * @return bool - If created by the BMC or not
252 */
253 bool isBMCSRC() const;
254
Matt Spinlerbd716f02019-10-15 10:54:11 -0500255 private:
256 /**
257 * @brief Fills in the user defined hex words from the
258 * AdditionalData fields.
259 *
260 * When creating this section from a message registry entry,
261 * that entry has a field that says which AdditionalData property
262 * fields to use to fill in the user defined hex data words 6-9
263 * (which correspond to hexData words 4-7).
264 *
265 * For example, given that AdditionalData is a map of string keys
266 * to string values, find the AdditionalData value for AdditionalData
267 * key X, convert it to a uint32_t, and save it in user data word Y.
268 *
269 * @param[in] regEntry - The message registry entry for the error
270 * @param[in] additionalData - The AdditionalData map
271 */
272 void setUserDefinedHexWords(const message::Entry& regEntry,
273 const AdditionalData& additionalData);
274 /**
275 * @brief Fills in the object from the stream data
276 *
277 * @param[in] stream - The stream to read from
278 */
279 void unflatten(Stream& stream);
280
281 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -0500282 * @brief Says if the word number is in the range of user defined words.
283 *
284 * This is only used for BMC generated SRCs, where words 6 - 9 are the
285 * user defined ones, meaning that setUserDefinedHexWords() will be
286 * used to fill them in based on the contents of the OpenBMC event log.
287 *
288 * @param[in] wordNum - The SRC word number, as defined by the spec.
289 *
290 * @return bool - If this word number can be filled in by the creator.
291 */
292 inline bool isUserDefinedWord(size_t wordNum) const
293 {
294 return (wordNum >= 6) && (wordNum <= 9);
295 }
296
297 /**
298 * @brief Sets the SRC format byte in the hex word data.
299 */
300 inline void setBMCFormat()
301 {
302 _hexData[0] |= bmcSRCFormat;
303 }
304
305 /**
306 * @brief Sets the hex word field that specifies which BMC
307 * (primary vs backup) created the error.
308 *
309 * Can be hardcoded until there are systems with redundant BMCs.
310 */
311 inline void setBMCPosition()
312 {
313 _hexData[1] |= primaryBMCPosition;
Matt Spinlerf9bae182019-10-09 13:37:38 -0500314 }
315
316 /**
Matt Spinler075e5ba2020-02-21 15:46:00 -0600317 * @brief Sets the motherboard CCIN hex word field
318 *
319 * @param[in] dataIface - The DataInterface object
320 */
321 void setMotherboardCCIN(const DataInterfaceBase& dataIface);
322
323 /**
Matt Spinlerf9bae182019-10-09 13:37:38 -0500324 * @brief Validates the section contents
325 *
326 * Updates _valid (in Section) with the results.
327 */
328 void validate() override;
329
330 /**
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800331 * @brief Get error description from message registry
332 * @param[in] regEntry - The message registry entry for the error
333 * @return std::optional<std::string> - Error message
334 */
335 std::optional<std::string>
336 getErrorMessage(const message::Entry& regEntry) const;
337
338 /**
339 * @brief Get Callout info in JSON
340 * @return std::optional<std::string> - Callout details
341 */
342 std::optional<std::string> getCallouts() const;
343
344 /**
Matt Spinlered046852020-03-13 13:58:15 -0500345 * @brief Checks the AdditionalData property and the message registry
346 * JSON and adds any necessary callouts.
347 *
348 * The callout sources are the AdditionalData event log property
349 * and the message registry JSON.
350 *
Matt Spinler03984582020-04-09 13:17:58 -0500351 * @param[in] regEntry - The message registry entry for the error
352 * @param[in] additionalData - The AdditionalData values
Matt Spinlered046852020-03-13 13:58:15 -0500353 * @param[in] dataIface - The DataInterface object
354 */
Matt Spinler03984582020-04-09 13:17:58 -0500355 void addCallouts(const message::Entry& regEntry,
356 const AdditionalData& additionalData,
Matt Spinlered046852020-03-13 13:58:15 -0500357 const DataInterfaceBase& dataIface);
358
359 /**
360 * @brief Adds a FRU callout based on an inventory path
361 *
362 * @param[in] inventoryPath - The inventory item to call out
Matt Spinleraf191c72020-06-04 11:35:13 -0500363 * @param[in] priority - An optional priority (uses high if nullopt)
364 * @param[in] locationCode - The expanded location code (or look it up)
Matt Spinlered046852020-03-13 13:58:15 -0500365 * @param[in] dataIface - The DataInterface object
366 */
367 void addInventoryCallout(const std::string& inventoryPath,
Matt Spinleraf191c72020-06-04 11:35:13 -0500368 const std::optional<CalloutPriority>& priority,
369 const std::optional<std::string>& locationCode,
Matt Spinlered046852020-03-13 13:58:15 -0500370 const DataInterfaceBase& dataIface);
371
372 /**
Matt Spinler03984582020-04-09 13:17:58 -0500373 * @brief Adds FRU callouts based on the registry entry JSON
374 * for this error.
375 * @param[in] regEntry - The message registry entry for the error
376 * @param[in] additionalData - The AdditionalData values
377 * @param[in] dataIface - The DataInterface object
378 */
379 void addRegistryCallouts(const message::Entry& regEntry,
380 const AdditionalData& additionalData,
381 const DataInterfaceBase& dataIface);
382
383 /**
384 * @brief Adds a single FRU callout from the message registry.
385 *
386 * @param[in] callout - The registry callout structure
387 * @param[in] dataIface - The DataInterface object
388 */
389 void addRegistryCallout(const message::RegistryCallout& callout,
390 const DataInterfaceBase& dataIface);
391
392 /**
Matt Spinlered046852020-03-13 13:58:15 -0500393 * @brief Creates the Callouts object _callouts
394 * so that callouts can be added to it.
395 */
396 void createCalloutsObject()
397 {
398 if (!_callouts)
399 {
400 _callouts = std::make_unique<src::Callouts>();
401 _flags |= additionalSections;
402 }
403 }
404
405 /**
Matt Spinler717de422020-06-04 13:10:14 -0500406 * @brief Adds any FRU callouts based on a device path in the
407 * AdditionalData parameter.
408 *
409 * @param[in] additionalData - The AdditionalData values
410 * @param[in] dataIface - The DataInterface object
411 */
412 void addDevicePathCallouts(const AdditionalData& additionalData,
413 const DataInterfaceBase& dataIface);
414
415 /**
Matt Spinlerf9bae182019-10-09 13:37:38 -0500416 * @brief The SRC version field
417 */
418 uint8_t _version;
419
420 /**
421 * @brief The SRC flags field
422 */
423 uint8_t _flags;
424
425 /**
426 * @brief A byte of reserved data after the flags field
427 */
428 uint8_t _reserved1B;
429
430 /**
431 * @brief The hex data word count.
432 *
433 * To be compatible with previous versions of SRCs, this is
434 * number of hex words (8) + 1 = 9.
435 */
436 uint8_t _wordCount;
437
438 /**
439 * @brief Two bytes of reserved data after the hex word count
440 */
441 uint16_t _reserved2B;
442
443 /**
444 * @brief The total size of the SRC section, not including the section
445 * header.
446 */
447 uint16_t _size;
448
449 /**
450 * @brief The SRC 'hex words'.
451 *
452 * In the spec these are referred to as SRC words 2 - 9 as words 0 and 1
453 * are filled by the 8 bytes of fields from above.
454 */
455 std::array<uint32_t, numSRCHexDataWords> _hexData;
456
457 /**
458 * @brief The 32 byte ASCII character string of the SRC
459 *
460 * It is padded with spaces to fill the 32 bytes.
461 * An example is:
462 * "BD8D1234 "
463 *
464 * That first word is what is commonly referred to as the refcode, and
465 * sometimes also called an SRC.
466 */
467 std::unique_ptr<src::AsciiString> _asciiString;
468
469 /**
470 * @brief The callouts subsection.
471 *
472 * Optional and only created if there are callouts.
473 */
474 std::unique_ptr<src::Callouts> _callouts;
475};
476
477} // namespace pels
478} // namespace openpower