diff options
Diffstat (limited to 'extensions/openpower-pels/src.cpp')
-rw-r--r-- | extensions/openpower-pels/src.cpp | 258 |
1 files changed, 257 insertions, 1 deletions
diff --git a/extensions/openpower-pels/src.cpp b/extensions/openpower-pels/src.cpp index b2b86bf..570c6c6 100644 --- a/extensions/openpower-pels/src.cpp +++ b/extensions/openpower-pels/src.cpp @@ -15,13 +15,18 @@ */ #include "src.hpp" +#include "json_utils.hpp" +#include "paths.hpp" +#include "pel_values.hpp" + #include <phosphor-logging/log.hpp> namespace openpower { namespace pels { - +namespace pv = openpower::pels::pel_values; +namespace rg = openpower::pels::message; using namespace phosphor::logging; void SRC::unflatten(Stream& stream) @@ -177,5 +182,256 @@ void SRC::validate() _valid = failed ? false : true; } +std::optional<std::string> SRC::getErrorDetails(message::Registry& registry, + DetailLevel type, + bool toCache) const +{ + const std::string jsonIndent(indentLevel, 0x20); + std::string errorOut; + uint8_t errorType = + strtoul(asciiString().substr(0, 2).c_str(), nullptr, 16); + if (errorType == static_cast<uint8_t>(SRCType::bmcError) || + errorType == static_cast<uint8_t>(SRCType::powerError)) + { + auto entry = registry.lookup("0x" + asciiString().substr(4, 4), + rg::LookupType::reasonCode, toCache); + if (entry) + { + errorOut.append(jsonIndent + "\"Error Details\": {\n"); + auto errorMsg = getErrorMessage(*entry); + if (errorMsg) + { + if (type == DetailLevel::message) + { + return errorMsg.value(); + } + else + { + jsonInsert(errorOut, "Message", errorMsg.value(), 2); + } + } + if (entry->src.hexwordADFields) + { + std::map<size_t, std::string> adFields = + entry->src.hexwordADFields.value(); + for (const auto& hexwordMap : adFields) + { + jsonInsert(errorOut, hexwordMap.second, + getNumberString("0x%X", + _hexData[getWordIndexFromWordNum( + hexwordMap.first)]), + 2); + } + } + errorOut.erase(errorOut.size() - 2); + errorOut.append("\n"); + errorOut.append(jsonIndent + "},\n"); + return errorOut; + } + } + return std::nullopt; +} + +std::optional<std::string> + SRC::getErrorMessage(const message::Entry& regEntry) const +{ + try + { + if (regEntry.doc.messageArgSources) + { + size_t msgLen = regEntry.doc.message.length(); + char msg[msgLen + 1]; + strcpy(msg, regEntry.doc.message.c_str()); + std::vector<uint32_t> argSourceVals; + std::string message; + const auto& argValues = regEntry.doc.messageArgSources.value(); + for (size_t i = 0; i < argValues.size(); ++i) + { + argSourceVals.push_back(_hexData[getWordIndexFromWordNum( + argValues[i].back() - '0')]); + } + const char* msgPointer = msg; + while (*msgPointer) + { + if (*msgPointer == '%') + { + msgPointer++; + size_t wordIndex = *msgPointer - '0'; + if (isdigit(*msgPointer) && wordIndex >= 1 && + static_cast<uint16_t>(wordIndex) <= + argSourceVals.size()) + { + message.append(getNumberString( + "0x%X", argSourceVals[wordIndex - 1])); + } + else + { + message.append("%" + std::string(1, *msgPointer)); + } + } + else + { + message.push_back(*msgPointer); + } + msgPointer++; + } + return message; + } + else + { + return regEntry.doc.message; + } + } + catch (const std::exception& e) + { + log<level::ERR>("Cannot get error message from registry entry", + entry("ERROR=%s", e.what())); + } + return std::nullopt; +} + +std::optional<std::string> SRC::getCallouts() const +{ + if (!_callouts) + { + return std::nullopt; + } + std::string printOut; + const std::string jsonIndent(indentLevel, 0x20); + const auto& callout = _callouts->callouts(); + const auto& compDescrp = pv::failingComponentType; + printOut.append(jsonIndent + "\"Callout Section\": {\n"); + jsonInsert(printOut, "Callout Count", std::to_string(callout.size()), 2); + printOut.append(jsonIndent + jsonIndent + "\"Callouts\": ["); + for (auto& entry : callout) + { + printOut.append("{\n"); + if (entry->fruIdentity()) + { + jsonInsert( + printOut, "FRU Type", + compDescrp.at(entry->fruIdentity()->failingComponentType()), 3); + jsonInsert(printOut, "Priority", + pv::getValue(entry->priority(), + pel_values::calloutPriorityValues), + 3); + if (!entry->locationCode().empty()) + { + jsonInsert(printOut, "Location Code", entry->locationCode(), 3); + } + if (entry->fruIdentity()->getPN().has_value()) + { + jsonInsert(printOut, "Part Number", + entry->fruIdentity()->getPN().value(), 3); + } + if (entry->fruIdentity()->getMaintProc().has_value()) + { + jsonInsert(printOut, "Procedure Number", + entry->fruIdentity()->getMaintProc().value(), 3); + if (pv::procedureDesc.find( + entry->fruIdentity()->getMaintProc().value()) != + pv::procedureDesc.end()) + { + jsonInsert( + printOut, "Description", + pv::procedureDesc.at( + entry->fruIdentity()->getMaintProc().value()), + 3); + } + } + if (entry->fruIdentity()->getCCIN().has_value()) + { + jsonInsert(printOut, "CCIN", + entry->fruIdentity()->getCCIN().value(), 3); + } + if (entry->fruIdentity()->getSN().has_value()) + { + jsonInsert(printOut, "Serial Number", + entry->fruIdentity()->getSN().value(), 3); + } + } + if (entry->pceIdentity()) + { + const auto& pceIdentMtms = entry->pceIdentity()->mtms(); + if (!pceIdentMtms.machineTypeAndModel().empty()) + { + jsonInsert(printOut, "PCE MTMS", + pceIdentMtms.machineTypeAndModel() + "_" + + pceIdentMtms.machineSerialNumber(), + 3); + } + if (!entry->pceIdentity()->enclosureName().empty()) + { + jsonInsert(printOut, "PCE Name", + entry->pceIdentity()->enclosureName(), 3); + } + } + if (entry->mru()) + { + const auto& mruCallouts = entry->mru()->mrus(); + std::string mruId; + for (auto& element : mruCallouts) + { + if (!mruId.empty()) + { + mruId.append(", " + getNumberString("%08X", element.id)); + } + else + { + mruId.append(getNumberString("%08X", element.id)); + } + } + jsonInsert(printOut, "MRU Id", mruId, 3); + } + printOut.erase(printOut.size() - 2); + printOut.append("\n" + jsonIndent + jsonIndent + "}, "); + }; + printOut.erase(printOut.size() - 2); + printOut.append("]\n" + jsonIndent + "}"); + return printOut; +} + +std::optional<std::string> SRC::getJSON() const +{ + std::string ps; + jsonInsert(ps, "Section Version", getNumberString("%d", _header.version), + 1); + jsonInsert(ps, "Sub-section type", getNumberString("%d", _header.subType), + 1); + jsonInsert(ps, "Created by", getNumberString("0x%X", _header.componentID), + 1); + jsonInsert(ps, "SRC Version", getNumberString("0x%02X", _version), 1); + jsonInsert(ps, "SRC Format", getNumberString("0x%02X", _hexData[0]), 1); + jsonInsert(ps, "Power Control Net Fault", + pv::boolString.at(isPowerFaultEvent()), 1); + rg::Registry registry(getMessageRegistryPath() / rg::registryFileName); + auto errorDetails = getErrorDetails(registry, DetailLevel::json); + if (errorDetails) + { + ps.append(errorDetails.value()); + } + jsonInsert(ps, "Valid Word Count", getNumberString("0x%02X", _wordCount), + 1); + std::string refcode = asciiString(); + refcode = refcode.substr(0, refcode.find(0x20)); + jsonInsert(ps, "Reference Code", refcode, 1); + for (size_t i = 2; i <= _wordCount; i++) + { + jsonInsert( + ps, "Hex Word " + std::to_string(i), + getNumberString("%08X", _hexData[getWordIndexFromWordNum(i)]), 1); + } + auto calloutJson = getCallouts(); + if (calloutJson) + { + ps.append(calloutJson.value()); + } + else + { + ps.erase(ps.size() - 2); + } + return ps; +} + } // namespace pels } // namespace openpower |