diff options
Diffstat (limited to 'extensions')
-rw-r--r-- | extensions/openpower-pels/manager.cpp | 157 | ||||
-rw-r--r-- | extensions/openpower-pels/manager.hpp | 31 |
2 files changed, 143 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() == ' ') { diff --git a/extensions/openpower-pels/manager.hpp b/extensions/openpower-pels/manager.hpp index bec67ca..86030d4 100644 --- a/extensions/openpower-pels/manager.hpp +++ b/extensions/openpower-pels/manager.hpp @@ -161,6 +161,20 @@ class Manager : public PELInterface */ void hostReject(uint32_t pelID, RejectionReason reason) override; + /** + * @brief Converts the ESEL field in an OpenBMC event log to a + * vector of uint8_ts that just contains the PEL data. + * + * That data string looks like: "50 48 00 ab ..." + * + * Throws an exception on any failures. + * + * @param[in] esel - The ESEL string + * + * @return std::vector<uint8_t> - The contained PEL data + */ + static std::vector<uint8_t> eselToRawData(const std::string& esel); + private: /** * @brief Adds a received raw PEL to the PEL repository @@ -208,6 +222,23 @@ class Manager : public PELInterface void closeFD(int fd, sdeventplus::source::EventBase& source); /** + * @brief Adds a PEL to the repository given its data + * + * @param[in] pelData - The PEL to add as a vector of uint8_ts + * @param[in] obmcLogID - the OpenBMC event log ID + */ + void addPEL(std::vector<uint8_t>& pelData, uint32_t obmcLogID); + + /** + * @brief Adds the PEL stored in the ESEL field of the AdditionalData + * property of an OpenBMC event log to the repository. + * + * @param[in] esel - The ESEL AdditionalData contents + * @param[in] obmcLogID - The OpenBMC event log ID + */ + void addESELPEL(const std::string& esel, uint32_t obmcLogID); + + /** * @brief Reference to phosphor-logging's Manager class */ phosphor::logging::internal::Manager& _logManager; |