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_data.hpp"
9 #include "user_header.hpp"
10 
11 #include <memory>
12 #include <vector>
13 
14 namespace openpower
15 {
16 namespace 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  *
37  * 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.
41  *
42  * 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  */
45 class 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      *
60      * 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      *
65      * @param[in] data - The PEL data
66      */
67     PEL(std::vector<uint8_t>& data);
68 
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      */
77     PEL(std::vector<uint8_t>& data, uint32_t obmcLogID);
78 
79     /**
80      * @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
89      * @param[in] additionalData - The AdditionalData contents
90      * @param[in] dataIface - The data interface object
91      */
92     PEL(const openpower::pels::message::Entry& entry, uint32_t obmcLogID,
93         uint64_t timestamp, phosphor::logging::Entry::Level severity,
94         const AdditionalData& additionalData,
95         const DataInterfaceBase& dataIface);
96 
97     /**
98      * @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      *
155      * @return const PrivateHeader& - the private header
156      */
157     const PrivateHeader& privateHeader() const
158     {
159         return *_ph;
160     }
161 
162     /**
163      * @brief Gives access to the User Header section class
164      *
165      * @return const UserHeader& - the user header
166      */
167     const UserHeader& userHeader() const
168     {
169         return *_uh;
170     }
171 
172     /**
173      * @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     /**
183      * @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     /**
194      * @brief Returns the PEL data.
195      *
196      * @return std::vector<uint8_t> - the raw PEL data
197      */
198     std::vector<uint8_t> data() const;
199 
200     /**
201      * @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     /**
208      * @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 
224     /**
225      * @brief Output a PEL in JSON.
226      */
227     void toJSON() const;
228 
229     /**
230      * @brief Sets the host transmission state in the User Header
231      *
232      * @param[in] state - The state value
233      */
234     void setHostTransmissionState(TransmissionState state)
235     {
236         _uh->setHostTransmissionState(static_cast<uint8_t>(state));
237     }
238 
239     /**
240      * @brief Returns the host transmission state
241      *
242      * @return HostTransmissionState - The state
243      */
244     TransmissionState hostTransmissionState() const
245     {
246         return static_cast<TransmissionState>(_uh->hostTransmissionState());
247     }
248 
249     /**
250      * @brief Sets the HMC transmission state in the User Header
251      *
252      * @param[in] state - The state value
253      */
254     void setHMCTransmissionState(TransmissionState state)
255     {
256         _uh->setHMCTransmissionState(static_cast<uint8_t>(state));
257     }
258 
259     /**
260      * @brief Returns the HMC transmission state
261      *
262      * @return HMCTransmissionState - The state
263      */
264     TransmissionState hmcTransmissionState() const
265     {
266         return static_cast<TransmissionState>(_uh->hmcTransmissionState());
267     }
268 
269   private:
270     /**
271      * @brief Builds the section objects from a PEL data buffer
272      *
273      * Note: The data parameter cannot be const for the same reasons
274      * as listed in the constructor.
275      *
276      * @param[in] data - The PEL data
277      * @param[in] obmcLogID - The OpenBMC event log ID to use for that
278      *                        field in the Private Header.
279      */
280     void populateFromRawData(std::vector<uint8_t>& data, uint32_t obmcLogID);
281 
282     /**
283      * @brief Flattens the PEL objects into the buffer
284      *
285      * @param[out] pelBuffer - What the data will be written to
286      */
287     void flatten(std::vector<uint8_t>& pelBuffer) const;
288 
289     /**
290      * @brief Check that the PEL fields that need to be in agreement
291      *        with each other are, and fix them up if necessary.
292      */
293     void checkRulesAndFix();
294 
295     /**
296      * @brief Returns a map of the section IDs that appear more than once
297      *        in the PEL.  The data value for each entry will be set to 0.
298      *
299      * @return std::map<uint16_t, size_t>
300      */
301     std::map<uint16_t, size_t> getPluralSections() const;
302 
303     /**
304      * @brief The PEL Private Header section
305      */
306     std::unique_ptr<PrivateHeader> _ph;
307 
308     /**
309      * @brief The PEL User Header section
310      */
311     std::unique_ptr<UserHeader> _uh;
312 
313     /**
314      * @brief Holds all sections by the PH and UH.
315      */
316     std::vector<std::unique_ptr<Section>> _optionalSections;
317 
318     /**
319      * @brief helper function for printing PELs.
320      * @param[in] Section& - section object reference
321      * @param[in] std::string - PEL string
322      * @param[in|out] pluralSections - Map used to track sections counts for
323      *                                 when there is more than 1.
324      */
325     void printSectionInJSON(const Section& section, std::string& buf,
326                             std::map<uint16_t, size_t>& pluralSections) const;
327 };
328 
329 namespace util
330 {
331 
332 /**
333  * @brief Create a UserData section containing the AdditionalData
334  *        contents as a JSON string.
335  *
336  * @param[in] ad - The AdditionalData contents
337  *
338  * @return std::unique_ptr<UserData> - The section
339  */
340 std::unique_ptr<UserData> makeADUserDataSection(const AdditionalData& ad);
341 
342 } // namespace util
343 
344 } // namespace pels
345 } // namespace openpower
346