PEL: Add the DRAM manufacturer info of DIMM callout in UD section
Add the called out DIMMs DRAM manufacturer info to the user data
section of the PEL to assist the service engineers in identifying the
manufacturer of the faulty DRAMs packaged within the DIMM module
directly from the logs, aiding in quick resolution.
The changes also moves the pdbg target and libekb initialization to
the PEL startup which avoids the need of multiple initialization as
the existing design.
When a PEL calls out a DIMM FRU, the DRAM manufacturer ID and the
expanded location code of those DIMMs are added to the SysInfo user
data section of the generated PEL in JSON format under the key 'DIMMs
Additional Info'.
In case of any errors occur during the collection or processing of
the manufacturer data, the error messages will be logged in the 'PEL
Internal Debug Data' section as a JSON array under the key 'DIMMs Info
Fetch Error' as a separate user data section.
Tested :
Below is a portion of PEL(callout section and User Data section are
shown) which callout the DIMM P0-C32.
```
"Hex Word 9": "00000000",
"Callout Section": {
"Callout Count": "1",
"Callouts": [{
"FRU Type": "Normal Hardware FRU",
"Priority": "Mandatory, replace all with this
type as a unit",
"Location Code": "UXXX.YYY.WWW004A-P0-C32",
"Part Number": "7777777",
"CCIN": "1234",
"Serial Number": "YYYYYY"
}]
}
```
"User Data": {
"Section Version": "1",
"Sub-section type": "1",
"Created by": "bmc error logging",
"BMCLoad": "0.65 0.69 0.64",
"BMCState": "Ready",
"BMCUptime": "0y 0d 0h 17m 43s",
"BootState": "Unspecified",
"ChassisState": "Off",
"DIMMs Additional Info": [
{
"DRAM Manufacturer ID": [
"0x88",
"0xAA"
]
"Location Code": "UXXX.YYY.WWW004A-P0-C32",
}
],
"FW Version ID": "fw1060.20-4-1060.2432.20240729a (NL1060_068)",
"HostState": "Off",
"System IM": "50001001"
}
```
Change-Id: I2ff81c66e63b99e8e84378ec78f586fb9b6322d7
Signed-off-by: Arya K Padman <aryakpadman@gmail.com>
diff --git a/extensions/openpower-pels/data_interface.cpp b/extensions/openpower-pels/data_interface.cpp
index 9e2a7e5..3cef1ab 100644
--- a/extensions/openpower-pels/data_interface.cpp
+++ b/extensions/openpower-pels/data_interface.cpp
@@ -22,6 +22,10 @@
#include <xyz/openbmc_project/State/BMC/server.hpp>
#include <xyz/openbmc_project/State/Boot/Progress/server.hpp>
+#ifdef PEL_ENABLE_PHAL
+#include <libphal.H>
+#endif
+
// Use a timeout of 10s for D-Bus calls so if there are
// timeouts the callers of the PEL creation method won't
// also timeout.
@@ -880,6 +884,107 @@
return std::get<1>(rawProgress);
}
+std::optional<std::vector<uint8_t>>
+ DataInterface::getDIProperty(const std::string& locationCode) const
+{
+ std::vector<uint8_t> viniDI;
+
+ try
+ {
+ // Note : The hardcoded value 0 should be changed when comes to
+ // multinode system.
+ auto objectPath = getInventoryFromLocCode(locationCode, 0, true);
+
+ DBusValue value;
+ getProperty(service_name::inventoryManager, objectPath[0],
+ interface::viniRecordVPD, "DI", value);
+
+ viniDI = std::get<std::vector<uint8_t>>(value);
+ }
+ catch (const std::exception& e)
+ {
+ lg2::warning(
+ "Failed reading DI property for the location code : {LOC_CODE} from "
+ "interface: {IFACE} exception: {ERROR}",
+ "LOC_CODE", locationCode, "IFACE", interface::viniRecordVPD,
+ "ERROR", e);
+ return std::nullopt;
+ }
+
+ return viniDI;
+}
+
+std::optional<bool>
+ DataInterfaceBase::isDIMMLocCode(const std::string& locCode) const
+{
+ if (_locationCache.contains(locCode))
+ {
+ return _locationCache.at(locCode);
+ }
+ else
+ {
+ return std::nullopt;
+ }
+}
+
+void DataInterfaceBase::addDIMMLocCode(const std::string& locCode,
+ bool isFRUDIMM)
+{
+ _locationCache.insert({locCode, isFRUDIMM});
+}
+
+std::expected<bool, std::string>
+ DataInterfaceBase::isDIMM(const std::string& locCode)
+{
+ auto isDIMMType = isDIMMLocCode(locCode);
+ if (isDIMMType.has_value())
+ {
+ return isDIMMType.value();
+ }
+#ifndef PEL_ENABLE_PHAL
+ return std::unexpected<std::string>(
+ std::format("PHAL feature is not enabled, so the LocationCode:[{}] "
+ "cannot be determined as DIMM",
+ locCode));
+#else
+ else
+ {
+ // Invoke pHAL API inorder to fetch the FRU Type
+ auto fruType = openpower::phal::pdbg::getFRUType(locCode);
+ if (fruType.has_value())
+ {
+ bool isDIMMFRU{false};
+ if (fruType.value() == ENUM_ATTR_TYPE_DIMM)
+ {
+ isDIMMFRU = true;
+ }
+ addDIMMLocCode(locCode, isDIMMFRU);
+ return isDIMMFRU;
+ }
+ else
+ {
+ std::string msg{std::format("Failed to determine the HW Type, "
+ "LocationCode:[{}]",
+ locCode)};
+ if (openpower::phal::exception::errMsgMap.contains(fruType.error()))
+ {
+ msg = std::format(
+ "{} PHALErrorMsg:[{}]", msg,
+ openpower::phal::exception::errMsgMap.at(fruType.error()));
+ }
+ else
+ {
+ msg = std::format(
+ "{} PHALErrorMsg:[Unknown PHALErrorCode:{}]", msg,
+ std::to_underlying<openpower::phal::exception::ERR_TYPE>(
+ fruType.error()));
+ }
+ return std::unexpected<std::string>(msg);
+ }
+ }
+#endif
+}
+
void DataInterface::startFruPlugWatch()
{
// Add a watch on inventory InterfacesAdded and then find all