blob: 8b592f7a6b8d3e1126974246edc18d3e4477a500 [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 Spinler56ad2a02020-03-26 14:00:52 -05009#include "user_data_formats.hpp"
Matt Spinlercb6b0592019-07-16 15:58:51 -050010#include "user_header.hpp"
11
12#include <memory>
13#include <vector>
14
15namespace openpower
16{
17namespace pels
18{
19
Matt Spinler56ad2a02020-03-26 14:00:52 -050020/**
21 * @brief Contains information about an FFDC file.
22 */
23struct PelFFDCfile
24{
25 UserDataFormat format;
26 uint8_t subType;
27 uint8_t version;
28 int fd;
29};
30
31using PelFFDC = std::vector<PelFFDCfile>;
32
Matt Spinlercb6b0592019-07-16 15:58:51 -050033/** @class PEL
34 *
35 * @brief This class represents a specific event log format referred to as a
36 * Platform Event Log.
37 *
38 * Every field in a PEL are in structures call sections, of which there are
39 * several types. Some sections are required, and some are optional. In some
40 * cases there may be more than one instance of a section type.
41 *
42 * The only two required sections for every type of PEL are the Private Header
43 * section and User Header section, which must be in the first and second
44 * positions, respectively.
45 *
46 * Every section starts with an 8 byte section header, which has the section
47 * size and type, among other things.
48 *
49 * This class represents all sections with objects.
50 *
Matt Spinlerbd716f02019-10-15 10:54:11 -050051 * The class can be constructed:
52 * - From a full formed flattened PEL.
53 * - From scratch based on an OpenBMC event and its corresponding PEL message
54 * registry entry.
Matt Spinlerb8323632019-09-20 15:11:04 -050055 *
Matt Spinlercb6b0592019-07-16 15:58:51 -050056 * The data() method allows one to retrieve the PEL as a vector<uint8_t>. This
57 * is the format in which it is stored and transmitted.
58 */
59class PEL
60{
61 public:
62 PEL() = delete;
63 ~PEL() = default;
64 PEL(const PEL&) = delete;
65 PEL& operator=(const PEL&) = delete;
66 PEL(PEL&&) = delete;
67 PEL& operator=(PEL&&) = delete;
68
69 /**
70 * @brief Constructor
71 *
72 * Build a PEL from raw data.
73 *
Matt Spinler07eefc52019-09-26 11:18:26 -050074 * Note: Neither this nor the following constructor can take a const vector&
75 * because the Stream class that is used to read from the vector cannot take
76 * a const. The alternative is to make a copy of the data, but as PELs can
77 * be up to 16KB that is undesireable.
78 *
Matt Spinlercb6b0592019-07-16 15:58:51 -050079 * @param[in] data - The PEL data
80 */
Matt Spinler07eefc52019-09-26 11:18:26 -050081 PEL(std::vector<uint8_t>& data);
Matt Spinlercb6b0592019-07-16 15:58:51 -050082
83 /**
84 * @brief Constructor
85 *
86 * Build a PEL from the raw data.
87 *
88 * @param[in] data - the PEL data
89 * @param[in] obmcLogID - the corresponding OpenBMC event log ID
90 */
Matt Spinler07eefc52019-09-26 11:18:26 -050091 PEL(std::vector<uint8_t>& data, uint32_t obmcLogID);
Matt Spinlercb6b0592019-07-16 15:58:51 -050092
93 /**
Matt Spinlerb8323632019-09-20 15:11:04 -050094 * @brief Constructor
95 *
96 * Creates a PEL from an OpenBMC event log and its message
97 * registry entry.
98 *
99 * @param[in] entry - The message registry entry for this error
100 * @param[in] obmcLogID - ID of corresponding OpenBMC event log
101 * @param[in] timestamp - Timestamp from the event log
102 * @param[in] severity - Severity from the event log
Matt Spinlerbd716f02019-10-15 10:54:11 -0500103 * @param[in] additionalData - The AdditionalData contents
Matt Spinler56ad2a02020-03-26 14:00:52 -0500104 * @param[in] ffdcFiles - FFCD files that go into UserData sections
Matt Spinleraa659472019-10-23 09:26:48 -0500105 * @param[in] dataIface - The data interface object
Matt Spinlerb8323632019-09-20 15:11:04 -0500106 */
107 PEL(const openpower::pels::message::Entry& entry, uint32_t obmcLogID,
Matt Spinlerbd716f02019-10-15 10:54:11 -0500108 uint64_t timestamp, phosphor::logging::Entry::Level severity,
Matt Spinler56ad2a02020-03-26 14:00:52 -0500109 const AdditionalData& additionalData, const PelFFDC& ffdcFiles,
Matt Spinleraa659472019-10-23 09:26:48 -0500110 const DataInterfaceBase& dataIface);
Matt Spinlerb8323632019-09-20 15:11:04 -0500111
112 /**
Matt Spinlercb6b0592019-07-16 15:58:51 -0500113 * @brief Convenience function to return the log ID field from the
114 * Private Header section.
115 *
116 * @return uint32_t - the ID
117 */
118 uint32_t id() const
119 {
120 return _ph->id();
121 }
122
123 /**
124 * @brief Convenience function to return the PLID field from the
125 * Private Header section.
126 *
127 * @return uint32_t - the PLID
128 */
129 uint32_t plid() const
130 {
131 return _ph->plid();
132 }
133
134 /**
135 * @brief Convenience function to return the OpenBMC event log ID field
136 * from the Private Header section.
137 *
138 * @return uint32_t - the OpenBMC event log ID
139 */
140 uint32_t obmcLogID() const
141 {
142 return _ph->obmcLogID();
143 }
144
145 /**
146 * @brief Convenience function to return the commit time field from
147 * the Private Header section.
148 *
149 * @return BCDTime - the timestamp
150 */
151 BCDTime commitTime() const
152 {
153 return _ph->commitTimestamp();
154 }
155
156 /**
157 * @brief Convenience function to return the create time field from
158 * the Private Header section.
159 *
160 * @return BCDTime - the timestamp
161 */
162 BCDTime createTime() const
163 {
164 return _ph->createTimestamp();
165 }
166
167 /**
168 * @brief Gives access to the Private Header section class
169 *
Matt Spinler97d19b42019-10-29 11:34:03 -0500170 * @return const PrivateHeader& - the private header
Matt Spinlercb6b0592019-07-16 15:58:51 -0500171 */
Matt Spinler97d19b42019-10-29 11:34:03 -0500172 const PrivateHeader& privateHeader() const
Matt Spinlercb6b0592019-07-16 15:58:51 -0500173 {
Matt Spinler97d19b42019-10-29 11:34:03 -0500174 return *_ph;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500175 }
176
177 /**
178 * @brief Gives access to the User Header section class
179 *
Matt Spinler97d19b42019-10-29 11:34:03 -0500180 * @return const UserHeader& - the user header
Matt Spinlercb6b0592019-07-16 15:58:51 -0500181 */
Matt Spinler97d19b42019-10-29 11:34:03 -0500182 const UserHeader& userHeader() const
Matt Spinlercb6b0592019-07-16 15:58:51 -0500183 {
Matt Spinler97d19b42019-10-29 11:34:03 -0500184 return *_uh;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500185 }
186
187 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -0500188 * @brief Gives access to the primary SRC's section class
189 *
190 * This is technically an optional section, so the return
191 * value is an std::optional<SRC*>.
192 *
193 * @return std::optional<SRC*> - the SRC section object
194 */
195 std::optional<SRC*> primarySRC() const;
196
197 /**
Matt Spinler131870c2019-09-25 13:29:04 -0500198 * @brief Returns the optional sections, which is everything but
199 * the Private and User Headers.
200 *
201 * @return const std::vector<std::unique_ptr<Section>>&
202 */
203 const std::vector<std::unique_ptr<Section>>& optionalSections() const
204 {
205 return _optionalSections;
206 }
207
208 /**
Matt Spinlercb6b0592019-07-16 15:58:51 -0500209 * @brief Returns the PEL data.
210 *
211 * @return std::vector<uint8_t> - the raw PEL data
212 */
Matt Spinler06885452019-11-06 10:35:42 -0600213 std::vector<uint8_t> data() const;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500214
215 /**
Matt Spinlerf1b46ff2020-01-22 14:10:04 -0600216 * @brief Returns the size of the PEL
217 *
218 * @return size_t The PEL size in bytes
219 */
220 size_t size() const;
221
222 /**
Matt Spinlercb6b0592019-07-16 15:58:51 -0500223 * @brief Says if the PEL is valid (the sections are all valid)
224 *
225 * @return bool - if the PEL is valid
226 */
227 bool valid() const;
228
229 /**
230 * @brief Sets the commit timestamp to the current time
231 */
232 void setCommitTime();
233
234 /**
235 * @brief Sets the error log ID field to a unique ID.
236 */
237 void assignID();
238
Aatir186ce8c2019-10-20 15:13:39 -0500239 /**
240 * @brief Output a PEL in JSON.
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800241 * @param[in] registry - Registry object reference
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800242 * @param[in] plugins - Vector of strings of plugins found in filesystem
Aatir186ce8c2019-10-20 15:13:39 -0500243 */
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800244 void toJSON(message::Registry& registry,
245 const std::vector<std::string>& plugins) const;
Aatir186ce8c2019-10-20 15:13:39 -0500246
Matt Spinlerf38ce982019-11-07 13:25:53 -0600247 /**
248 * @brief Sets the host transmission state in the User Header
249 *
250 * @param[in] state - The state value
251 */
252 void setHostTransmissionState(TransmissionState state)
253 {
254 _uh->setHostTransmissionState(static_cast<uint8_t>(state));
255 }
256
257 /**
258 * @brief Returns the host transmission state
259 *
260 * @return HostTransmissionState - The state
261 */
262 TransmissionState hostTransmissionState() const
263 {
264 return static_cast<TransmissionState>(_uh->hostTransmissionState());
265 }
266
267 /**
268 * @brief Sets the HMC transmission state in the User Header
269 *
270 * @param[in] state - The state value
271 */
272 void setHMCTransmissionState(TransmissionState state)
273 {
274 _uh->setHMCTransmissionState(static_cast<uint8_t>(state));
275 }
276
277 /**
278 * @brief Returns the HMC transmission state
279 *
280 * @return HMCTransmissionState - The state
281 */
282 TransmissionState hmcTransmissionState() const
283 {
284 return static_cast<TransmissionState>(_uh->hmcTransmissionState());
285 }
286
Andrew Geissler44fc3162020-07-09 09:21:31 -0500287 /**
288 * @brief Returns true if any callout is present in the primary SRC
289 *
290 * @return true if callout present, false otherwise
291 */
292 bool isCalloutPresent() const;
293
Sumit Kumar3160a542021-04-26 08:07:04 -0500294 /**
295 * @brief Updates the system info data into HB extended user
296 * data section to this PEL object
297 *
298 * @param[in] dataIface - The data interface object
299 */
300 void updateSysInfoInExtendedUserDataSection(
301 const DataInterfaceBase& dataIface);
302
Matt Spinlercb6b0592019-07-16 15:58:51 -0500303 private:
304 /**
305 * @brief Builds the section objects from a PEL data buffer
306 *
Matt Spinler07eefc52019-09-26 11:18:26 -0500307 * Note: The data parameter cannot be const for the same reasons
308 * as listed in the constructor.
309 *
310 * @param[in] data - The PEL data
Matt Spinlercb6b0592019-07-16 15:58:51 -0500311 * @param[in] obmcLogID - The OpenBMC event log ID to use for that
312 * field in the Private Header.
313 */
Matt Spinler07eefc52019-09-26 11:18:26 -0500314 void populateFromRawData(std::vector<uint8_t>& data, uint32_t obmcLogID);
Matt Spinlercb6b0592019-07-16 15:58:51 -0500315
316 /**
317 * @brief Flattens the PEL objects into the buffer
318 *
319 * @param[out] pelBuffer - What the data will be written to
320 */
Matt Spinler06885452019-11-06 10:35:42 -0600321 void flatten(std::vector<uint8_t>& pelBuffer) const;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500322
323 /**
Matt Spinlerf1e85e22019-11-01 11:31:31 -0500324 * @brief Check that the PEL fields that need to be in agreement
325 * with each other are, and fix them up if necessary.
326 */
327 void checkRulesAndFix();
328
329 /**
Matt Spinleracb7c102020-01-10 13:49:22 -0600330 * @brief Returns a map of the section IDs that appear more than once
331 * in the PEL. The data value for each entry will be set to 0.
332 *
333 * @return std::map<uint16_t, size_t>
334 */
335 std::map<uint16_t, size_t> getPluralSections() const;
336
337 /**
Matt Spinler85f61a62020-06-03 16:28:55 -0500338 * @brief Adds the UserData section to this PEL object,
339 * shrinking it if necessary
340 *
341 * @param[in] userData - The section to add
342 *
343 * @return bool - If the section was added or not.
344 */
345 bool addUserDataSection(std::unique_ptr<UserData> userData);
346
347 /**
348 * @brief helper function for printing PELs.
349 * @param[in] Section& - section object reference
350 * @param[in] std::string - PEL string
351 * @param[in|out] pluralSections - Map used to track sections counts for
352 * when there is more than 1.
353 * @param[in] registry - Registry object reference
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800354 * @param[in] plugins - Vector of strings of plugins found in filesystem
355 * @param[in] creatorID - Creator Subsystem ID (only for UserData section)
Matt Spinler85f61a62020-06-03 16:28:55 -0500356 */
357 void printSectionInJSON(const Section& section, std::string& buf,
358 std::map<uint16_t, size_t>& pluralSections,
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800359 message::Registry& registry,
360 const std::vector<std::string>& plugins,
361 uint8_t creatorID = 0) const;
Matt Spinler85f61a62020-06-03 16:28:55 -0500362
363 /**
Matt Spinler5a90a952020-08-27 09:39:03 -0500364 * @brief Returns any callout JSON found in the FFDC files.
365 *
366 * Looks for an FFDC file that is JSON format and has the
367 * sub-type value set to 0xCA and returns its data as a JSON object.
368 *
369 * @param[in] ffdcFiles - FFCD files that go into UserData sections
370 *
371 * @return json - The callout JSON, or an empty object if not found
372 */
373 nlohmann::json getCalloutJSON(const PelFFDC& ffdcFiles);
374
375 /**
Matt Spinlercb6b0592019-07-16 15:58:51 -0500376 * @brief The PEL Private Header section
377 */
378 std::unique_ptr<PrivateHeader> _ph;
379
380 /**
381 * @brief The PEL User Header section
382 */
383 std::unique_ptr<UserHeader> _uh;
384
385 /**
Matt Spinler131870c2019-09-25 13:29:04 -0500386 * @brief Holds all sections by the PH and UH.
387 */
388 std::vector<std::unique_ptr<Section>> _optionalSections;
Aatir186ce8c2019-10-20 15:13:39 -0500389
390 /**
Matt Spinler6d663822020-01-22 14:50:46 -0600391 * @brief The maximum size a PEL can be in bytes.
392 */
393 static constexpr size_t _maxPELSize = 16384;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500394};
395
Matt Spinlerafa857c2019-10-24 13:03:46 -0500396namespace util
397{
398
399/**
Matt Spinler85f61a62020-06-03 16:28:55 -0500400 * @brief Creates a UserData section object that contains JSON.
401 *
402 * @param[in] json - The JSON contents
403 *
404 * @return std::unique_ptr<UserData> - The UserData object
405 */
406std::unique_ptr<UserData> makeJSONUserDataSection(const nlohmann::json& json);
407
408/**
Matt Spinlerafa857c2019-10-24 13:03:46 -0500409 * @brief Create a UserData section containing the AdditionalData
410 * contents as a JSON string.
411 *
412 * @param[in] ad - The AdditionalData contents
413 *
414 * @return std::unique_ptr<UserData> - The section
415 */
416std::unique_ptr<UserData> makeADUserDataSection(const AdditionalData& ad);
417
Matt Spinler4dcd3f42020-01-22 14:55:07 -0600418/**
419 * @brief Create a UserData section containing various useful pieces
420 * of system information as a JSON string.
421 *
422 * @param[in] ad - The AdditionalData contents
423 * @param[in] dataIface - The data interface object
424 *
425 * @return std::unique_ptr<UserData> - The section
426 */
427std::unique_ptr<UserData>
428 makeSysInfoUserDataSection(const AdditionalData& ad,
429 const DataInterfaceBase& dataIface);
Matt Spinler56ad2a02020-03-26 14:00:52 -0500430
431/**
Matt Spinler5a90a952020-08-27 09:39:03 -0500432 * @brief Reads data from an opened file descriptor.
433 *
434 * @param[in] fd - The FD to read from
435 *
436 * @return std::vector<uint8_t> - The data read
437 */
438std::vector<uint8_t> readFD(int fd);
439
440/**
Matt Spinler56ad2a02020-03-26 14:00:52 -0500441 * @brief Create a UserData section that contains the data in the file
442 * pointed to by the file descriptor passed in.
443 *
444 * @param[in] componentID - The component ID of the PEL creator
445 * @param[in] file - The FFDC file information
446 */
447std::unique_ptr<UserData> makeFFDCuserDataSection(uint16_t componentID,
448 const PelFFDCfile& file);
Matt Spinlerafa857c2019-10-24 13:03:46 -0500449} // namespace util
450
Matt Spinlercb6b0592019-07-16 15:58:51 -0500451} // namespace pels
452} // namespace openpower