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      * @param[in] registry - Registry object reference
227      */
228     void toJSON(message::Registry& registry) const;
229 
230     /**
231      * @brief Sets the host transmission state in the User Header
232      *
233      * @param[in] state - The state value
234      */
235     void setHostTransmissionState(TransmissionState state)
236     {
237         _uh->setHostTransmissionState(static_cast<uint8_t>(state));
238     }
239 
240     /**
241      * @brief Returns the host transmission state
242      *
243      * @return HostTransmissionState - The state
244      */
245     TransmissionState hostTransmissionState() const
246     {
247         return static_cast<TransmissionState>(_uh->hostTransmissionState());
248     }
249 
250     /**
251      * @brief Sets the HMC transmission state in the User Header
252      *
253      * @param[in] state - The state value
254      */
255     void setHMCTransmissionState(TransmissionState state)
256     {
257         _uh->setHMCTransmissionState(static_cast<uint8_t>(state));
258     }
259 
260     /**
261      * @brief Returns the HMC transmission state
262      *
263      * @return HMCTransmissionState - The state
264      */
265     TransmissionState hmcTransmissionState() const
266     {
267         return static_cast<TransmissionState>(_uh->hmcTransmissionState());
268     }
269 
270   private:
271     /**
272      * @brief Builds the section objects from a PEL data buffer
273      *
274      * Note: The data parameter cannot be const for the same reasons
275      * as listed in the constructor.
276      *
277      * @param[in] data - The PEL data
278      * @param[in] obmcLogID - The OpenBMC event log ID to use for that
279      *                        field in the Private Header.
280      */
281     void populateFromRawData(std::vector<uint8_t>& data, uint32_t obmcLogID);
282 
283     /**
284      * @brief Flattens the PEL objects into the buffer
285      *
286      * @param[out] pelBuffer - What the data will be written to
287      */
288     void flatten(std::vector<uint8_t>& pelBuffer) const;
289 
290     /**
291      * @brief Check that the PEL fields that need to be in agreement
292      *        with each other are, and fix them up if necessary.
293      */
294     void checkRulesAndFix();
295 
296     /**
297      * @brief Returns a map of the section IDs that appear more than once
298      *        in the PEL.  The data value for each entry will be set to 0.
299      *
300      * @return std::map<uint16_t, size_t>
301      */
302     std::map<uint16_t, size_t> getPluralSections() const;
303 
304     /**
305      * @brief The PEL Private Header section
306      */
307     std::unique_ptr<PrivateHeader> _ph;
308 
309     /**
310      * @brief The PEL User Header section
311      */
312     std::unique_ptr<UserHeader> _uh;
313 
314     /**
315      * @brief Holds all sections by the PH and UH.
316      */
317     std::vector<std::unique_ptr<Section>> _optionalSections;
318 
319     /**
320      * @brief helper function for printing PELs.
321      * @param[in] Section& - section object reference
322      * @param[in] std::string - PEL string
323      * @param[in|out] pluralSections - Map used to track sections counts for
324      *                                 when there is more than 1.
325      * @param[in] registry - Registry object reference
326      */
327     void printSectionInJSON(const Section& section, std::string& buf,
328                             std::map<uint16_t, size_t>& pluralSections,
329                             message::Registry& registry) const;
330 
331     /**
332      * @brief The maximum size a PEL can be in bytes.
333      */
334     static constexpr size_t _maxPELSize = 16384;
335 };
336 
337 namespace util
338 {
339 
340 /**
341  * @brief Create a UserData section containing the AdditionalData
342  *        contents as a JSON string.
343  *
344  * @param[in] ad - The AdditionalData contents
345  *
346  * @return std::unique_ptr<UserData> - The section
347  */
348 std::unique_ptr<UserData> makeADUserDataSection(const AdditionalData& ad);
349 
350 /**
351  * @brief Create a UserData section containing various useful pieces
352  *        of system information as a JSON string.
353  *
354  * @param[in] ad - The AdditionalData contents
355  * @param[in] dataIface - The data interface object
356  *
357  * @return std::unique_ptr<UserData> - The section
358  */
359 std::unique_ptr<UserData>
360     makeSysInfoUserDataSection(const AdditionalData& ad,
361                                const DataInterfaceBase& dataIface);
362 } // namespace util
363 
364 } // namespace pels
365 } // namespace openpower
366