blob: 29d86d553f2260c118305a063cc4e6d78d6d7357 [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"
Matt Spinlerafa857c2019-10-24 13:03:46 -05009#include "user_data_formats.hpp"
Matt Spinlercb6b0592019-07-16 15:58:51 -050010
Matt Spinler07eefc52019-09-26 11:18:26 -050011#include <phosphor-logging/log.hpp>
12
Matt Spinlercb6b0592019-07-16 15:58:51 -050013namespace openpower
14{
15namespace pels
16{
Matt Spinlerb8323632019-09-20 15:11:04 -050017namespace message = openpower::pels::message;
18
19PEL::PEL(const message::Entry& entry, uint32_t obmcLogID, uint64_t timestamp,
Matt Spinlerbd716f02019-10-15 10:54:11 -050020 phosphor::logging::Entry::Level severity,
Matt Spinleraa659472019-10-23 09:26:48 -050021 const AdditionalData& additionalData,
22 const DataInterfaceBase& dataIface)
Matt Spinlerb8323632019-09-20 15:11:04 -050023{
24 _ph = std::make_unique<PrivateHeader>(entry.componentID, obmcLogID,
25 timestamp);
26 _uh = std::make_unique<UserHeader>(entry, severity);
27
Matt Spinlerbd716f02019-10-15 10:54:11 -050028 auto src = std::make_unique<SRC>(entry, additionalData);
29 _optionalSections.push_back(std::move(src));
Matt Spinlerb8323632019-09-20 15:11:04 -050030
Matt Spinleraa659472019-10-23 09:26:48 -050031 auto mtms = std::make_unique<FailingMTMS>(dataIface);
32 _optionalSections.push_back(std::move(mtms));
Matt Spinlerbd716f02019-10-15 10:54:11 -050033
Matt Spinlerafa857c2019-10-24 13:03:46 -050034 if (!additionalData.empty())
35 {
36 auto ud = util::makeADUserDataSection(additionalData);
37 _optionalSections.push_back(std::move(ud));
38 }
39
Matt Spinler97d19b42019-10-29 11:34:03 -050040 _ph->setSectionCount(2 + _optionalSections.size());
Matt Spinlerb8323632019-09-20 15:11:04 -050041}
Matt Spinlercb6b0592019-07-16 15:58:51 -050042
Matt Spinler07eefc52019-09-26 11:18:26 -050043PEL::PEL(std::vector<uint8_t>& data) : PEL(data, 0)
Matt Spinlercb6b0592019-07-16 15:58:51 -050044{
45}
46
Matt Spinler07eefc52019-09-26 11:18:26 -050047PEL::PEL(std::vector<uint8_t>& data, uint32_t obmcLogID)
Matt Spinlercb6b0592019-07-16 15:58:51 -050048{
Matt Spinler07eefc52019-09-26 11:18:26 -050049 populateFromRawData(data, obmcLogID);
Matt Spinlercb6b0592019-07-16 15:58:51 -050050}
51
Matt Spinler07eefc52019-09-26 11:18:26 -050052void PEL::populateFromRawData(std::vector<uint8_t>& data, uint32_t obmcLogID)
Matt Spinlercb6b0592019-07-16 15:58:51 -050053{
Matt Spinler07eefc52019-09-26 11:18:26 -050054 Stream pelData{data};
Matt Spinlercb6b0592019-07-16 15:58:51 -050055 _ph = std::make_unique<PrivateHeader>(pelData);
56 if (obmcLogID != 0)
57 {
Matt Spinler97d19b42019-10-29 11:34:03 -050058 _ph->setOBMCLogID(obmcLogID);
Matt Spinlercb6b0592019-07-16 15:58:51 -050059 }
60
61 _uh = std::make_unique<UserHeader>(pelData);
Matt Spinler131870c2019-09-25 13:29:04 -050062
63 // Use the section factory to create the rest of the objects
64 for (size_t i = 2; i < _ph->sectionCount(); i++)
65 {
66 auto section = section_factory::create(pelData);
67 _optionalSections.push_back(std::move(section));
68 }
Matt Spinlercb6b0592019-07-16 15:58:51 -050069}
70
71bool PEL::valid() const
72{
73 bool valid = _ph->valid();
74
75 if (valid)
76 {
77 valid = _uh->valid();
78 }
79
Matt Spinler131870c2019-09-25 13:29:04 -050080 if (valid)
81 {
82 if (!std::all_of(_optionalSections.begin(), _optionalSections.end(),
83 [](const auto& section) { return section->valid(); }))
84 {
85 valid = false;
86 }
87 }
88
Matt Spinlercb6b0592019-07-16 15:58:51 -050089 return valid;
90}
91
92void PEL::setCommitTime()
93{
94 auto now = std::chrono::system_clock::now();
Matt Spinler97d19b42019-10-29 11:34:03 -050095 _ph->setCommitTimestamp(getBCDTime(now));
Matt Spinlercb6b0592019-07-16 15:58:51 -050096}
97
98void PEL::assignID()
99{
Matt Spinler97d19b42019-10-29 11:34:03 -0500100 _ph->setID(generatePELID());
Matt Spinlercb6b0592019-07-16 15:58:51 -0500101}
102
103void PEL::flatten(std::vector<uint8_t>& pelBuffer)
104{
105 Stream pelData{pelBuffer};
Matt Spinlerb8323632019-09-20 15:11:04 -0500106
Matt Spinler07eefc52019-09-26 11:18:26 -0500107 if (!valid())
Matt Spinlercb6b0592019-07-16 15:58:51 -0500108 {
Matt Spinler07eefc52019-09-26 11:18:26 -0500109 using namespace phosphor::logging;
110 log<level::WARNING>("Unflattening an invalid PEL");
Matt Spinlercb6b0592019-07-16 15:58:51 -0500111 }
112
Matt Spinler07eefc52019-09-26 11:18:26 -0500113 _ph->flatten(pelData);
Matt Spinlerb8323632019-09-20 15:11:04 -0500114 _uh->flatten(pelData);
Matt Spinler07eefc52019-09-26 11:18:26 -0500115
116 for (auto& section : _optionalSections)
117 {
118 section->flatten(pelData);
119 }
Matt Spinlercb6b0592019-07-16 15:58:51 -0500120}
121
122std::vector<uint8_t> PEL::data()
123{
Matt Spinler07eefc52019-09-26 11:18:26 -0500124 std::vector<uint8_t> pelData;
125 flatten(pelData);
126 return pelData;
Matt Spinlercb6b0592019-07-16 15:58:51 -0500127}
128
Matt Spinlerbd716f02019-10-15 10:54:11 -0500129std::optional<SRC*> PEL::primarySRC() const
130{
131 auto src = std::find_if(
132 _optionalSections.begin(), _optionalSections.end(), [](auto& section) {
133 return section->header().id ==
134 static_cast<uint16_t>(SectionID::primarySRC);
135 });
136 if (src != _optionalSections.end())
137 {
138 return static_cast<SRC*>(src->get());
139 }
140
141 return std::nullopt;
142}
143
Matt Spinlerafa857c2019-10-24 13:03:46 -0500144namespace util
145{
146
147std::unique_ptr<UserData> makeADUserDataSection(const AdditionalData& ad)
148{
149 assert(!ad.empty());
150 nlohmann::json json;
151
152 // Remove the 'ESEL' entry, as it contains a full PEL in the value.
153 if (ad.getValue("ESEL"))
154 {
155 auto newAD = ad;
156 newAD.remove("ESEL");
157 json = newAD.toJSON();
158 }
159 else
160 {
161 json = ad.toJSON();
162 }
163
164 auto jsonString = json.dump();
165 std::vector<uint8_t> jsonData(jsonString.begin(), jsonString.end());
166
167 return std::make_unique<UserData>(
168 static_cast<uint16_t>(ComponentID::phosphorLogging),
169 static_cast<uint8_t>(UserDataFormat::json),
170 static_cast<uint8_t>(UserDataFormatVersion::json), jsonData);
171}
172
173} // namespace util
Matt Spinlercb6b0592019-07-16 15:58:51 -0500174} // namespace pels
175} // namespace openpower