blob: 157af5a1fc14e28e54c0110304299bcf8c3c002a [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 Spinlerbd716f02019-10-15 10:54:11 -05006#include "src.hpp"
Matt Spinlercb6b0592019-07-16 15:58:51 -05007#include "stream.hpp"
8
Matt Spinler07eefc52019-09-26 11:18:26 -05009#include <phosphor-logging/log.hpp>
10
Matt Spinlercb6b0592019-07-16 15:58:51 -050011namespace openpower
12{
13namespace pels
14{
Matt Spinlerb8323632019-09-20 15:11:04 -050015namespace message = openpower::pels::message;
16
17PEL::PEL(const message::Entry& entry, uint32_t obmcLogID, uint64_t timestamp,
Matt Spinlerbd716f02019-10-15 10:54:11 -050018 phosphor::logging::Entry::Level severity,
19 const AdditionalData& additionalData)
Matt Spinlerb8323632019-09-20 15:11:04 -050020{
21 _ph = std::make_unique<PrivateHeader>(entry.componentID, obmcLogID,
22 timestamp);
23 _uh = std::make_unique<UserHeader>(entry, severity);
24
Matt Spinlerbd716f02019-10-15 10:54:11 -050025 auto src = std::make_unique<SRC>(entry, additionalData);
26 _optionalSections.push_back(std::move(src));
Matt Spinlerb8323632019-09-20 15:11:04 -050027
Matt Spinlerbd716f02019-10-15 10:54:11 -050028 // Add future sections here
29
30 _ph->sectionCount() = 2 + _optionalSections.size();
Matt Spinlerb8323632019-09-20 15:11:04 -050031}
Matt Spinlercb6b0592019-07-16 15:58:51 -050032
Matt Spinler07eefc52019-09-26 11:18:26 -050033PEL::PEL(std::vector<uint8_t>& data) : PEL(data, 0)
Matt Spinlercb6b0592019-07-16 15:58:51 -050034{
35}
36
Matt Spinler07eefc52019-09-26 11:18:26 -050037PEL::PEL(std::vector<uint8_t>& data, uint32_t obmcLogID)
Matt Spinlercb6b0592019-07-16 15:58:51 -050038{
Matt Spinler07eefc52019-09-26 11:18:26 -050039 populateFromRawData(data, obmcLogID);
Matt Spinlercb6b0592019-07-16 15:58:51 -050040}
41
Matt Spinler07eefc52019-09-26 11:18:26 -050042void PEL::populateFromRawData(std::vector<uint8_t>& data, uint32_t obmcLogID)
Matt Spinlercb6b0592019-07-16 15:58:51 -050043{
Matt Spinler07eefc52019-09-26 11:18:26 -050044 Stream pelData{data};
Matt Spinlercb6b0592019-07-16 15:58:51 -050045 _ph = std::make_unique<PrivateHeader>(pelData);
46 if (obmcLogID != 0)
47 {
48 _ph->obmcLogID() = obmcLogID;
49 }
50
51 _uh = std::make_unique<UserHeader>(pelData);
Matt Spinler131870c2019-09-25 13:29:04 -050052
53 // Use the section factory to create the rest of the objects
54 for (size_t i = 2; i < _ph->sectionCount(); i++)
55 {
56 auto section = section_factory::create(pelData);
57 _optionalSections.push_back(std::move(section));
58 }
Matt Spinlercb6b0592019-07-16 15:58:51 -050059}
60
61bool PEL::valid() const
62{
63 bool valid = _ph->valid();
64
65 if (valid)
66 {
67 valid = _uh->valid();
68 }
69
Matt Spinler131870c2019-09-25 13:29:04 -050070 if (valid)
71 {
72 if (!std::all_of(_optionalSections.begin(), _optionalSections.end(),
73 [](const auto& section) { return section->valid(); }))
74 {
75 valid = false;
76 }
77 }
78
Matt Spinlercb6b0592019-07-16 15:58:51 -050079 return valid;
80}
81
82void PEL::setCommitTime()
83{
84 auto now = std::chrono::system_clock::now();
85 _ph->commitTimestamp() = getBCDTime(now);
86}
87
88void PEL::assignID()
89{
90 _ph->id() = generatePELID();
91}
92
93void PEL::flatten(std::vector<uint8_t>& pelBuffer)
94{
95 Stream pelData{pelBuffer};
Matt Spinlerb8323632019-09-20 15:11:04 -050096
Matt Spinler07eefc52019-09-26 11:18:26 -050097 if (!valid())
Matt Spinlercb6b0592019-07-16 15:58:51 -050098 {
Matt Spinler07eefc52019-09-26 11:18:26 -050099 using namespace phosphor::logging;
100 log<level::WARNING>("Unflattening an invalid PEL");
Matt Spinlercb6b0592019-07-16 15:58:51 -0500101 }
102
Matt Spinler07eefc52019-09-26 11:18:26 -0500103 _ph->flatten(pelData);
Matt Spinlerb8323632019-09-20 15:11:04 -0500104 _uh->flatten(pelData);
Matt Spinler07eefc52019-09-26 11:18:26 -0500105
106 for (auto& section : _optionalSections)
107 {
108 section->flatten(pelData);
109 }
Matt Spinlercb6b0592019-07-16 15:58:51 -0500110}
111
112std::vector<uint8_t> PEL::data()
113{
Matt Spinler07eefc52019-09-26 11:18:26 -0500114 std::vector<uint8_t> pelData;
115 flatten(pelData);
116 return pelData;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500117}
118
Matt Spinlerbd716f02019-10-15 10:54:11 -0500119std::optional<SRC*> PEL::primarySRC() const
120{
121 auto src = std::find_if(
122 _optionalSections.begin(), _optionalSections.end(), [](auto& section) {
123 return section->header().id ==
124 static_cast<uint16_t>(SectionID::primarySRC);
125 });
126 if (src != _optionalSections.end())
127 {
128 return static_cast<SRC*>(src->get());
129 }
130
131 return std::nullopt;
132}
133
Matt Spinlercb6b0592019-07-16 15:58:51 -0500134} // namespace pels
135} // namespace openpower