blob: ffd4974e83b9a5bfeb393ef92fa2ce48805b21a6 [file] [log] [blame]
#include "pel.hpp"
#include "bcd_time.hpp"
#include "failing_mtms.hpp"
#include "log_id.hpp"
#include "section_factory.hpp"
#include "src.hpp"
#include "stream.hpp"
#include <phosphor-logging/log.hpp>
namespace openpower
{
namespace pels
{
namespace message = openpower::pels::message;
PEL::PEL(const message::Entry& entry, uint32_t obmcLogID, uint64_t timestamp,
phosphor::logging::Entry::Level severity,
const AdditionalData& additionalData,
const DataInterfaceBase& dataIface)
{
_ph = std::make_unique<PrivateHeader>(entry.componentID, obmcLogID,
timestamp);
_uh = std::make_unique<UserHeader>(entry, severity);
auto src = std::make_unique<SRC>(entry, additionalData);
_optionalSections.push_back(std::move(src));
auto mtms = std::make_unique<FailingMTMS>(dataIface);
_optionalSections.push_back(std::move(mtms));
_ph->sectionCount() = 2 + _optionalSections.size();
}
PEL::PEL(std::vector<uint8_t>& data) : PEL(data, 0)
{
}
PEL::PEL(std::vector<uint8_t>& data, uint32_t obmcLogID)
{
populateFromRawData(data, obmcLogID);
}
void PEL::populateFromRawData(std::vector<uint8_t>& data, uint32_t obmcLogID)
{
Stream pelData{data};
_ph = std::make_unique<PrivateHeader>(pelData);
if (obmcLogID != 0)
{
_ph->obmcLogID() = obmcLogID;
}
_uh = std::make_unique<UserHeader>(pelData);
// Use the section factory to create the rest of the objects
for (size_t i = 2; i < _ph->sectionCount(); i++)
{
auto section = section_factory::create(pelData);
_optionalSections.push_back(std::move(section));
}
}
bool PEL::valid() const
{
bool valid = _ph->valid();
if (valid)
{
valid = _uh->valid();
}
if (valid)
{
if (!std::all_of(_optionalSections.begin(), _optionalSections.end(),
[](const auto& section) { return section->valid(); }))
{
valid = false;
}
}
return valid;
}
void PEL::setCommitTime()
{
auto now = std::chrono::system_clock::now();
_ph->commitTimestamp() = getBCDTime(now);
}
void PEL::assignID()
{
_ph->id() = generatePELID();
}
void PEL::flatten(std::vector<uint8_t>& pelBuffer)
{
Stream pelData{pelBuffer};
if (!valid())
{
using namespace phosphor::logging;
log<level::WARNING>("Unflattening an invalid PEL");
}
_ph->flatten(pelData);
_uh->flatten(pelData);
for (auto& section : _optionalSections)
{
section->flatten(pelData);
}
}
std::vector<uint8_t> PEL::data()
{
std::vector<uint8_t> pelData;
flatten(pelData);
return pelData;
}
std::optional<SRC*> PEL::primarySRC() const
{
auto src = std::find_if(
_optionalSections.begin(), _optionalSections.end(), [](auto& section) {
return section->header().id ==
static_cast<uint16_t>(SectionID::primarySRC);
});
if (src != _optionalSections.end())
{
return static_cast<SRC*>(src->get());
}
return std::nullopt;
}
} // namespace pels
} // namespace openpower