blob: 2296f6f9b8c8fcc054b2288916a01ce97fb62bda [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"
6#include "pel_types.hpp"
Matt Spinlerbd716f02019-10-15 10:54:11 -05007#include "registry.hpp"
Matt Spinlerf9bae182019-10-09 13:37:38 -05008#include "section.hpp"
9#include "stream.hpp"
10
11namespace openpower
12{
13namespace pels
14{
15
Matt Spinlerbd716f02019-10-15 10:54:11 -050016constexpr uint8_t srcSectionVersion = 0x01;
17constexpr uint8_t srcSectionSubtype = 0x01;
Matt Spinlerf9bae182019-10-09 13:37:38 -050018constexpr size_t numSRCHexDataWords = 8;
Matt Spinlerbd716f02019-10-15 10:54:11 -050019constexpr uint8_t srcVersion = 0x02;
20constexpr uint8_t bmcSRCFormat = 0x55;
21constexpr uint8_t primaryBMCPosition = 0x10;
22constexpr size_t baseSRCSize = 72;
Matt Spinlerf9bae182019-10-09 13:37:38 -050023
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +080024enum class DetailLevel
25{
26 message = 0x01,
27 json = 0x02
28};
Matt Spinlerf9bae182019-10-09 13:37:38 -050029/**
30 * @class SRC
31 *
32 * SRC stands for System Reference Code.
33 *
34 * This class represents the SRC sections in the PEL, of which there are 2:
35 * primary SRC and secondary SRC. These are the same structurally, the
36 * difference is that the primary SRC must be the 3rd section in the PEL if
37 * present and there is only one of them, and the secondary SRC sections are
38 * optional and there can be more than one (by definition, for there to be a
39 * secondary SRC, a primary SRC must also exist).
40 *
41 * This section consists of:
42 * - An 8B header (Has the version, flags, hexdata word count, and size fields)
43 * - 8 4B words of hex data
44 * - An ASCII character string
45 * - An optional subsection for Callouts
46 */
47class SRC : public Section
48{
49 public:
50 enum HeaderFlags
51 {
Matt Spinlerbd716f02019-10-15 10:54:11 -050052 additionalSections = 0x01,
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +080053 powerFaultEvent = 0x02,
54 hypDumpInit = 0x04,
55 i5OSServiceEventBit = 0x10,
56 virtualProgressSRC = 0x80
Matt Spinlerf9bae182019-10-09 13:37:38 -050057 };
58
59 SRC() = delete;
60 ~SRC() = default;
61 SRC(const SRC&) = delete;
62 SRC& operator=(const SRC&) = delete;
63 SRC(SRC&&) = delete;
64 SRC& operator=(SRC&&) = delete;
65
66 /**
67 * @brief Constructor
68 *
69 * Fills in this class's data fields from the stream.
70 *
71 * @param[in] pel - the PEL data stream
72 */
73 explicit SRC(Stream& pel);
74
75 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -050076 * @brief Constructor
77 *
78 * Creates the section with data from the PEL message registry entry for
79 * this error, along with the AdditionalData property contents from the
80 * corresponding event log.
81 *
82 * @param[in] regEntry - The message registry entry for this event log
83 * @param[in] additionalData - The AdditionalData properties in this event
84 * log
85 */
86 SRC(const message::Entry& regEntry, const AdditionalData& additionalData);
87
88 /**
Matt Spinlerf9bae182019-10-09 13:37:38 -050089 * @brief Flatten the section into the stream
90 *
91 * @param[in] stream - The stream to write to
92 */
Matt Spinler06885452019-11-06 10:35:42 -060093 void flatten(Stream& stream) const override;
Matt Spinlerf9bae182019-10-09 13:37:38 -050094
95 /**
96 * @brief Returns the SRC version, which is a different field
97 * than the version byte in the section header.
98 *
99 * @return uint8_t
100 */
101 uint8_t version() const
102 {
103 return _version;
104 }
105
106 /**
107 * @brief Returns the flags byte
108 *
109 * @return uint8_t
110 */
111 uint8_t flags() const
112 {
113 return _flags;
114 }
115
116 /**
117 * @brief Returns the hex data word count.
118 *
119 * Even though there always 8 words, this returns 9 due to previous
120 * SRC version formats.
121 *
122 * @return uint8_t
123 */
124 uint8_t hexWordCount() const
125 {
126 return _wordCount;
127 }
128
129 /**
130 * @brief Returns the size of the SRC section, not including the header.
131 *
132 * @return uint16_t
133 */
134 uint16_t size() const
135 {
136 return _size;
137 }
138
139 /**
140 * @brief Returns the 8 hex data words.
141 *
142 * @return const std::array<uint32_t, numSRCHexDataWords>&
143 */
144 const std::array<uint32_t, numSRCHexDataWords>& hexwordData() const
145 {
146 return _hexData;
147 }
148
149 /**
150 * @brief Returns the ASCII string
151 *
152 * @return std::string
153 */
154 std::string asciiString() const
155 {
156 return _asciiString->get();
157 }
158
159 /**
160 * @brief Returns the callouts subsection
161 *
162 * If no callouts, this unique_ptr will be empty
163 *
164 * @return const std::unique_ptr<src::Callouts>&
165 */
166 const std::unique_ptr<src::Callouts>& callouts() const
167 {
168 return _callouts;
169 }
170
Matt Spinlerf9bae182019-10-09 13:37:38 -0500171 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -0500172 * @brief Returns the size of this section when flattened into a PEL
Matt Spinlerf9bae182019-10-09 13:37:38 -0500173 *
Matt Spinlerbd716f02019-10-15 10:54:11 -0500174 * @return size_t - the size of the section
Matt Spinlerf9bae182019-10-09 13:37:38 -0500175 */
Matt Spinlerbd716f02019-10-15 10:54:11 -0500176 size_t flattenedSize() const
177 {
178 return _header.size;
179 }
Matt Spinlerf9bae182019-10-09 13:37:38 -0500180
181 /**
182 * @brief Says if this SRC has additional subsections in it
183 *
184 * Note: The callouts section is the only possible subsection.
185 *
186 * @return bool
187 */
188 inline bool hasAdditionalSections() const
189 {
Matt Spinlerbd716f02019-10-15 10:54:11 -0500190 return _flags & additionalSections;
191 }
192
193 /**
194 * @brief Indicates if this event log is for a power fault.
195 *
196 * This comes from a field in the message registry for BMC
197 * generated PELs.
198 *
199 * @return bool
200 */
201 inline bool isPowerFaultEvent() const
202 {
203 return _flags & powerFaultEvent;
204 }
205
Matt Spinlerc63e2e82019-12-02 15:50:12 -0600206 /**
207 * @brief Get the _hexData[] index to use based on the corresponding
208 * SRC word number.
209 *
210 * Converts the specification nomenclature to this data structure.
211 * See the _hexData documentation below for more information.
212 *
213 * @param[in] wordNum - The SRC word number, as defined by the spec.
214 *
215 * @return size_t The corresponding index into _hexData.
216 */
217 inline size_t getWordIndexFromWordNum(size_t wordNum) const
218 {
219 assert(wordNum >= 2 && wordNum <= 9);
220 return wordNum - 2;
221 }
222
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800223 /**
224 * @brief Get section in JSON.
225 * @return std::optional<std::string> - SRC section's JSON
226 */
227 std::optional<std::string> getJSON() const override;
228
229 /**
230 * @brief Get error details based on refcode and hexwords
231 * @param[in] registry - Registry object
232 * @param[in] type - detail level enum value : single message or full json
233 * @param[in] toCache - boolean to cache registry in memory, default=false
234 * @return std::optional<std::string> - Error details
235 */
236 std::optional<std::string> getErrorDetails(message::Registry& registry,
237 DetailLevel type,
238 bool toCache = false) const;
239
Matt Spinlerbd716f02019-10-15 10:54:11 -0500240 private:
241 /**
242 * @brief Fills in the user defined hex words from the
243 * AdditionalData fields.
244 *
245 * When creating this section from a message registry entry,
246 * that entry has a field that says which AdditionalData property
247 * fields to use to fill in the user defined hex data words 6-9
248 * (which correspond to hexData words 4-7).
249 *
250 * For example, given that AdditionalData is a map of string keys
251 * to string values, find the AdditionalData value for AdditionalData
252 * key X, convert it to a uint32_t, and save it in user data word Y.
253 *
254 * @param[in] regEntry - The message registry entry for the error
255 * @param[in] additionalData - The AdditionalData map
256 */
257 void setUserDefinedHexWords(const message::Entry& regEntry,
258 const AdditionalData& additionalData);
259 /**
260 * @brief Fills in the object from the stream data
261 *
262 * @param[in] stream - The stream to read from
263 */
264 void unflatten(Stream& stream);
265
266 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -0500267 * @brief Says if the word number is in the range of user defined words.
268 *
269 * This is only used for BMC generated SRCs, where words 6 - 9 are the
270 * user defined ones, meaning that setUserDefinedHexWords() will be
271 * used to fill them in based on the contents of the OpenBMC event log.
272 *
273 * @param[in] wordNum - The SRC word number, as defined by the spec.
274 *
275 * @return bool - If this word number can be filled in by the creator.
276 */
277 inline bool isUserDefinedWord(size_t wordNum) const
278 {
279 return (wordNum >= 6) && (wordNum <= 9);
280 }
281
282 /**
283 * @brief Sets the SRC format byte in the hex word data.
284 */
285 inline void setBMCFormat()
286 {
287 _hexData[0] |= bmcSRCFormat;
288 }
289
290 /**
291 * @brief Sets the hex word field that specifies which BMC
292 * (primary vs backup) created the error.
293 *
294 * Can be hardcoded until there are systems with redundant BMCs.
295 */
296 inline void setBMCPosition()
297 {
298 _hexData[1] |= primaryBMCPosition;
Matt Spinlerf9bae182019-10-09 13:37:38 -0500299 }
300
301 /**
302 * @brief Validates the section contents
303 *
304 * Updates _valid (in Section) with the results.
305 */
306 void validate() override;
307
308 /**
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800309 * @brief Get error description from message registry
310 * @param[in] regEntry - The message registry entry for the error
311 * @return std::optional<std::string> - Error message
312 */
313 std::optional<std::string>
314 getErrorMessage(const message::Entry& regEntry) const;
315
316 /**
317 * @brief Get Callout info in JSON
318 * @return std::optional<std::string> - Callout details
319 */
320 std::optional<std::string> getCallouts() const;
321
322 /**
Matt Spinlerf9bae182019-10-09 13:37:38 -0500323 * @brief The SRC version field
324 */
325 uint8_t _version;
326
327 /**
328 * @brief The SRC flags field
329 */
330 uint8_t _flags;
331
332 /**
333 * @brief A byte of reserved data after the flags field
334 */
335 uint8_t _reserved1B;
336
337 /**
338 * @brief The hex data word count.
339 *
340 * To be compatible with previous versions of SRCs, this is
341 * number of hex words (8) + 1 = 9.
342 */
343 uint8_t _wordCount;
344
345 /**
346 * @brief Two bytes of reserved data after the hex word count
347 */
348 uint16_t _reserved2B;
349
350 /**
351 * @brief The total size of the SRC section, not including the section
352 * header.
353 */
354 uint16_t _size;
355
356 /**
357 * @brief The SRC 'hex words'.
358 *
359 * In the spec these are referred to as SRC words 2 - 9 as words 0 and 1
360 * are filled by the 8 bytes of fields from above.
361 */
362 std::array<uint32_t, numSRCHexDataWords> _hexData;
363
364 /**
365 * @brief The 32 byte ASCII character string of the SRC
366 *
367 * It is padded with spaces to fill the 32 bytes.
368 * An example is:
369 * "BD8D1234 "
370 *
371 * That first word is what is commonly referred to as the refcode, and
372 * sometimes also called an SRC.
373 */
374 std::unique_ptr<src::AsciiString> _asciiString;
375
376 /**
377 * @brief The callouts subsection.
378 *
379 * Optional and only created if there are callouts.
380 */
381 std::unique_ptr<src::Callouts> _callouts;
382};
383
384} // namespace pels
385} // namespace openpower