1cb6b059eSMatt Spinler #pragma once
2cb6b059eSMatt Spinler 
3b832363dSMatt Spinler #include "additional_data.hpp"
4aa659477SMatt Spinler #include "data_interface.hpp"
5cb6b059eSMatt Spinler #include "private_header.hpp"
6b832363dSMatt Spinler #include "registry.hpp"
7bd716f00SMatt Spinler #include "src.hpp"
8afa857c7SMatt Spinler #include "user_data.hpp"
9cb6b059eSMatt Spinler #include "user_header.hpp"
10cb6b059eSMatt Spinler 
11cb6b059eSMatt Spinler #include <memory>
12cb6b059eSMatt Spinler #include <vector>
13cb6b059eSMatt Spinler 
14cb6b059eSMatt Spinler namespace openpower
15cb6b059eSMatt Spinler {
16cb6b059eSMatt Spinler namespace pels
17cb6b059eSMatt Spinler {
18cb6b059eSMatt Spinler 
19cb6b059eSMatt Spinler /** @class PEL
20cb6b059eSMatt Spinler  *
21cb6b059eSMatt Spinler  * @brief This class represents a specific event log format referred to as a
22cb6b059eSMatt Spinler  * Platform Event Log.
23cb6b059eSMatt Spinler  *
24cb6b059eSMatt Spinler  * Every field in a PEL are in structures call sections, of which there are
25cb6b059eSMatt Spinler  * several types.  Some sections are required, and some are optional.  In some
26cb6b059eSMatt Spinler  * cases there may be more than one instance of a section type.
27cb6b059eSMatt Spinler  *
28cb6b059eSMatt Spinler  * The only two required sections for every type of PEL are the Private Header
29cb6b059eSMatt Spinler  * section and User Header section, which must be in the first and second
30cb6b059eSMatt Spinler  * positions, respectively.
31cb6b059eSMatt Spinler  *
32cb6b059eSMatt Spinler  * Every section starts with an 8 byte section header, which has the section
33cb6b059eSMatt Spinler  * size and type, among other things.
34cb6b059eSMatt Spinler  *
35cb6b059eSMatt Spinler  * This class represents all sections with objects.
36cb6b059eSMatt Spinler  *
37bd716f00SMatt Spinler  * The class can be constructed:
38bd716f00SMatt Spinler  * - From a full formed flattened PEL.
39bd716f00SMatt Spinler  * - From scratch based on an OpenBMC event and its corresponding PEL message
40bd716f00SMatt Spinler  *   registry entry.
41b832363dSMatt Spinler  *
42cb6b059eSMatt Spinler  * The data() method allows one to retrieve the PEL as a vector<uint8_t>.  This
43cb6b059eSMatt Spinler  * is the format in which it is stored and transmitted.
44cb6b059eSMatt Spinler  */
45cb6b059eSMatt Spinler class PEL
46cb6b059eSMatt Spinler {
47cb6b059eSMatt Spinler   public:
48cb6b059eSMatt Spinler     PEL() = delete;
49cb6b059eSMatt Spinler     ~PEL() = default;
50cb6b059eSMatt Spinler     PEL(const PEL&) = delete;
51cb6b059eSMatt Spinler     PEL& operator=(const PEL&) = delete;
52cb6b059eSMatt Spinler     PEL(PEL&&) = delete;
53cb6b059eSMatt Spinler     PEL& operator=(PEL&&) = delete;
54cb6b059eSMatt Spinler 
55cb6b059eSMatt Spinler     /**
56cb6b059eSMatt Spinler      * @brief Constructor
57cb6b059eSMatt Spinler      *
58cb6b059eSMatt Spinler      * Build a PEL from raw data.
59cb6b059eSMatt Spinler      *
6007eefc54SMatt Spinler      * Note: Neither this nor the following constructor can take a const vector&
6107eefc54SMatt Spinler      * because the Stream class that is used to read from the vector cannot take
6207eefc54SMatt Spinler      * a const.  The alternative is to make a copy of the data, but as PELs can
6307eefc54SMatt Spinler      * be up to 16KB that is undesireable.
6407eefc54SMatt Spinler      *
65cb6b059eSMatt Spinler      * @param[in] data - The PEL data
66cb6b059eSMatt Spinler      */
6707eefc54SMatt Spinler     PEL(std::vector<uint8_t>& data);
68cb6b059eSMatt Spinler 
69cb6b059eSMatt Spinler     /**
70cb6b059eSMatt Spinler      * @brief Constructor
71cb6b059eSMatt Spinler      *
72cb6b059eSMatt Spinler      * Build a PEL from the raw data.
73cb6b059eSMatt Spinler      *
74cb6b059eSMatt Spinler      * @param[in] data - the PEL data
75cb6b059eSMatt Spinler      * @param[in] obmcLogID - the corresponding OpenBMC event log ID
76cb6b059eSMatt Spinler      */
7707eefc54SMatt Spinler     PEL(std::vector<uint8_t>& data, uint32_t obmcLogID);
78cb6b059eSMatt Spinler 
79cb6b059eSMatt Spinler     /**
80b832363dSMatt Spinler      * @brief Constructor
81b832363dSMatt Spinler      *
82b832363dSMatt Spinler      * Creates a PEL from an OpenBMC event log and its message
83b832363dSMatt Spinler      * registry entry.
84b832363dSMatt Spinler      *
85b832363dSMatt Spinler      * @param[in] entry - The message registry entry for this error
86b832363dSMatt Spinler      * @param[in] obmcLogID - ID of corresponding OpenBMC event log
87b832363dSMatt Spinler      * @param[in] timestamp - Timestamp from the event log
88b832363dSMatt Spinler      * @param[in] severity - Severity from the event log
89bd716f00SMatt Spinler      * @param[in] additionalData - The AdditionalData contents
90aa659477SMatt Spinler      * @param[in] dataIface - The data interface object
91b832363dSMatt Spinler      */
92b832363dSMatt Spinler     PEL(const openpower::pels::message::Entry& entry, uint32_t obmcLogID,
93bd716f00SMatt Spinler         uint64_t timestamp, phosphor::logging::Entry::Level severity,
94aa659477SMatt Spinler         const AdditionalData& additionalData,
95aa659477SMatt Spinler         const DataInterfaceBase& dataIface);
96b832363dSMatt Spinler 
97b832363dSMatt Spinler     /**
98cb6b059eSMatt Spinler      * @brief Convenience function to return the log ID field from the
99cb6b059eSMatt Spinler      *        Private Header section.
100cb6b059eSMatt Spinler      *
101cb6b059eSMatt Spinler      * @return uint32_t - the ID
102cb6b059eSMatt Spinler      */
103cb6b059eSMatt Spinler     uint32_t id() const
104cb6b059eSMatt Spinler     {
105cb6b059eSMatt Spinler         return _ph->id();
106cb6b059eSMatt Spinler     }
107cb6b059eSMatt Spinler 
108cb6b059eSMatt Spinler     /**
109cb6b059eSMatt Spinler      * @brief Convenience function to return the PLID field from the
110cb6b059eSMatt Spinler      *        Private Header section.
111cb6b059eSMatt Spinler      *
112cb6b059eSMatt Spinler      * @return uint32_t - the PLID
113cb6b059eSMatt Spinler      */
114cb6b059eSMatt Spinler     uint32_t plid() const
115cb6b059eSMatt Spinler     {
116cb6b059eSMatt Spinler         return _ph->plid();
117cb6b059eSMatt Spinler     }
118cb6b059eSMatt Spinler 
119cb6b059eSMatt Spinler     /**
120cb6b059eSMatt Spinler      * @brief Convenience function to return the OpenBMC event log ID field
121cb6b059eSMatt Spinler      * from the Private Header section.
122cb6b059eSMatt Spinler      *
123cb6b059eSMatt Spinler      * @return uint32_t - the OpenBMC event log ID
124cb6b059eSMatt Spinler      */
125cb6b059eSMatt Spinler     uint32_t obmcLogID() const
126cb6b059eSMatt Spinler     {
127cb6b059eSMatt Spinler         return _ph->obmcLogID();
128cb6b059eSMatt Spinler     }
129cb6b059eSMatt Spinler 
130cb6b059eSMatt Spinler     /**
131cb6b059eSMatt Spinler      * @brief Convenience function to return the commit time field from
132cb6b059eSMatt Spinler      *        the Private Header section.
133cb6b059eSMatt Spinler      *
134cb6b059eSMatt Spinler      * @return BCDTime - the timestamp
135cb6b059eSMatt Spinler      */
136cb6b059eSMatt Spinler     BCDTime commitTime() const
137cb6b059eSMatt Spinler     {
138cb6b059eSMatt Spinler         return _ph->commitTimestamp();
139cb6b059eSMatt Spinler     }
140cb6b059eSMatt Spinler 
141cb6b059eSMatt Spinler     /**
142cb6b059eSMatt Spinler      * @brief Convenience function to return the create time field from
143cb6b059eSMatt Spinler      *        the Private Header section.
144cb6b059eSMatt Spinler      *
145cb6b059eSMatt Spinler      * @return BCDTime - the timestamp
146cb6b059eSMatt Spinler      */
147cb6b059eSMatt Spinler     BCDTime createTime() const
148cb6b059eSMatt Spinler     {
149cb6b059eSMatt Spinler         return _ph->createTimestamp();
150cb6b059eSMatt Spinler     }
151cb6b059eSMatt Spinler 
152cb6b059eSMatt Spinler     /**
153cb6b059eSMatt Spinler      * @brief Gives access to the Private Header section class
154cb6b059eSMatt Spinler      *
15597d19b48SMatt Spinler      * @return const PrivateHeader& - the private header
156cb6b059eSMatt Spinler      */
15797d19b48SMatt Spinler     const PrivateHeader& privateHeader() const
158cb6b059eSMatt Spinler     {
15997d19b48SMatt Spinler         return *_ph;
160cb6b059eSMatt Spinler     }
161cb6b059eSMatt Spinler 
162cb6b059eSMatt Spinler     /**
163cb6b059eSMatt Spinler      * @brief Gives access to the User Header section class
164cb6b059eSMatt Spinler      *
16597d19b48SMatt Spinler      * @return const UserHeader& - the user header
166cb6b059eSMatt Spinler      */
16797d19b48SMatt Spinler     const UserHeader& userHeader() const
168cb6b059eSMatt Spinler     {
16997d19b48SMatt Spinler         return *_uh;
170cb6b059eSMatt Spinler     }
171cb6b059eSMatt Spinler 
172cb6b059eSMatt Spinler     /**
173bd716f00SMatt Spinler      * @brief Gives access to the primary SRC's section class
174bd716f00SMatt Spinler      *
175bd716f00SMatt Spinler      * This is technically an optional section, so the return
176bd716f00SMatt Spinler      * value is an std::optional<SRC*>.
177bd716f00SMatt Spinler      *
178bd716f00SMatt Spinler      * @return std::optional<SRC*> - the SRC section object
179bd716f00SMatt Spinler      */
180bd716f00SMatt Spinler     std::optional<SRC*> primarySRC() const;
181bd716f00SMatt Spinler 
182bd716f00SMatt Spinler     /**
183131870c7SMatt Spinler      * @brief Returns the optional sections, which is everything but
184131870c7SMatt Spinler      *        the Private and User Headers.
185131870c7SMatt Spinler      *
186131870c7SMatt Spinler      * @return const std::vector<std::unique_ptr<Section>>&
187131870c7SMatt Spinler      */
188131870c7SMatt Spinler     const std::vector<std::unique_ptr<Section>>& optionalSections() const
189131870c7SMatt Spinler     {
190131870c7SMatt Spinler         return _optionalSections;
191131870c7SMatt Spinler     }
192131870c7SMatt Spinler 
193131870c7SMatt Spinler     /**
194cb6b059eSMatt Spinler      * @brief Returns the PEL data.
195cb6b059eSMatt Spinler      *
196cb6b059eSMatt Spinler      * @return std::vector<uint8_t> - the raw PEL data
197cb6b059eSMatt Spinler      */
1980688545bSMatt Spinler     std::vector<uint8_t> data() const;
199cb6b059eSMatt Spinler 
200cb6b059eSMatt Spinler     /**
201cb6b059eSMatt Spinler      * @brief Says if the PEL is valid (the sections are all valid)
202cb6b059eSMatt Spinler      *
203cb6b059eSMatt Spinler      * @return bool - if the PEL is valid
204cb6b059eSMatt Spinler      */
205cb6b059eSMatt Spinler     bool valid() const;
206cb6b059eSMatt Spinler 
207cb6b059eSMatt Spinler     /**
208cb6b059eSMatt Spinler      * @brief Sets the commit timestamp to the current time
209cb6b059eSMatt Spinler      */
210cb6b059eSMatt Spinler     void setCommitTime();
211cb6b059eSMatt Spinler 
212cb6b059eSMatt Spinler     /**
213cb6b059eSMatt Spinler      * @brief Sets the error log ID field to a unique ID.
214cb6b059eSMatt Spinler      */
215cb6b059eSMatt Spinler     void assignID();
216cb6b059eSMatt Spinler 
217186ce8c9SAatir     /**
218186ce8c9SAatir      * @brief Output a PEL in JSON.
219186ce8c9SAatir      */
2200688545bSMatt Spinler     void toJSON() const;
221186ce8c9SAatir 
222f38ce984SMatt Spinler     /**
223f38ce984SMatt Spinler      * @brief Sets the host transmission state in the User Header
224f38ce984SMatt Spinler      *
225f38ce984SMatt Spinler      * @param[in] state - The state value
226f38ce984SMatt Spinler      */
227f38ce984SMatt Spinler     void setHostTransmissionState(TransmissionState state)
228f38ce984SMatt Spinler     {
229f38ce984SMatt Spinler         _uh->setHostTransmissionState(static_cast<uint8_t>(state));
230f38ce984SMatt Spinler     }
231f38ce984SMatt Spinler 
232f38ce984SMatt Spinler     /**
233f38ce984SMatt Spinler      * @brief Returns the host transmission state
234f38ce984SMatt Spinler      *
235f38ce984SMatt Spinler      * @return HostTransmissionState - The state
236f38ce984SMatt Spinler      */
237f38ce984SMatt Spinler     TransmissionState hostTransmissionState() const
238f38ce984SMatt Spinler     {
239f38ce984SMatt Spinler         return static_cast<TransmissionState>(_uh->hostTransmissionState());
240f38ce984SMatt Spinler     }
241f38ce984SMatt Spinler 
242f38ce984SMatt Spinler     /**
243f38ce984SMatt Spinler      * @brief Sets the HMC transmission state in the User Header
244f38ce984SMatt Spinler      *
245f38ce984SMatt Spinler      * @param[in] state - The state value
246f38ce984SMatt Spinler      */
247f38ce984SMatt Spinler     void setHMCTransmissionState(TransmissionState state)
248f38ce984SMatt Spinler     {
249f38ce984SMatt Spinler         _uh->setHMCTransmissionState(static_cast<uint8_t>(state));
250f38ce984SMatt Spinler     }
251f38ce984SMatt Spinler 
252f38ce984SMatt Spinler     /**
253f38ce984SMatt Spinler      * @brief Returns the HMC transmission state
254f38ce984SMatt Spinler      *
255f38ce984SMatt Spinler      * @return HMCTransmissionState - The state
256f38ce984SMatt Spinler      */
257f38ce984SMatt Spinler     TransmissionState hmcTransmissionState() const
258f38ce984SMatt Spinler     {
259f38ce984SMatt Spinler         return static_cast<TransmissionState>(_uh->hmcTransmissionState());
260f38ce984SMatt Spinler     }
261f38ce984SMatt Spinler 
262cb6b059eSMatt Spinler   private:
263cb6b059eSMatt Spinler     /**
264cb6b059eSMatt Spinler      * @brief Builds the section objects from a PEL data buffer
265cb6b059eSMatt Spinler      *
26607eefc54SMatt Spinler      * Note: The data parameter cannot be const for the same reasons
26707eefc54SMatt Spinler      * as listed in the constructor.
26807eefc54SMatt Spinler      *
26907eefc54SMatt Spinler      * @param[in] data - The PEL data
270cb6b059eSMatt Spinler      * @param[in] obmcLogID - The OpenBMC event log ID to use for that
271cb6b059eSMatt Spinler      *                        field in the Private Header.
272cb6b059eSMatt Spinler      */
27307eefc54SMatt Spinler     void populateFromRawData(std::vector<uint8_t>& data, uint32_t obmcLogID);
274cb6b059eSMatt Spinler 
275cb6b059eSMatt Spinler     /**
276cb6b059eSMatt Spinler      * @brief Flattens the PEL objects into the buffer
277cb6b059eSMatt Spinler      *
278cb6b059eSMatt Spinler      * @param[out] pelBuffer - What the data will be written to
279cb6b059eSMatt Spinler      */
2800688545bSMatt Spinler     void flatten(std::vector<uint8_t>& pelBuffer) const;
281cb6b059eSMatt Spinler 
282cb6b059eSMatt Spinler     /**
283f1e85e20SMatt Spinler      * @brief Check that the PEL fields that need to be in agreement
284f1e85e20SMatt Spinler      *        with each other are, and fix them up if necessary.
285f1e85e20SMatt Spinler      */
286f1e85e20SMatt Spinler     void checkRulesAndFix();
287f1e85e20SMatt Spinler 
288f1e85e20SMatt Spinler     /**
289*acb7c106SMatt Spinler      * @brief Returns a map of the section IDs that appear more than once
290*acb7c106SMatt Spinler      *        in the PEL.  The data value for each entry will be set to 0.
291*acb7c106SMatt Spinler      *
292*acb7c106SMatt Spinler      * @return std::map<uint16_t, size_t>
293*acb7c106SMatt Spinler      */
294*acb7c106SMatt Spinler     std::map<uint16_t, size_t> getPluralSections() const;
295*acb7c106SMatt Spinler 
296*acb7c106SMatt Spinler     /**
297cb6b059eSMatt Spinler      * @brief The PEL Private Header section
298cb6b059eSMatt Spinler      */
299cb6b059eSMatt Spinler     std::unique_ptr<PrivateHeader> _ph;
300cb6b059eSMatt Spinler 
301cb6b059eSMatt Spinler     /**
302cb6b059eSMatt Spinler      * @brief The PEL User Header section
303cb6b059eSMatt Spinler      */
304cb6b059eSMatt Spinler     std::unique_ptr<UserHeader> _uh;
305cb6b059eSMatt Spinler 
306cb6b059eSMatt Spinler     /**
307131870c7SMatt Spinler      * @brief Holds all sections by the PH and UH.
308131870c7SMatt Spinler      */
309131870c7SMatt Spinler     std::vector<std::unique_ptr<Section>> _optionalSections;
310186ce8c9SAatir 
311186ce8c9SAatir     /**
312186ce8c9SAatir      * @brief helper function for printing PELs.
313186ce8c9SAatir      * @param[in] Section& - section object reference
314186ce8c9SAatir      * @param[in] std::string - PEL string
315*acb7c106SMatt Spinler      * @param[in|out] pluralSections - Map used to track sections counts for
316*acb7c106SMatt Spinler      *                                 when there is more than 1.
317186ce8c9SAatir      */
318*acb7c106SMatt Spinler     void printSectionInJSON(const Section& section, std::string& buf,
319*acb7c106SMatt Spinler                             std::map<uint16_t, size_t>& pluralSections) const;
320cb6b059eSMatt Spinler };
321cb6b059eSMatt Spinler 
322afa857c7SMatt Spinler namespace util
323afa857c7SMatt Spinler {
324afa857c7SMatt Spinler 
325afa857c7SMatt Spinler /**
326afa857c7SMatt Spinler  * @brief Create a UserData section containing the AdditionalData
327afa857c7SMatt Spinler  *        contents as a JSON string.
328afa857c7SMatt Spinler  *
329afa857c7SMatt Spinler  * @param[in] ad - The AdditionalData contents
330afa857c7SMatt Spinler  *
331afa857c7SMatt Spinler  * @return std::unique_ptr<UserData> - The section
332afa857c7SMatt Spinler  */
333afa857c7SMatt Spinler std::unique_ptr<UserData> makeADUserDataSection(const AdditionalData& ad);
334afa857c7SMatt Spinler 
335afa857c7SMatt Spinler } // namespace util
336afa857c7SMatt Spinler 
337cb6b059eSMatt Spinler } // namespace pels
338cb6b059eSMatt Spinler } // namespace openpower
339