1 #pragma once
2 
3 #include "additional_data.hpp"
4 #include "data_interface.hpp"
5 #include "private_header.hpp"
6 #include "registry.hpp"
7 #include "src.hpp"
8 #include "user_header.hpp"
9 
10 #include <memory>
11 #include <vector>
12 
13 namespace openpower
14 {
15 namespace pels
16 {
17 
18 /** @class PEL
19  *
20  * @brief This class represents a specific event log format referred to as a
21  * Platform Event Log.
22  *
23  * Every field in a PEL are in structures call sections, of which there are
24  * several types.  Some sections are required, and some are optional.  In some
25  * cases there may be more than one instance of a section type.
26  *
27  * The only two required sections for every type of PEL are the Private Header
28  * section and User Header section, which must be in the first and second
29  * positions, respectively.
30  *
31  * Every section starts with an 8 byte section header, which has the section
32  * size and type, among other things.
33  *
34  * This class represents all sections with objects.
35  *
36  * The class can be constructed:
37  * - From a full formed flattened PEL.
38  * - From scratch based on an OpenBMC event and its corresponding PEL message
39  *   registry entry.
40  *
41  * The data() method allows one to retrieve the PEL as a vector<uint8_t>.  This
42  * is the format in which it is stored and transmitted.
43  */
44 class PEL
45 {
46   public:
47     PEL() = delete;
48     ~PEL() = default;
49     PEL(const PEL&) = delete;
50     PEL& operator=(const PEL&) = delete;
51     PEL(PEL&&) = delete;
52     PEL& operator=(PEL&&) = delete;
53 
54     /**
55      * @brief Constructor
56      *
57      * Build a PEL from raw data.
58      *
59      * Note: Neither this nor the following constructor can take a const vector&
60      * because the Stream class that is used to read from the vector cannot take
61      * a const.  The alternative is to make a copy of the data, but as PELs can
62      * be up to 16KB that is undesireable.
63      *
64      * @param[in] data - The PEL data
65      */
66     PEL(std::vector<uint8_t>& data);
67 
68     /**
69      * @brief Constructor
70      *
71      * Build a PEL from the raw data.
72      *
73      * @param[in] data - the PEL data
74      * @param[in] obmcLogID - the corresponding OpenBMC event log ID
75      */
76     PEL(std::vector<uint8_t>& data, uint32_t obmcLogID);
77 
78     /**
79      * @brief Constructor
80      *
81      * Creates a PEL from an OpenBMC event log and its message
82      * registry entry.
83      *
84      * @param[in] entry - The message registry entry for this error
85      * @param[in] obmcLogID - ID of corresponding OpenBMC event log
86      * @param[in] timestamp - Timestamp from the event log
87      * @param[in] severity - Severity from the event log
88      * @param[in] additionalData - The AdditionalData contents
89      * @param[in] dataIface - The data interface object
90      */
91     PEL(const openpower::pels::message::Entry& entry, uint32_t obmcLogID,
92         uint64_t timestamp, phosphor::logging::Entry::Level severity,
93         const AdditionalData& additionalData,
94         const DataInterfaceBase& dataIface);
95 
96     /**
97      * @brief Convenience function to return the log ID field from the
98      *        Private Header section.
99      *
100      * @return uint32_t - the ID
101      */
102     uint32_t id() const
103     {
104         return _ph->id();
105     }
106 
107     /**
108      * @brief Convenience function to return the PLID field from the
109      *        Private Header section.
110      *
111      * @return uint32_t - the PLID
112      */
113     uint32_t plid() const
114     {
115         return _ph->plid();
116     }
117 
118     /**
119      * @brief Convenience function to return the OpenBMC event log ID field
120      * from the Private Header section.
121      *
122      * @return uint32_t - the OpenBMC event log ID
123      */
124     uint32_t obmcLogID() const
125     {
126         return _ph->obmcLogID();
127     }
128 
129     /**
130      * @brief Convenience function to return the commit time field from
131      *        the Private Header section.
132      *
133      * @return BCDTime - the timestamp
134      */
135     BCDTime commitTime() const
136     {
137         return _ph->commitTimestamp();
138     }
139 
140     /**
141      * @brief Convenience function to return the create time field from
142      *        the Private Header section.
143      *
144      * @return BCDTime - the timestamp
145      */
146     BCDTime createTime() const
147     {
148         return _ph->createTimestamp();
149     }
150 
151     /**
152      * @brief Gives access to the Private Header section class
153      *
154      * @return std::unique_ptr<PrivateHeader>& the private header
155      */
156     std::unique_ptr<PrivateHeader>& privateHeader()
157     {
158         return _ph;
159     }
160 
161     /**
162      * @brief Gives access to the User Header section class
163      *
164      * @return std::unique_ptr<UserHeader>& the user header
165      */
166     std::unique_ptr<UserHeader>& userHeader()
167     {
168         return _uh;
169     }
170 
171     /**
172      * @brief Gives access to the primary SRC's section class
173      *
174      * This is technically an optional section, so the return
175      * value is an std::optional<SRC*>.
176      *
177      * @return std::optional<SRC*> - the SRC section object
178      */
179     std::optional<SRC*> primarySRC() const;
180 
181     /**
182      * @brief Returns the optional sections, which is everything but
183      *        the Private and User Headers.
184      *
185      * @return const std::vector<std::unique_ptr<Section>>&
186      */
187     const std::vector<std::unique_ptr<Section>>& optionalSections() const
188     {
189         return _optionalSections;
190     }
191 
192     /**
193      * @brief Returns the PEL data.
194      *
195      * @return std::vector<uint8_t> - the raw PEL data
196      */
197     std::vector<uint8_t> data();
198 
199     /**
200      * @brief Says if the PEL is valid (the sections are all valid)
201      *
202      * @return bool - if the PEL is valid
203      */
204     bool valid() const;
205 
206     /**
207      * @brief Sets the commit timestamp to the current time
208      */
209     void setCommitTime();
210 
211     /**
212      * @brief Sets the error log ID field to a unique ID.
213      */
214     void assignID();
215 
216   private:
217     /**
218      * @brief Builds the section objects from a PEL data buffer
219      *
220      * Note: The data parameter cannot be const for the same reasons
221      * as listed in the constructor.
222      *
223      * @param[in] data - The PEL data
224      * @param[in] obmcLogID - The OpenBMC event log ID to use for that
225      *                        field in the Private Header.
226      */
227     void populateFromRawData(std::vector<uint8_t>& data, uint32_t obmcLogID);
228 
229     /**
230      * @brief Flattens the PEL objects into the buffer
231      *
232      * @param[out] pelBuffer - What the data will be written to
233      */
234     void flatten(std::vector<uint8_t>& pelBuffer);
235 
236     /**
237      * @brief The PEL Private Header section
238      */
239     std::unique_ptr<PrivateHeader> _ph;
240 
241     /**
242      * @brief The PEL User Header section
243      */
244     std::unique_ptr<UserHeader> _uh;
245 
246     /**
247      * @brief Holds all sections by the PH and UH.
248      */
249     std::vector<std::unique_ptr<Section>> _optionalSections;
250 };
251 
252 } // namespace pels
253 } // namespace openpower
254