blob: 0475c1c9827a38bbcc5ff61d9df92c51d28a332f [file] [log] [blame]
Matt Spinlercb6b0592019-07-16 15:58:51 -05001#pragma once
2
Matt Spinlerb8323632019-09-20 15:11:04 -05003#include "additional_data.hpp"
Matt Spinleraa659472019-10-23 09:26:48 -05004#include "data_interface.hpp"
Matt Spinlercb6b0592019-07-16 15:58:51 -05005#include "private_header.hpp"
Matt Spinlerb8323632019-09-20 15:11:04 -05006#include "registry.hpp"
Matt Spinlerbd716f02019-10-15 10:54:11 -05007#include "src.hpp"
Matt Spinlerafa857c2019-10-24 13:03:46 -05008#include "user_data.hpp"
Matt Spinlercb6b0592019-07-16 15:58:51 -05009#include "user_header.hpp"
10
11#include <memory>
12#include <vector>
13
14namespace openpower
15{
16namespace pels
17{
18
19/** @class PEL
20 *
21 * @brief This class represents a specific event log format referred to as a
22 * Platform Event Log.
23 *
24 * Every field in a PEL are in structures call sections, of which there are
25 * several types. Some sections are required, and some are optional. In some
26 * cases there may be more than one instance of a section type.
27 *
28 * The only two required sections for every type of PEL are the Private Header
29 * section and User Header section, which must be in the first and second
30 * positions, respectively.
31 *
32 * Every section starts with an 8 byte section header, which has the section
33 * size and type, among other things.
34 *
35 * This class represents all sections with objects.
36 *
Matt Spinlerbd716f02019-10-15 10:54:11 -050037 * The class can be constructed:
38 * - From a full formed flattened PEL.
39 * - From scratch based on an OpenBMC event and its corresponding PEL message
40 * registry entry.
Matt Spinlerb8323632019-09-20 15:11:04 -050041 *
Matt Spinlercb6b0592019-07-16 15:58:51 -050042 * The data() method allows one to retrieve the PEL as a vector<uint8_t>. This
43 * is the format in which it is stored and transmitted.
44 */
45class PEL
46{
47 public:
48 PEL() = delete;
49 ~PEL() = default;
50 PEL(const PEL&) = delete;
51 PEL& operator=(const PEL&) = delete;
52 PEL(PEL&&) = delete;
53 PEL& operator=(PEL&&) = delete;
54
55 /**
56 * @brief Constructor
57 *
58 * Build a PEL from raw data.
59 *
Matt Spinler07eefc52019-09-26 11:18:26 -050060 * Note: Neither this nor the following constructor can take a const vector&
61 * because the Stream class that is used to read from the vector cannot take
62 * a const. The alternative is to make a copy of the data, but as PELs can
63 * be up to 16KB that is undesireable.
64 *
Matt Spinlercb6b0592019-07-16 15:58:51 -050065 * @param[in] data - The PEL data
66 */
Matt Spinler07eefc52019-09-26 11:18:26 -050067 PEL(std::vector<uint8_t>& data);
Matt Spinlercb6b0592019-07-16 15:58:51 -050068
69 /**
70 * @brief Constructor
71 *
72 * Build a PEL from the raw data.
73 *
74 * @param[in] data - the PEL data
75 * @param[in] obmcLogID - the corresponding OpenBMC event log ID
76 */
Matt Spinler07eefc52019-09-26 11:18:26 -050077 PEL(std::vector<uint8_t>& data, uint32_t obmcLogID);
Matt Spinlercb6b0592019-07-16 15:58:51 -050078
79 /**
Matt Spinlerb8323632019-09-20 15:11:04 -050080 * @brief Constructor
81 *
82 * Creates a PEL from an OpenBMC event log and its message
83 * registry entry.
84 *
85 * @param[in] entry - The message registry entry for this error
86 * @param[in] obmcLogID - ID of corresponding OpenBMC event log
87 * @param[in] timestamp - Timestamp from the event log
88 * @param[in] severity - Severity from the event log
Matt Spinlerbd716f02019-10-15 10:54:11 -050089 * @param[in] additionalData - The AdditionalData contents
Matt Spinleraa659472019-10-23 09:26:48 -050090 * @param[in] dataIface - The data interface object
Matt Spinlerb8323632019-09-20 15:11:04 -050091 */
92 PEL(const openpower::pels::message::Entry& entry, uint32_t obmcLogID,
Matt Spinlerbd716f02019-10-15 10:54:11 -050093 uint64_t timestamp, phosphor::logging::Entry::Level severity,
Matt Spinleraa659472019-10-23 09:26:48 -050094 const AdditionalData& additionalData,
95 const DataInterfaceBase& dataIface);
Matt Spinlerb8323632019-09-20 15:11:04 -050096
97 /**
Matt Spinlercb6b0592019-07-16 15:58:51 -050098 * @brief Convenience function to return the log ID field from the
99 * Private Header section.
100 *
101 * @return uint32_t - the ID
102 */
103 uint32_t id() const
104 {
105 return _ph->id();
106 }
107
108 /**
109 * @brief Convenience function to return the PLID field from the
110 * Private Header section.
111 *
112 * @return uint32_t - the PLID
113 */
114 uint32_t plid() const
115 {
116 return _ph->plid();
117 }
118
119 /**
120 * @brief Convenience function to return the OpenBMC event log ID field
121 * from the Private Header section.
122 *
123 * @return uint32_t - the OpenBMC event log ID
124 */
125 uint32_t obmcLogID() const
126 {
127 return _ph->obmcLogID();
128 }
129
130 /**
131 * @brief Convenience function to return the commit time field from
132 * the Private Header section.
133 *
134 * @return BCDTime - the timestamp
135 */
136 BCDTime commitTime() const
137 {
138 return _ph->commitTimestamp();
139 }
140
141 /**
142 * @brief Convenience function to return the create time field from
143 * the Private Header section.
144 *
145 * @return BCDTime - the timestamp
146 */
147 BCDTime createTime() const
148 {
149 return _ph->createTimestamp();
150 }
151
152 /**
153 * @brief Gives access to the Private Header section class
154 *
Matt Spinler97d19b42019-10-29 11:34:03 -0500155 * @return const PrivateHeader& - the private header
Matt Spinlercb6b0592019-07-16 15:58:51 -0500156 */
Matt Spinler97d19b42019-10-29 11:34:03 -0500157 const PrivateHeader& privateHeader() const
Matt Spinlercb6b0592019-07-16 15:58:51 -0500158 {
Matt Spinler97d19b42019-10-29 11:34:03 -0500159 return *_ph;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500160 }
161
162 /**
163 * @brief Gives access to the User Header section class
164 *
Matt Spinler97d19b42019-10-29 11:34:03 -0500165 * @return const UserHeader& - the user header
Matt Spinlercb6b0592019-07-16 15:58:51 -0500166 */
Matt Spinler97d19b42019-10-29 11:34:03 -0500167 const UserHeader& userHeader() const
Matt Spinlercb6b0592019-07-16 15:58:51 -0500168 {
Matt Spinler97d19b42019-10-29 11:34:03 -0500169 return *_uh;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500170 }
171
172 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -0500173 * @brief Gives access to the primary SRC's section class
174 *
175 * This is technically an optional section, so the return
176 * value is an std::optional<SRC*>.
177 *
178 * @return std::optional<SRC*> - the SRC section object
179 */
180 std::optional<SRC*> primarySRC() const;
181
182 /**
Matt Spinler131870c2019-09-25 13:29:04 -0500183 * @brief Returns the optional sections, which is everything but
184 * the Private and User Headers.
185 *
186 * @return const std::vector<std::unique_ptr<Section>>&
187 */
188 const std::vector<std::unique_ptr<Section>>& optionalSections() const
189 {
190 return _optionalSections;
191 }
192
193 /**
Matt Spinlercb6b0592019-07-16 15:58:51 -0500194 * @brief Returns the PEL data.
195 *
196 * @return std::vector<uint8_t> - the raw PEL data
197 */
Matt Spinler06885452019-11-06 10:35:42 -0600198 std::vector<uint8_t> data() const;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500199
200 /**
Matt Spinlerf1b46ff2020-01-22 14:10:04 -0600201 * @brief Returns the size of the PEL
202 *
203 * @return size_t The PEL size in bytes
204 */
205 size_t size() const;
206
207 /**
Matt Spinlercb6b0592019-07-16 15:58:51 -0500208 * @brief Says if the PEL is valid (the sections are all valid)
209 *
210 * @return bool - if the PEL is valid
211 */
212 bool valid() const;
213
214 /**
215 * @brief Sets the commit timestamp to the current time
216 */
217 void setCommitTime();
218
219 /**
220 * @brief Sets the error log ID field to a unique ID.
221 */
222 void assignID();
223
Aatir186ce8c2019-10-20 15:13:39 -0500224 /**
225 * @brief Output a PEL in JSON.
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800226 * @param[in] registry - Registry object reference
Aatir186ce8c2019-10-20 15:13:39 -0500227 */
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800228 void toJSON(message::Registry& registry) const;
Aatir186ce8c2019-10-20 15:13:39 -0500229
Matt Spinlerf38ce982019-11-07 13:25:53 -0600230 /**
231 * @brief Sets the host transmission state in the User Header
232 *
233 * @param[in] state - The state value
234 */
235 void setHostTransmissionState(TransmissionState state)
236 {
237 _uh->setHostTransmissionState(static_cast<uint8_t>(state));
238 }
239
240 /**
241 * @brief Returns the host transmission state
242 *
243 * @return HostTransmissionState - The state
244 */
245 TransmissionState hostTransmissionState() const
246 {
247 return static_cast<TransmissionState>(_uh->hostTransmissionState());
248 }
249
250 /**
251 * @brief Sets the HMC transmission state in the User Header
252 *
253 * @param[in] state - The state value
254 */
255 void setHMCTransmissionState(TransmissionState state)
256 {
257 _uh->setHMCTransmissionState(static_cast<uint8_t>(state));
258 }
259
260 /**
261 * @brief Returns the HMC transmission state
262 *
263 * @return HMCTransmissionState - The state
264 */
265 TransmissionState hmcTransmissionState() const
266 {
267 return static_cast<TransmissionState>(_uh->hmcTransmissionState());
268 }
269
Matt Spinlercb6b0592019-07-16 15:58:51 -0500270 private:
271 /**
272 * @brief Builds the section objects from a PEL data buffer
273 *
Matt Spinler07eefc52019-09-26 11:18:26 -0500274 * Note: The data parameter cannot be const for the same reasons
275 * as listed in the constructor.
276 *
277 * @param[in] data - The PEL data
Matt Spinlercb6b0592019-07-16 15:58:51 -0500278 * @param[in] obmcLogID - The OpenBMC event log ID to use for that
279 * field in the Private Header.
280 */
Matt Spinler07eefc52019-09-26 11:18:26 -0500281 void populateFromRawData(std::vector<uint8_t>& data, uint32_t obmcLogID);
Matt Spinlercb6b0592019-07-16 15:58:51 -0500282
283 /**
284 * @brief Flattens the PEL objects into the buffer
285 *
286 * @param[out] pelBuffer - What the data will be written to
287 */
Matt Spinler06885452019-11-06 10:35:42 -0600288 void flatten(std::vector<uint8_t>& pelBuffer) const;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500289
290 /**
Matt Spinlerf1e85e22019-11-01 11:31:31 -0500291 * @brief Check that the PEL fields that need to be in agreement
292 * with each other are, and fix them up if necessary.
293 */
294 void checkRulesAndFix();
295
296 /**
Matt Spinleracb7c102020-01-10 13:49:22 -0600297 * @brief Returns a map of the section IDs that appear more than once
298 * in the PEL. The data value for each entry will be set to 0.
299 *
300 * @return std::map<uint16_t, size_t>
301 */
302 std::map<uint16_t, size_t> getPluralSections() const;
303
304 /**
Matt Spinlercb6b0592019-07-16 15:58:51 -0500305 * @brief The PEL Private Header section
306 */
307 std::unique_ptr<PrivateHeader> _ph;
308
309 /**
310 * @brief The PEL User Header section
311 */
312 std::unique_ptr<UserHeader> _uh;
313
314 /**
Matt Spinler131870c2019-09-25 13:29:04 -0500315 * @brief Holds all sections by the PH and UH.
316 */
317 std::vector<std::unique_ptr<Section>> _optionalSections;
Aatir186ce8c2019-10-20 15:13:39 -0500318
319 /**
320 * @brief helper function for printing PELs.
321 * @param[in] Section& - section object reference
322 * @param[in] std::string - PEL string
Matt Spinleracb7c102020-01-10 13:49:22 -0600323 * @param[in|out] pluralSections - Map used to track sections counts for
324 * when there is more than 1.
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800325 * @param[in] registry - Registry object reference
Aatir186ce8c2019-10-20 15:13:39 -0500326 */
Matt Spinleracb7c102020-01-10 13:49:22 -0600327 void printSectionInJSON(const Section& section, std::string& buf,
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800328 std::map<uint16_t, size_t>& pluralSections,
329 message::Registry& registry) const;
Matt Spinler6d663822020-01-22 14:50:46 -0600330
331 /**
332 * @brief The maximum size a PEL can be in bytes.
333 */
334 static constexpr size_t _maxPELSize = 16384;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500335};
336
Matt Spinlerafa857c2019-10-24 13:03:46 -0500337namespace util
338{
339
340/**
341 * @brief Create a UserData section containing the AdditionalData
342 * contents as a JSON string.
343 *
344 * @param[in] ad - The AdditionalData contents
345 *
346 * @return std::unique_ptr<UserData> - The section
347 */
348std::unique_ptr<UserData> makeADUserDataSection(const AdditionalData& ad);
349
Matt Spinler4dcd3f42020-01-22 14:55:07 -0600350/**
351 * @brief Create a UserData section containing various useful pieces
352 * of system information as a JSON string.
353 *
354 * @param[in] ad - The AdditionalData contents
355 * @param[in] dataIface - The data interface object
356 *
357 * @return std::unique_ptr<UserData> - The section
358 */
359std::unique_ptr<UserData>
360 makeSysInfoUserDataSection(const AdditionalData& ad,
361 const DataInterfaceBase& dataIface);
Matt Spinlerafa857c2019-10-24 13:03:46 -0500362} // namespace util
363
Matt Spinlercb6b0592019-07-16 15:58:51 -0500364} // namespace pels
365} // namespace openpower