Parse FB Unified SEL
Parsing a special Facebook Unified SEL
Tested: Verified this sending command through ipmitool.
Change-Id: Ia954290c6d6713a0b1f47584d4a8795e02efb852
Signed-off-by: Vijay Khemka <vijaykhemka@fb.com>
diff --git a/include/storagecommands.hpp b/include/storagecommands.hpp
index e51e9ca..c63bd22 100644
--- a/include/storagecommands.hpp
+++ b/include/storagecommands.hpp
@@ -109,6 +109,7 @@
static constexpr auto stdErr = "Standard";
static constexpr auto oemTSErr = "OEM timestamped";
+static constexpr auto fbUniSELErr = "Facebook Unified SEL";
static constexpr auto oemNTSErr = "OEM non-timestamped";
static constexpr auto unknownErr = "Unknown";
@@ -116,6 +117,7 @@
static constexpr uint8_t oemTSErrTypeMin = 0xC0;
static constexpr uint8_t oemTSErrTypeMax = 0xDF;
static constexpr uint8_t oemNTSErrTypeMin = 0xE0;
+static constexpr uint8_t fbUniErrType = 0xFB;
static constexpr uint8_t oemNTSErrTypeMax = 0xFF;
static constexpr uint8_t unifiedPcieErr = 0;
diff --git a/src/selcommands.cpp b/src/selcommands.cpp
index f91ee07..ae98ba8 100644
--- a/src/selcommands.cpp
+++ b/src/selcommands.cpp
@@ -303,6 +303,61 @@
return;
}
+static void parseOemUnifiedSel(NtsOemSELEntry *data, std::string &errStr)
+{
+ uint8_t *ptr = data->oemData;
+ int genInfo = ptr[0];
+ int errType = genInfo & 0x0f;
+ std::vector<std::string> dimmEvent = {
+ "Memory training failure", "Memory correctable error",
+ "Memory uncorrectable error", "Reserved"};
+
+ std::stringstream tmpStream;
+ tmpStream << std::hex << std::uppercase << std::setfill('0');
+
+ switch (errType)
+ {
+ case unifiedPcieErr:
+ if (((genInfo & 0x10) >> 4) == 0) // x86
+ {
+ tmpStream << "GeneralInfo: x86/PCIeErr(0x" << std::setw(2)
+ << genInfo << "),";
+ }
+
+ tmpStream << " Bus " << std::setw(2) << (int)(ptr[8]) << "/Dev "
+ << std::setw(2) << (int)(ptr[7] >> 3) << "/Fun "
+ << std::setw(2) << (int)(ptr[7] & 0x7)
+ << ", TotalErrID1Cnt: 0x" << std::setw(4)
+ << (int)((ptr[10] << 8) | ptr[9]) << ", ErrID2: 0x"
+ << std::setw(2) << (int)(ptr[11]) << ", ErrID1: 0x"
+ << std::setw(2) << (int)(ptr[12]);
+
+ break;
+ case unifiedMemErr:
+ tmpStream << "GeneralInfo: MemErr(0x" << std::setw(2) << genInfo
+ << "), DIMM Slot Location: Sled " << std::setw(2)
+ << (int)((ptr[5] >> 4) & 0x03) << "/Socket "
+ << std::setw(2) << (int)(ptr[5] & 0x0f) << ", Channel "
+ << std::setw(2) << (int)(ptr[6] & 0x0f) << ", Slot "
+ << std::setw(2) << (int)(ptr[7] & 0x0f)
+ << ", DIMM Failure Event: " << dimmEvent[(ptr[9] & 0x03)]
+ << ", Major Code: 0x" << std::setw(2) << (int)(ptr[10])
+ << ", Minor Code: 0x" << std::setw(2) << (int)(ptr[11]);
+
+ break;
+ default:
+ std::vector<uint8_t> oemData(ptr, ptr + 13);
+ std::string oemDataStr;
+ toHexStr(oemData, oemDataStr);
+ tmpStream << "Undefined Error Type(0x" << std::setw(2) << errType
+ << "), Raw: " << oemDataStr;
+ }
+
+ errStr = tmpStream.str();
+
+ return;
+}
+
static void parseSelData(std::vector<uint8_t> &reqData, std::string &msgLog)
{
@@ -383,6 +438,13 @@
"), Time: " + timeStr + ", MFG ID: " + mfrIdStr +
", OEM Data: (" + oemDataStr + ") " + errLog;
}
+ else if (recType == fbUniErrType)
+ {
+ NtsOemSELEntry *data = reinterpret_cast<NtsOemSELEntry *>(&reqData[0]);
+ errType = fbUniSELErr;
+ parseOemUnifiedSel(data, errLog);
+ msgLog += errType + " (0x" + recTypeStream.str() + "), " + errLog;
+ }
else if ((recType >= oemNTSErrTypeMin) && (recType <= oemNTSErrTypeMax))
{
/* Non timestamped OEM SEL records */