blob: ffd4974e83b9a5bfeb393ef92fa2ce48805b21a6 [file] [log] [blame]
Matt Spinlercb6b0592019-07-16 15:58:51 -05001#include "pel.hpp"
2
3#include "bcd_time.hpp"
Matt Spinleraa659472019-10-23 09:26:48 -05004#include "failing_mtms.hpp"
Matt Spinlercb6b0592019-07-16 15:58:51 -05005#include "log_id.hpp"
Matt Spinler131870c2019-09-25 13:29:04 -05006#include "section_factory.hpp"
Matt Spinlerbd716f02019-10-15 10:54:11 -05007#include "src.hpp"
Matt Spinlercb6b0592019-07-16 15:58:51 -05008#include "stream.hpp"
9
Matt Spinler07eefc52019-09-26 11:18:26 -050010#include <phosphor-logging/log.hpp>
11
Matt Spinlercb6b0592019-07-16 15:58:51 -050012namespace openpower
13{
14namespace pels
15{
Matt Spinlerb8323632019-09-20 15:11:04 -050016namespace message = openpower::pels::message;
17
18PEL::PEL(const message::Entry& entry, uint32_t obmcLogID, uint64_t timestamp,
Matt Spinlerbd716f02019-10-15 10:54:11 -050019 phosphor::logging::Entry::Level severity,
Matt Spinleraa659472019-10-23 09:26:48 -050020 const AdditionalData& additionalData,
21 const DataInterfaceBase& dataIface)
Matt Spinlerb8323632019-09-20 15:11:04 -050022{
23 _ph = std::make_unique<PrivateHeader>(entry.componentID, obmcLogID,
24 timestamp);
25 _uh = std::make_unique<UserHeader>(entry, severity);
26
Matt Spinlerbd716f02019-10-15 10:54:11 -050027 auto src = std::make_unique<SRC>(entry, additionalData);
28 _optionalSections.push_back(std::move(src));
Matt Spinlerb8323632019-09-20 15:11:04 -050029
Matt Spinleraa659472019-10-23 09:26:48 -050030 auto mtms = std::make_unique<FailingMTMS>(dataIface);
31 _optionalSections.push_back(std::move(mtms));
Matt Spinlerbd716f02019-10-15 10:54:11 -050032
33 _ph->sectionCount() = 2 + _optionalSections.size();
Matt Spinlerb8323632019-09-20 15:11:04 -050034}
Matt Spinlercb6b0592019-07-16 15:58:51 -050035
Matt Spinler07eefc52019-09-26 11:18:26 -050036PEL::PEL(std::vector<uint8_t>& data) : PEL(data, 0)
Matt Spinlercb6b0592019-07-16 15:58:51 -050037{
38}
39
Matt Spinler07eefc52019-09-26 11:18:26 -050040PEL::PEL(std::vector<uint8_t>& data, uint32_t obmcLogID)
Matt Spinlercb6b0592019-07-16 15:58:51 -050041{
Matt Spinler07eefc52019-09-26 11:18:26 -050042 populateFromRawData(data, obmcLogID);
Matt Spinlercb6b0592019-07-16 15:58:51 -050043}
44
Matt Spinler07eefc52019-09-26 11:18:26 -050045void PEL::populateFromRawData(std::vector<uint8_t>& data, uint32_t obmcLogID)
Matt Spinlercb6b0592019-07-16 15:58:51 -050046{
Matt Spinler07eefc52019-09-26 11:18:26 -050047 Stream pelData{data};
Matt Spinlercb6b0592019-07-16 15:58:51 -050048 _ph = std::make_unique<PrivateHeader>(pelData);
49 if (obmcLogID != 0)
50 {
51 _ph->obmcLogID() = obmcLogID;
52 }
53
54 _uh = std::make_unique<UserHeader>(pelData);
Matt Spinler131870c2019-09-25 13:29:04 -050055
56 // Use the section factory to create the rest of the objects
57 for (size_t i = 2; i < _ph->sectionCount(); i++)
58 {
59 auto section = section_factory::create(pelData);
60 _optionalSections.push_back(std::move(section));
61 }
Matt Spinlercb6b0592019-07-16 15:58:51 -050062}
63
64bool PEL::valid() const
65{
66 bool valid = _ph->valid();
67
68 if (valid)
69 {
70 valid = _uh->valid();
71 }
72
Matt Spinler131870c2019-09-25 13:29:04 -050073 if (valid)
74 {
75 if (!std::all_of(_optionalSections.begin(), _optionalSections.end(),
76 [](const auto& section) { return section->valid(); }))
77 {
78 valid = false;
79 }
80 }
81
Matt Spinlercb6b0592019-07-16 15:58:51 -050082 return valid;
83}
84
85void PEL::setCommitTime()
86{
87 auto now = std::chrono::system_clock::now();
88 _ph->commitTimestamp() = getBCDTime(now);
89}
90
91void PEL::assignID()
92{
93 _ph->id() = generatePELID();
94}
95
96void PEL::flatten(std::vector<uint8_t>& pelBuffer)
97{
98 Stream pelData{pelBuffer};
Matt Spinlerb8323632019-09-20 15:11:04 -050099
Matt Spinler07eefc52019-09-26 11:18:26 -0500100 if (!valid())
Matt Spinlercb6b0592019-07-16 15:58:51 -0500101 {
Matt Spinler07eefc52019-09-26 11:18:26 -0500102 using namespace phosphor::logging;
103 log<level::WARNING>("Unflattening an invalid PEL");
Matt Spinlercb6b0592019-07-16 15:58:51 -0500104 }
105
Matt Spinler07eefc52019-09-26 11:18:26 -0500106 _ph->flatten(pelData);
Matt Spinlerb8323632019-09-20 15:11:04 -0500107 _uh->flatten(pelData);
Matt Spinler07eefc52019-09-26 11:18:26 -0500108
109 for (auto& section : _optionalSections)
110 {
111 section->flatten(pelData);
112 }
Matt Spinlercb6b0592019-07-16 15:58:51 -0500113}
114
115std::vector<uint8_t> PEL::data()
116{
Matt Spinler07eefc52019-09-26 11:18:26 -0500117 std::vector<uint8_t> pelData;
118 flatten(pelData);
119 return pelData;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500120}
121
Matt Spinlerbd716f02019-10-15 10:54:11 -0500122std::optional<SRC*> PEL::primarySRC() const
123{
124 auto src = std::find_if(
125 _optionalSections.begin(), _optionalSections.end(), [](auto& section) {
126 return section->header().id ==
127 static_cast<uint16_t>(SectionID::primarySRC);
128 });
129 if (src != _optionalSections.end())
130 {
131 return static_cast<SRC*>(src->get());
132 }
133
134 return std::nullopt;
135}
136
Matt Spinlercb6b0592019-07-16 15:58:51 -0500137} // namespace pels
138} // namespace openpower