blob: 5586187bd94d0f0da7e48650dff115d522393ffd [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 Spinler9d921092022-12-15 11:54:49 -06005#include "journal.hpp"
Matt Spinlercb6b0592019-07-16 15:58:51 -05006#include "private_header.hpp"
Matt Spinlerb8323632019-09-20 15:11:04 -05007#include "registry.hpp"
Matt Spinlerbd716f02019-10-15 10:54:11 -05008#include "src.hpp"
Matt Spinlerafa857c2019-10-24 13:03:46 -05009#include "user_data.hpp"
Matt Spinler56ad2a02020-03-26 14:00:52 -050010#include "user_data_formats.hpp"
Matt Spinlercb6b0592019-07-16 15:58:51 -050011#include "user_header.hpp"
12
13#include <memory>
14#include <vector>
15
16namespace openpower
17{
18namespace pels
19{
20
Matt Spinler56ad2a02020-03-26 14:00:52 -050021/**
22 * @brief Contains information about an FFDC file.
23 */
24struct PelFFDCfile
25{
26 UserDataFormat format;
27 uint8_t subType;
28 uint8_t version;
29 int fd;
30};
31
32using PelFFDC = std::vector<PelFFDCfile>;
Arya K Padmand8ae6182024-07-19 06:25:10 -050033using DebugData = std::map<std::string, std::vector<std::string>>;
Matt Spinler56ad2a02020-03-26 14:00:52 -050034
Jayanth Othayoth1ddf1e82021-06-04 09:00:54 -050035constexpr uint8_t jsonCalloutSubtype = 0xCA;
36
Matt Spinlercb6b0592019-07-16 15:58:51 -050037/** @class PEL
38 *
39 * @brief This class represents a specific event log format referred to as a
40 * Platform Event Log.
41 *
42 * Every field in a PEL are in structures call sections, of which there are
43 * several types. Some sections are required, and some are optional. In some
44 * cases there may be more than one instance of a section type.
45 *
46 * The only two required sections for every type of PEL are the Private Header
47 * section and User Header section, which must be in the first and second
48 * positions, respectively.
49 *
50 * Every section starts with an 8 byte section header, which has the section
51 * size and type, among other things.
52 *
53 * This class represents all sections with objects.
54 *
Matt Spinlerbd716f02019-10-15 10:54:11 -050055 * The class can be constructed:
56 * - From a full formed flattened PEL.
57 * - From scratch based on an OpenBMC event and its corresponding PEL message
58 * registry entry.
Matt Spinlerb8323632019-09-20 15:11:04 -050059 *
Matt Spinlercb6b0592019-07-16 15:58:51 -050060 * The data() method allows one to retrieve the PEL as a vector<uint8_t>. This
61 * is the format in which it is stored and transmitted.
62 */
63class PEL
64{
65 public:
66 PEL() = delete;
67 ~PEL() = default;
68 PEL(const PEL&) = delete;
69 PEL& operator=(const PEL&) = delete;
70 PEL(PEL&&) = delete;
71 PEL& operator=(PEL&&) = delete;
72
73 /**
74 * @brief Constructor
75 *
76 * Build a PEL from raw data.
77 *
Matt Spinler07eefc52019-09-26 11:18:26 -050078 * Note: Neither this nor the following constructor can take a const vector&
79 * because the Stream class that is used to read from the vector cannot take
80 * a const. The alternative is to make a copy of the data, but as PELs can
81 * be up to 16KB that is undesireable.
82 *
Matt Spinlercb6b0592019-07-16 15:58:51 -050083 * @param[in] data - The PEL data
84 */
Matt Spinler45796e82022-07-01 11:25:27 -050085 explicit PEL(std::vector<uint8_t>& data);
Matt Spinlercb6b0592019-07-16 15:58:51 -050086
87 /**
88 * @brief Constructor
89 *
90 * Build a PEL from the raw data.
91 *
92 * @param[in] data - the PEL data
93 * @param[in] obmcLogID - the corresponding OpenBMC event log ID
94 */
Matt Spinler07eefc52019-09-26 11:18:26 -050095 PEL(std::vector<uint8_t>& data, uint32_t obmcLogID);
Matt Spinlercb6b0592019-07-16 15:58:51 -050096
97 /**
Matt Spinlerb8323632019-09-20 15:11:04 -050098 * @brief Constructor
99 *
100 * Creates a PEL from an OpenBMC event log and its message
101 * registry entry.
102 *
103 * @param[in] entry - The message registry entry for this error
104 * @param[in] obmcLogID - ID of corresponding OpenBMC event log
105 * @param[in] timestamp - Timestamp from the event log
106 * @param[in] severity - Severity from the event log
Matt Spinlerbd716f02019-10-15 10:54:11 -0500107 * @param[in] additionalData - The AdditionalData contents
Matt Spinler56ad2a02020-03-26 14:00:52 -0500108 * @param[in] ffdcFiles - FFCD files that go into UserData sections
Matt Spinleraa659472019-10-23 09:26:48 -0500109 * @param[in] dataIface - The data interface object
Matt Spinler9d921092022-12-15 11:54:49 -0600110 * @param[in] journal - The journal object
Matt Spinlerb8323632019-09-20 15:11:04 -0500111 */
112 PEL(const openpower::pels::message::Entry& entry, uint32_t obmcLogID,
Matt Spinlerbd716f02019-10-15 10:54:11 -0500113 uint64_t timestamp, phosphor::logging::Entry::Level severity,
Matt Spinler56ad2a02020-03-26 14:00:52 -0500114 const AdditionalData& additionalData, const PelFFDC& ffdcFiles,
Matt Spinler9d921092022-12-15 11:54:49 -0600115 const DataInterfaceBase& dataIface, const JournalBase& journal);
Matt Spinlerb8323632019-09-20 15:11:04 -0500116
117 /**
Matt Spinlercb6b0592019-07-16 15:58:51 -0500118 * @brief Convenience function to return the log ID field from the
119 * Private Header section.
120 *
121 * @return uint32_t - the ID
122 */
123 uint32_t id() const
124 {
125 return _ph->id();
126 }
127
128 /**
129 * @brief Convenience function to return the PLID field from the
130 * Private Header section.
131 *
132 * @return uint32_t - the PLID
133 */
134 uint32_t plid() const
135 {
136 return _ph->plid();
137 }
138
139 /**
140 * @brief Convenience function to return the OpenBMC event log ID field
141 * from the Private Header section.
142 *
143 * @return uint32_t - the OpenBMC event log ID
144 */
145 uint32_t obmcLogID() const
146 {
147 return _ph->obmcLogID();
148 }
149
150 /**
151 * @brief Convenience function to return the commit time field from
152 * the Private Header section.
153 *
154 * @return BCDTime - the timestamp
155 */
156 BCDTime commitTime() const
157 {
158 return _ph->commitTimestamp();
159 }
160
161 /**
162 * @brief Convenience function to return the create time field from
163 * the Private Header section.
164 *
165 * @return BCDTime - the timestamp
166 */
167 BCDTime createTime() const
168 {
169 return _ph->createTimestamp();
170 }
171
172 /**
173 * @brief Gives access to the Private Header section class
174 *
Matt Spinler97d19b42019-10-29 11:34:03 -0500175 * @return const PrivateHeader& - the private header
Matt Spinlercb6b0592019-07-16 15:58:51 -0500176 */
Matt Spinler97d19b42019-10-29 11:34:03 -0500177 const PrivateHeader& privateHeader() const
Matt Spinlercb6b0592019-07-16 15:58:51 -0500178 {
Matt Spinler97d19b42019-10-29 11:34:03 -0500179 return *_ph;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500180 }
181
182 /**
183 * @brief Gives access to the User Header section class
184 *
Matt Spinler97d19b42019-10-29 11:34:03 -0500185 * @return const UserHeader& - the user header
Matt Spinlercb6b0592019-07-16 15:58:51 -0500186 */
Matt Spinler97d19b42019-10-29 11:34:03 -0500187 const UserHeader& userHeader() const
Matt Spinlercb6b0592019-07-16 15:58:51 -0500188 {
Matt Spinler97d19b42019-10-29 11:34:03 -0500189 return *_uh;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500190 }
191
192 /**
Matt Spinlerbd716f02019-10-15 10:54:11 -0500193 * @brief Gives access to the primary SRC's section class
194 *
195 * This is technically an optional section, so the return
196 * value is an std::optional<SRC*>.
197 *
198 * @return std::optional<SRC*> - the SRC section object
199 */
200 std::optional<SRC*> primarySRC() const;
201
202 /**
Matt Spinler131870c2019-09-25 13:29:04 -0500203 * @brief Returns the optional sections, which is everything but
204 * the Private and User Headers.
205 *
206 * @return const std::vector<std::unique_ptr<Section>>&
207 */
208 const std::vector<std::unique_ptr<Section>>& optionalSections() const
209 {
210 return _optionalSections;
211 }
212
213 /**
Matt Spinlercb6b0592019-07-16 15:58:51 -0500214 * @brief Returns the PEL data.
215 *
216 * @return std::vector<uint8_t> - the raw PEL data
217 */
Matt Spinler06885452019-11-06 10:35:42 -0600218 std::vector<uint8_t> data() const;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500219
220 /**
Matt Spinlerf1b46ff2020-01-22 14:10:04 -0600221 * @brief Returns the size of the PEL
222 *
223 * @return size_t The PEL size in bytes
224 */
225 size_t size() const;
226
227 /**
Matt Spinlercb6b0592019-07-16 15:58:51 -0500228 * @brief Says if the PEL is valid (the sections are all valid)
229 *
230 * @return bool - if the PEL is valid
231 */
232 bool valid() const;
233
234 /**
235 * @brief Sets the commit timestamp to the current time
236 */
237 void setCommitTime();
238
239 /**
240 * @brief Sets the error log ID field to a unique ID.
241 */
242 void assignID();
243
Aatir186ce8c2019-10-20 15:13:39 -0500244 /**
245 * @brief Output a PEL in JSON.
Harisuddin Mohamed Isaa214ed32020-02-28 15:58:23 +0800246 * @param[in] registry - Registry object reference
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800247 * @param[in] plugins - Vector of strings of plugins found in filesystem
Aatir186ce8c2019-10-20 15:13:39 -0500248 */
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800249 void toJSON(message::Registry& registry,
250 const std::vector<std::string>& plugins) const;
Aatir186ce8c2019-10-20 15:13:39 -0500251
Matt Spinlerf38ce982019-11-07 13:25:53 -0600252 /**
253 * @brief Sets the host transmission state in the User Header
254 *
255 * @param[in] state - The state value
256 */
257 void setHostTransmissionState(TransmissionState state)
258 {
259 _uh->setHostTransmissionState(static_cast<uint8_t>(state));
260 }
261
262 /**
263 * @brief Returns the host transmission state
264 *
265 * @return HostTransmissionState - The state
266 */
267 TransmissionState hostTransmissionState() const
268 {
269 return static_cast<TransmissionState>(_uh->hostTransmissionState());
270 }
271
272 /**
273 * @brief Sets the HMC transmission state in the User Header
274 *
275 * @param[in] state - The state value
276 */
277 void setHMCTransmissionState(TransmissionState state)
278 {
279 _uh->setHMCTransmissionState(static_cast<uint8_t>(state));
280 }
281
282 /**
283 * @brief Returns the HMC transmission state
284 *
285 * @return HMCTransmissionState - The state
286 */
287 TransmissionState hmcTransmissionState() const
288 {
289 return static_cast<TransmissionState>(_uh->hmcTransmissionState());
290 }
291
Andrew Geissler44fc3162020-07-09 09:21:31 -0500292 /**
Andrew Geisslerf8e750d2022-01-14 14:56:13 -0600293 * @brief Returns true if a hardware callout is present in the primary SRC
Andrew Geissler44fc3162020-07-09 09:21:31 -0500294 *
Andrew Geisslerf8e750d2022-01-14 14:56:13 -0600295 * @return true if hardware callout present, false otherwise
Andrew Geissler44fc3162020-07-09 09:21:31 -0500296 */
Andrew Geisslerf8e750d2022-01-14 14:56:13 -0600297 bool isHwCalloutPresent() const;
Andrew Geissler44fc3162020-07-09 09:21:31 -0500298
Sumit Kumar3160a542021-04-26 08:07:04 -0500299 /**
300 * @brief Updates the system info data into HB extended user
301 * data section to this PEL object
302 *
303 * @param[in] dataIface - The data interface object
304 */
305 void updateSysInfoInExtendedUserDataSection(
306 const DataInterfaceBase& dataIface);
307
Matt Spinler8e65f4e2023-05-02 13:40:08 -0500308 /**
309 * @brief Return the deconfig flag from hex data word 5 of BMC and
310 * hostboot PELs.
311 *
312 * This only applies to BMC and hostboot PELs because only those
313 * SRC formats have this flag defined.
314 *
315 * @return bool - If the 'one or more resources are deconfigured'
316 * flag is set.
317 */
318 bool getDeconfigFlag() const;
319
320 /**
321 * @brief Return the guard flag from hex data word 5 of BMC and
322 * hostboot PELs.
323 *
324 * This only applies to BMC and hostboot PELs because only those
325 * SRC formats have this flag defined.
326 *
327 * @return bool - If the 'one or more resources are guarded'
328 * flag is set.
329 */
330 bool getGuardFlag() const;
331
Matt Spinlercb6b0592019-07-16 15:58:51 -0500332 private:
333 /**
334 * @brief Builds the section objects from a PEL data buffer
335 *
Matt Spinler07eefc52019-09-26 11:18:26 -0500336 * Note: The data parameter cannot be const for the same reasons
337 * as listed in the constructor.
338 *
339 * @param[in] data - The PEL data
Matt Spinlercb6b0592019-07-16 15:58:51 -0500340 * @param[in] obmcLogID - The OpenBMC event log ID to use for that
341 * field in the Private Header.
342 */
Matt Spinler07eefc52019-09-26 11:18:26 -0500343 void populateFromRawData(std::vector<uint8_t>& data, uint32_t obmcLogID);
Matt Spinlercb6b0592019-07-16 15:58:51 -0500344
345 /**
346 * @brief Flattens the PEL objects into the buffer
347 *
348 * @param[out] pelBuffer - What the data will be written to
349 */
Matt Spinler06885452019-11-06 10:35:42 -0600350 void flatten(std::vector<uint8_t>& pelBuffer) const;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500351
352 /**
Matt Spinlerf1e85e22019-11-01 11:31:31 -0500353 * @brief Check that the PEL fields that need to be in agreement
354 * with each other are, and fix them up if necessary.
355 */
356 void checkRulesAndFix();
357
358 /**
Matt Spinleracb7c102020-01-10 13:49:22 -0600359 * @brief Returns a map of the section IDs that appear more than once
360 * in the PEL. The data value for each entry will be set to 0.
361 *
362 * @return std::map<uint16_t, size_t>
363 */
364 std::map<uint16_t, size_t> getPluralSections() const;
365
366 /**
Matt Spinler85f61a62020-06-03 16:28:55 -0500367 * @brief Adds the UserData section to this PEL object,
368 * shrinking it if necessary
369 *
370 * @param[in] userData - The section to add
371 *
372 * @return bool - If the section was added or not.
373 */
374 bool addUserDataSection(std::unique_ptr<UserData> userData);
375
376 /**
377 * @brief helper function for printing PELs.
378 * @param[in] Section& - section object reference
379 * @param[in] std::string - PEL string
380 * @param[in|out] pluralSections - Map used to track sections counts for
381 * when there is more than 1.
382 * @param[in] registry - Registry object reference
Harisuddin Mohamed Isaf67bafd2020-07-06 17:51:21 +0800383 * @param[in] plugins - Vector of strings of plugins found in filesystem
384 * @param[in] creatorID - Creator Subsystem ID (only for UserData section)
Matt Spinler85f61a62020-06-03 16:28:55 -0500385 */
Patrick Williams075c7922024-08-16 15:19:49 -0400386 void printSectionInJSON(
387 const Section& section, std::string& buf,
388 std::map<uint16_t, size_t>& pluralSections, message::Registry& registry,
389 const std::vector<std::string>& plugins, uint8_t creatorID = 0) const;
Matt Spinler85f61a62020-06-03 16:28:55 -0500390
391 /**
Matt Spinler5a90a952020-08-27 09:39:03 -0500392 * @brief Returns any callout JSON found in the FFDC files.
393 *
394 * Looks for an FFDC file that is JSON format and has the
395 * sub-type value set to 0xCA and returns its data as a JSON object.
396 *
397 * @param[in] ffdcFiles - FFCD files that go into UserData sections
398 *
399 * @return json - The callout JSON, or an empty object if not found
400 */
401 nlohmann::json getCalloutJSON(const PelFFDC& ffdcFiles);
402
403 /**
Sumit Kumar3e274432021-09-14 06:37:56 -0500404 * @brief Update terminate bit in primary SRC section to this PEL object is
405 * severity set to 0x51 = critical error, system termination
406 */
407 void updateTerminateBitInSRCSection();
408
409 /**
Matt Spinler9d921092022-12-15 11:54:49 -0600410 * @brief Adds journal data to the PEL as UserData sections
411 * if specified to in the message registry.
412 *
413 * @param regEntry - The registry entry
414 * @param journal - The journal object
415 */
416 void addJournalSections(const message::Entry& regEntry,
417 const JournalBase& journal);
418
419 /**
Arya K Padmand8ae6182024-07-19 06:25:10 -0500420 * @brief API to collect the addditional details of the DIMM callouts in
421 * the PEL as a JSON object in adSysInfoData.
422 *
423 * @param[in] src - Unique pointer to the SRC object
424 * @param[in] dataIface - The data interface object
425 * @param[out] adSysInfoData - The additional data to SysInfo in json format
426 * @param[out] debugData - The map of string and vector of string to store
427 * the debug data if any.
428 */
429 void addAdDetailsForDIMMsCallout(
430 const std::unique_ptr<SRC>& src, const DataInterfaceBase& dataIface,
431 nlohmann::json& adSysInfoData, DebugData& debugData);
432
433 /**
Matt Spinlercb6b0592019-07-16 15:58:51 -0500434 * @brief The PEL Private Header section
435 */
436 std::unique_ptr<PrivateHeader> _ph;
437
438 /**
439 * @brief The PEL User Header section
440 */
441 std::unique_ptr<UserHeader> _uh;
442
443 /**
Matt Spinler131870c2019-09-25 13:29:04 -0500444 * @brief Holds all sections by the PH and UH.
445 */
446 std::vector<std::unique_ptr<Section>> _optionalSections;
Aatir186ce8c2019-10-20 15:13:39 -0500447
448 /**
Matt Spinler6d663822020-01-22 14:50:46 -0600449 * @brief The maximum size a PEL can be in bytes.
450 */
451 static constexpr size_t _maxPELSize = 16384;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500452};
453
Matt Spinlerafa857c2019-10-24 13:03:46 -0500454namespace util
455{
456
457/**
Matt Spinler85f61a62020-06-03 16:28:55 -0500458 * @brief Creates a UserData section object that contains JSON.
459 *
460 * @param[in] json - The JSON contents
461 *
462 * @return std::unique_ptr<UserData> - The UserData object
463 */
464std::unique_ptr<UserData> makeJSONUserDataSection(const nlohmann::json& json);
465
466/**
Matt Spinlerafa857c2019-10-24 13:03:46 -0500467 * @brief Create a UserData section containing the AdditionalData
468 * contents as a JSON string.
469 *
470 * @param[in] ad - The AdditionalData contents
471 *
472 * @return std::unique_ptr<UserData> - The section
473 */
474std::unique_ptr<UserData> makeADUserDataSection(const AdditionalData& ad);
475
Matt Spinler4dcd3f42020-01-22 14:55:07 -0600476/**
477 * @brief Create a UserData section containing various useful pieces
478 * of system information as a JSON string.
479 *
480 * @param[in] ad - The AdditionalData contents
481 * @param[in] dataIface - The data interface object
George Liu9ac0d9b2022-07-15 10:57:38 +0800482 * @param[in] addUptime - Whether to add the uptime attribute the default is
483 * true
Arya K Padmand8ae6182024-07-19 06:25:10 -0500484 * @param[in] adSysInfoData - The additional data to SysInfo in json format.
485 * Default value will be empty.
Matt Spinler4dcd3f42020-01-22 14:55:07 -0600486 *
487 * @return std::unique_ptr<UserData> - The section
488 */
Patrick Williams075c7922024-08-16 15:19:49 -0400489std::unique_ptr<UserData> makeSysInfoUserDataSection(
490 const AdditionalData& ad, const DataInterfaceBase& dataIface,
Arya K Padmand8ae6182024-07-19 06:25:10 -0500491 bool addUptime = true,
492 const nlohmann::json& adSysInfoData =
493 nlohmann::json(nlohmann::json::value_t::object));
Matt Spinler56ad2a02020-03-26 14:00:52 -0500494
495/**
Matt Spinler5a90a952020-08-27 09:39:03 -0500496 * @brief Reads data from an opened file descriptor.
497 *
498 * @param[in] fd - The FD to read from
499 *
500 * @return std::vector<uint8_t> - The data read
501 */
502std::vector<uint8_t> readFD(int fd);
503
504/**
Matt Spinler56ad2a02020-03-26 14:00:52 -0500505 * @brief Create a UserData section that contains the data in the file
506 * pointed to by the file descriptor passed in.
507 *
508 * @param[in] componentID - The component ID of the PEL creator
509 * @param[in] file - The FFDC file information
510 */
Patrick Williams075c7922024-08-16 15:19:49 -0400511std::unique_ptr<UserData>
512 makeFFDCuserDataSection(uint16_t componentID, const PelFFDCfile& file);
Matt Spinler9d921092022-12-15 11:54:49 -0600513
514/**
Arya K Padmand8ae6182024-07-19 06:25:10 -0500515 * @brief To create JSON object with the given location code and the hex
516 * converted value of the given DI property.
517 *
518 * @param[in] locationCode - The location code of the DIMM
519 * @param[in] diPropVal - The DI property value of the DIMM
520 * @param[out] adSysInfoData - Holds the created JSON object
521 */
522
523void addDIMMInfo(const std::string& locationCode,
524 const std::vector<std::uint8_t>& diPropVal,
525 nlohmann::json& adSysInfoData);
526
527/**
Matt Spinler9d921092022-12-15 11:54:49 -0600528 * @brief Flattens a vector of strings into a vector of bytes suitable
529 * for storing in a PEL section.
530 *
531 * Adds a newline character after each string.
532 *
533 * @param lines - The vector of strings to convert
534 *
535 * @return std::vector<uint8_t> - The flattened data
536 */
537std::vector<uint8_t> flattenLines(const std::vector<std::string>& lines);
538
Matt Spinlerafa857c2019-10-24 13:03:46 -0500539} // namespace util
540
Matt Spinlercb6b0592019-07-16 15:58:51 -0500541} // namespace pels
542} // namespace openpower