summaryrefslogtreecommitdiffstats
path: root/extensions/openpower-pels/src.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/openpower-pels/src.cpp')
-rw-r--r--extensions/openpower-pels/src.cpp258
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
OpenPOWER on IntegriCloud