blob: dada63a6a7d9df1841e065e73f2203b17ae006a4 [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
24/**
25 * @class SRC
26 *
27 * SRC stands for System Reference Code.
28 *
29 * This class represents the SRC sections in the PEL, of which there are 2:
30 * primary SRC and secondary SRC. These are the same structurally, the
31 * difference is that the primary SRC must be the 3rd section in the PEL if
32 * present and there is only one of them, and the secondary SRC sections are
33 * optional and there can be more than one (by definition, for there to be a
34 * secondary SRC, a primary SRC must also exist).
35 *
36 * This section consists of:
37 * - An 8B header (Has the version, flags, hexdata word count, and size fields)
38 * - 8 4B words of hex data
39 * - An ASCII character string
40 * - An optional subsection for Callouts
41 */
42class SRC : public Section
43{
44 public:
45 enum HeaderFlags
46 {
Matt Spinlerbd716f02019-10-15 10:54:11 -050047 additionalSections = 0x01,
48 powerFaultEvent = 0x02
Matt Spinlerf9bae182019-10-09 13:37:38 -050049 };
50
51 SRC() = delete;
52 ~SRC() = default;
53 SRC(const SRC&) = delete;
54 SRC& operator=(const SRC&) = delete;
55 SRC(SRC&&) = delete;
56 SRC& operator=(SRC&&) = delete;
57
58 /**
59 * @brief Constructor
60 *
61 * Fills in this class's data fields from the stream.
62 *
63 * @param[in] pel - the PEL data stream
64 */
65 explicit SRC(Stream& pel);
66
67 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -050068 * @brief Constructor
69 *
70 * Creates the section with data from the PEL message registry entry for
71 * this error, along with the AdditionalData property contents from the
72 * corresponding event log.
73 *
74 * @param[in] regEntry - The message registry entry for this event log
75 * @param[in] additionalData - The AdditionalData properties in this event
76 * log
77 */
78 SRC(const message::Entry& regEntry, const AdditionalData& additionalData);
79
80 /**
Matt Spinlerf9bae182019-10-09 13:37:38 -050081 * @brief Flatten the section into the stream
82 *
83 * @param[in] stream - The stream to write to
84 */
Matt Spinler06885452019-11-06 10:35:42 -060085 void flatten(Stream& stream) const override;
Matt Spinlerf9bae182019-10-09 13:37:38 -050086
87 /**
88 * @brief Returns the SRC version, which is a different field
89 * than the version byte in the section header.
90 *
91 * @return uint8_t
92 */
93 uint8_t version() const
94 {
95 return _version;
96 }
97
98 /**
99 * @brief Returns the flags byte
100 *
101 * @return uint8_t
102 */
103 uint8_t flags() const
104 {
105 return _flags;
106 }
107
108 /**
109 * @brief Returns the hex data word count.
110 *
111 * Even though there always 8 words, this returns 9 due to previous
112 * SRC version formats.
113 *
114 * @return uint8_t
115 */
116 uint8_t hexWordCount() const
117 {
118 return _wordCount;
119 }
120
121 /**
122 * @brief Returns the size of the SRC section, not including the header.
123 *
124 * @return uint16_t
125 */
126 uint16_t size() const
127 {
128 return _size;
129 }
130
131 /**
132 * @brief Returns the 8 hex data words.
133 *
134 * @return const std::array<uint32_t, numSRCHexDataWords>&
135 */
136 const std::array<uint32_t, numSRCHexDataWords>& hexwordData() const
137 {
138 return _hexData;
139 }
140
141 /**
142 * @brief Returns the ASCII string
143 *
144 * @return std::string
145 */
146 std::string asciiString() const
147 {
148 return _asciiString->get();
149 }
150
151 /**
152 * @brief Returns the callouts subsection
153 *
154 * If no callouts, this unique_ptr will be empty
155 *
156 * @return const std::unique_ptr<src::Callouts>&
157 */
158 const std::unique_ptr<src::Callouts>& callouts() const
159 {
160 return _callouts;
161 }
162
Matt Spinlerf9bae182019-10-09 13:37:38 -0500163 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -0500164 * @brief Returns the size of this section when flattened into a PEL
Matt Spinlerf9bae182019-10-09 13:37:38 -0500165 *
Matt Spinlerbd716f02019-10-15 10:54:11 -0500166 * @return size_t - the size of the section
Matt Spinlerf9bae182019-10-09 13:37:38 -0500167 */
Matt Spinlerbd716f02019-10-15 10:54:11 -0500168 size_t flattenedSize() const
169 {
170 return _header.size;
171 }
Matt Spinlerf9bae182019-10-09 13:37:38 -0500172
173 /**
174 * @brief Says if this SRC has additional subsections in it
175 *
176 * Note: The callouts section is the only possible subsection.
177 *
178 * @return bool
179 */
180 inline bool hasAdditionalSections() const
181 {
Matt Spinlerbd716f02019-10-15 10:54:11 -0500182 return _flags & additionalSections;
183 }
184
185 /**
186 * @brief Indicates if this event log is for a power fault.
187 *
188 * This comes from a field in the message registry for BMC
189 * generated PELs.
190 *
191 * @return bool
192 */
193 inline bool isPowerFaultEvent() const
194 {
195 return _flags & powerFaultEvent;
196 }
197
Matt Spinlerc63e2e82019-12-02 15:50:12 -0600198 /**
199 * @brief Get the _hexData[] index to use based on the corresponding
200 * SRC word number.
201 *
202 * Converts the specification nomenclature to this data structure.
203 * See the _hexData documentation below for more information.
204 *
205 * @param[in] wordNum - The SRC word number, as defined by the spec.
206 *
207 * @return size_t The corresponding index into _hexData.
208 */
209 inline size_t getWordIndexFromWordNum(size_t wordNum) const
210 {
211 assert(wordNum >= 2 && wordNum <= 9);
212 return wordNum - 2;
213 }
214
Matt Spinlerbd716f02019-10-15 10:54:11 -0500215 private:
216 /**
217 * @brief Fills in the user defined hex words from the
218 * AdditionalData fields.
219 *
220 * When creating this section from a message registry entry,
221 * that entry has a field that says which AdditionalData property
222 * fields to use to fill in the user defined hex data words 6-9
223 * (which correspond to hexData words 4-7).
224 *
225 * For example, given that AdditionalData is a map of string keys
226 * to string values, find the AdditionalData value for AdditionalData
227 * key X, convert it to a uint32_t, and save it in user data word Y.
228 *
229 * @param[in] regEntry - The message registry entry for the error
230 * @param[in] additionalData - The AdditionalData map
231 */
232 void setUserDefinedHexWords(const message::Entry& regEntry,
233 const AdditionalData& additionalData);
234 /**
235 * @brief Fills in the object from the stream data
236 *
237 * @param[in] stream - The stream to read from
238 */
239 void unflatten(Stream& stream);
240
241 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -0500242 * @brief Says if the word number is in the range of user defined words.
243 *
244 * This is only used for BMC generated SRCs, where words 6 - 9 are the
245 * user defined ones, meaning that setUserDefinedHexWords() will be
246 * used to fill them in based on the contents of the OpenBMC event log.
247 *
248 * @param[in] wordNum - The SRC word number, as defined by the spec.
249 *
250 * @return bool - If this word number can be filled in by the creator.
251 */
252 inline bool isUserDefinedWord(size_t wordNum) const
253 {
254 return (wordNum >= 6) && (wordNum <= 9);
255 }
256
257 /**
258 * @brief Sets the SRC format byte in the hex word data.
259 */
260 inline void setBMCFormat()
261 {
262 _hexData[0] |= bmcSRCFormat;
263 }
264
265 /**
266 * @brief Sets the hex word field that specifies which BMC
267 * (primary vs backup) created the error.
268 *
269 * Can be hardcoded until there are systems with redundant BMCs.
270 */
271 inline void setBMCPosition()
272 {
273 _hexData[1] |= primaryBMCPosition;
Matt Spinlerf9bae182019-10-09 13:37:38 -0500274 }
275
276 /**
277 * @brief Validates the section contents
278 *
279 * Updates _valid (in Section) with the results.
280 */
281 void validate() override;
282
283 /**
284 * @brief The SRC version field
285 */
286 uint8_t _version;
287
288 /**
289 * @brief The SRC flags field
290 */
291 uint8_t _flags;
292
293 /**
294 * @brief A byte of reserved data after the flags field
295 */
296 uint8_t _reserved1B;
297
298 /**
299 * @brief The hex data word count.
300 *
301 * To be compatible with previous versions of SRCs, this is
302 * number of hex words (8) + 1 = 9.
303 */
304 uint8_t _wordCount;
305
306 /**
307 * @brief Two bytes of reserved data after the hex word count
308 */
309 uint16_t _reserved2B;
310
311 /**
312 * @brief The total size of the SRC section, not including the section
313 * header.
314 */
315 uint16_t _size;
316
317 /**
318 * @brief The SRC 'hex words'.
319 *
320 * In the spec these are referred to as SRC words 2 - 9 as words 0 and 1
321 * are filled by the 8 bytes of fields from above.
322 */
323 std::array<uint32_t, numSRCHexDataWords> _hexData;
324
325 /**
326 * @brief The 32 byte ASCII character string of the SRC
327 *
328 * It is padded with spaces to fill the 32 bytes.
329 * An example is:
330 * "BD8D1234 "
331 *
332 * That first word is what is commonly referred to as the refcode, and
333 * sometimes also called an SRC.
334 */
335 std::unique_ptr<src::AsciiString> _asciiString;
336
337 /**
338 * @brief The callouts subsection.
339 *
340 * Optional and only created if there are callouts.
341 */
342 std::unique_ptr<src::Callouts> _callouts;
343};
344
345} // namespace pels
346} // namespace openpower