summaryrefslogtreecommitdiffstats
path: root/extensions/openpower-pels/manager.cpp
diff options
context:
space:
mode:
authorMatt Spinler <spinler@us.ibm.com>2020-01-24 11:05:20 -0600
committerMatt Spinler <spinler@us.ibm.com>2020-02-14 19:15:42 +0000
commit19e729013197be8ba7faccd88004043ac1e7e27f (patch)
treee79843df36fa1ab5de5a0f59c44003f649f86259 /extensions/openpower-pels/manager.cpp
parente95fd0154e723813f5d7bf981e97b7ca6f28f7ef (diff)
downloadphosphor-logging-19e729013197be8ba7faccd88004043ac1e7e27f.tar.gz
phosphor-logging-19e729013197be8ba7faccd88004043ac1e7e27f.zip
PEL: Add PELs from ESELs
When the OpenPower host firmware subsystem hostboot creates PELs, those PELs get added to OpenBMC event logs in the ESEL entry of the AdditionalData property. (Eventually hostboot will update their code to use PLDM to send down PELs.) This commit looks for that ESEL keyword on incoming event logs, extracts the PEL data, and adds it to the PEL repository with all of the other PELs. It extracts the PEL data by converting the string value to a vector of uint8_ts starting after the IPMI data fields contained in that string. Signed-off-by: Matt Spinler <spinler@us.ibm.com> Change-Id: I2b7f2915dceb9c306466b8181cae05a3ddd65057
Diffstat (limited to 'extensions/openpower-pels/manager.cpp')
-rw-r--r--extensions/openpower-pels/manager.cpp157
1 files changed, 112 insertions, 45 deletions
diff --git a/extensions/openpower-pels/manager.cpp b/extensions/openpower-pels/manager.cpp
index 05ccb42..4eb6772 100644
--- a/extensions/openpower-pels/manager.cpp
+++ b/extensions/openpower-pels/manager.cpp
@@ -39,7 +39,8 @@ namespace common_error = sdbusplus::xyz::openbmc_project::Common::Error;
namespace additional_data
{
constexpr auto rawPEL = "RAWPEL";
-}
+constexpr auto esel = "ESEL";
+} // namespace additional_data
void Manager::create(const std::string& message, uint32_t obmcLogID,
uint64_t timestamp, Entry::Level severity,
@@ -48,7 +49,8 @@ void Manager::create(const std::string& message, uint32_t obmcLogID,
{
AdditionalData ad{additionalData};
- // If a PEL was passed in, use that. Otherwise, create one.
+ // If a PEL was passed in via a filename or in an ESEL,
+ // use that. Otherwise, create one.
auto rawPelPath = ad.getValue(additional_data::rawPEL);
if (rawPelPath)
{
@@ -56,8 +58,16 @@ void Manager::create(const std::string& message, uint32_t obmcLogID,
}
else
{
- createPEL(message, obmcLogID, timestamp, severity, additionalData,
- associations);
+ auto esel = ad.getValue(additional_data::esel);
+ if (esel)
+ {
+ addESELPEL(*esel, obmcLogID);
+ }
+ else
+ {
+ createPEL(message, obmcLogID, timestamp, severity, additionalData,
+ associations);
+ }
}
}
@@ -80,55 +90,113 @@ void Manager::addRawPEL(const std::string& rawPelPath, uint32_t obmcLogID)
file.close();
- auto pel = std::make_unique<openpower::pels::PEL>(data, obmcLogID);
- if (pel->valid())
- {
- // PELs created by others still need these fields set by us.
- pel->assignID();
- pel->setCommitTime();
+ addPEL(data, obmcLogID);
+ }
+ else
+ {
+ log<level::ERR>("Raw PEL file from BMC event log does not exist",
+ entry("PELFILE=%s", (rawPelPath).c_str()),
+ entry("OBMCLOGID=%d", obmcLogID));
+ }
+}
- try
- {
- _repo.add(pel);
- }
- catch (std::exception& e)
- {
- // Probably a full or r/o filesystem, not much we can do.
- log<level::ERR>("Unable to add PEL to Repository",
- entry("PEL_ID=0x%X", pel->id()));
- }
+void Manager::addPEL(std::vector<uint8_t>& pelData, uint32_t obmcLogID)
+{
+
+ auto pel = std::make_unique<openpower::pels::PEL>(pelData, obmcLogID);
+ if (pel->valid())
+ {
+ // PELs created by others still need these fields set by us.
+ pel->assignID();
+ pel->setCommitTime();
+
+ try
+ {
+ _repo.add(pel);
}
- else
+ catch (std::exception& e)
{
- log<level::ERR>("Invalid PEL received from the host",
- entry("PELFILE=%s", rawPelPath.c_str()),
- entry("OBMCLOGID=%d", obmcLogID));
+ // Probably a full or r/o filesystem, not much we can do.
+ log<level::ERR>("Unable to add PEL to Repository",
+ entry("PEL_ID=0x%X", pel->id()));
+ }
+ }
+ else
+ {
+ log<level::ERR>("Invalid PEL received from the host",
+ entry("OBMCLOGID=%d", obmcLogID));
- AdditionalData ad;
- ad.add("PLID", getNumberString("0x%08X", pel->plid()));
- ad.add("OBMC_LOG_ID", std::to_string(obmcLogID));
- ad.add("RAW_PEL_FILENAME", rawPelPath);
- ad.add("PEL_SIZE", std::to_string(data.size()));
+ AdditionalData ad;
+ ad.add("PLID", getNumberString("0x%08X", pel->plid()));
+ ad.add("OBMC_LOG_ID", std::to_string(obmcLogID));
+ ad.add("PEL_SIZE", std::to_string(pelData.size()));
- std::string asciiString;
- auto src = pel->primarySRC();
- if (src)
- {
- asciiString = (*src)->asciiString();
- }
+ std::string asciiString;
+ auto src = pel->primarySRC();
+ if (src)
+ {
+ asciiString = (*src)->asciiString();
+ }
- ad.add("SRC", asciiString);
+ ad.add("SRC", asciiString);
- _eventLogger.log("org.open_power.Logging.Error.BadHostPEL",
- Entry::Level::Error, ad);
- }
+ _eventLogger.log("org.open_power.Logging.Error.BadHostPEL",
+ Entry::Level::Error, ad);
}
- else
+}
+
+void Manager::addESELPEL(const std::string& esel, uint32_t obmcLogID)
+{
+ std::vector<uint8_t> data;
+
+ try
{
- log<level::ERR>("Raw PEL file from BMC event log does not exist",
- entry("PELFILE=%s", (rawPelPath).c_str()),
- entry("OBMCLOGID=%d", obmcLogID));
+ data = std::move(eselToRawData(esel));
+ }
+ catch (std::exception& e)
+ {
+ // Try to add it below anyway, so it follows the usual bad data path.
+ log<level::ERR>("Problems converting ESEL string to a byte vector");
+ }
+
+ addPEL(data, obmcLogID);
+}
+
+std::vector<uint8_t> Manager::eselToRawData(const std::string& esel)
+{
+ std::vector<uint8_t> data;
+ std::string byteString;
+
+ // As the eSEL string looks like: "50 48 00 ab ..." there are 3
+ // characters per raw byte, and since the actual PEL data starts
+ // at the 16th byte, the code will grab the PEL data starting at
+ // offset 48 in the string.
+ static constexpr size_t pelStart = 16 * 3;
+
+ if (esel.size() <= pelStart)
+ {
+ log<level::ERR>("ESEL data too short",
+ entry("ESEL_SIZE=%d", esel.size()));
+
+ throw std::length_error("ESEL data too short");
}
+
+ for (size_t i = pelStart; i < esel.size(); i += 3)
+ {
+ if (i + 1 < esel.size())
+ {
+ byteString = esel.substr(i, 2);
+ data.push_back(std::stoi(byteString, nullptr, 16));
+ }
+ else
+ {
+ log<level::ERR>("ESEL data too short",
+ entry("ESEL_SIZE=%d", esel.size()));
+ throw std::length_error("ESEL data too short");
+ }
+ }
+
+ return data;
}
void Manager::erase(uint32_t obmcLogID)
@@ -165,8 +233,7 @@ void Manager::createPEL(const std::string& message, uint32_t obmcLogID,
if (src)
{
using namespace std::literals::string_literals;
- char id[11];
- sprintf(id, "0x%08X", pel->id());
+ auto id = getNumberString("0x%08X", pel->id());
msg = "Created PEL "s + id + " with SRC "s + (*src)->asciiString();
while (msg.back() == ' ')
{
OpenPOWER on IntegriCloud