blob: c7df5e8e9d7d5d4024d0ca7f72c61874a204daca [file] [log] [blame]
Matt Spinlercb6b0592019-07-16 15:58:51 -05001#include "pel.hpp"
2
3#include "bcd_time.hpp"
4#include "log_id.hpp"
Matt Spinler131870c2019-09-25 13:29:04 -05005#include "section_factory.hpp"
Matt Spinlercb6b0592019-07-16 15:58:51 -05006#include "stream.hpp"
7
8namespace openpower
9{
10namespace pels
11{
Matt Spinlerb8323632019-09-20 15:11:04 -050012namespace message = openpower::pels::message;
13
14PEL::PEL(const message::Entry& entry, uint32_t obmcLogID, uint64_t timestamp,
15 phosphor::logging::Entry::Level severity)
16{
17 _ph = std::make_unique<PrivateHeader>(entry.componentID, obmcLogID,
18 timestamp);
19 _uh = std::make_unique<UserHeader>(entry, severity);
20
21 // Add future sections here and update the count
22
23 _ph->sectionCount() = 2;
24}
Matt Spinlercb6b0592019-07-16 15:58:51 -050025
26PEL::PEL(const std::vector<uint8_t>& data) : PEL(data, 0)
27{
28}
29
30PEL::PEL(const std::vector<uint8_t>& data, uint32_t obmcLogID) : _rawPEL(data)
31{
Matt Spinlerb8323632019-09-20 15:11:04 -050032 _fromStream = true;
Matt Spinlercb6b0592019-07-16 15:58:51 -050033 populateFromRawData(obmcLogID);
34}
35
36void PEL::populateFromRawData(uint32_t obmcLogID)
37{
38 Stream pelData{_rawPEL};
39 _ph = std::make_unique<PrivateHeader>(pelData);
40 if (obmcLogID != 0)
41 {
42 _ph->obmcLogID() = obmcLogID;
43 }
44
45 _uh = std::make_unique<UserHeader>(pelData);
Matt Spinler131870c2019-09-25 13:29:04 -050046
47 // Use the section factory to create the rest of the objects
48 for (size_t i = 2; i < _ph->sectionCount(); i++)
49 {
50 auto section = section_factory::create(pelData);
51 _optionalSections.push_back(std::move(section));
52 }
Matt Spinlercb6b0592019-07-16 15:58:51 -050053}
54
55bool PEL::valid() const
56{
57 bool valid = _ph->valid();
58
59 if (valid)
60 {
61 valid = _uh->valid();
62 }
63
Matt Spinler131870c2019-09-25 13:29:04 -050064 if (valid)
65 {
66 if (!std::all_of(_optionalSections.begin(), _optionalSections.end(),
67 [](const auto& section) { return section->valid(); }))
68 {
69 valid = false;
70 }
71 }
72
Matt Spinlercb6b0592019-07-16 15:58:51 -050073 return valid;
74}
75
76void PEL::setCommitTime()
77{
78 auto now = std::chrono::system_clock::now();
79 _ph->commitTimestamp() = getBCDTime(now);
80}
81
82void PEL::assignID()
83{
84 _ph->id() = generatePELID();
85}
86
87void PEL::flatten(std::vector<uint8_t>& pelBuffer)
88{
89 Stream pelData{pelBuffer};
Matt Spinlerb8323632019-09-20 15:11:04 -050090
91 _ph->flatten(pelData);
92
93 // If constructed from a PEL stream originally, don't flatten the
94 // rest of the objects until we support every PEL section type.
95 // Still need the PrivateHeader, as we updated fields in it.
96 if (_fromStream)
Matt Spinlercb6b0592019-07-16 15:58:51 -050097 {
98 return;
99 }
100
Matt Spinlerb8323632019-09-20 15:11:04 -0500101 _uh->flatten(pelData);
Matt Spinlercb6b0592019-07-16 15:58:51 -0500102}
103
104std::vector<uint8_t> PEL::data()
105{
106 // Until we can recreate a complete PEL from objects, need to just flatten
107 // on top of the original PEL data which we need to keep around for this
Matt Spinlerb8323632019-09-20 15:11:04 -0500108 // reason. If creating a PEL from scratch, _rawPEL will get filled in with
109 // what we do have.
Matt Spinlercb6b0592019-07-16 15:58:51 -0500110
111 flatten(_rawPEL);
112 return _rawPEL;
113}
114
115} // namespace pels
116} // namespace openpower