yosemitev2:Multi-host DIMM info displayed in OCP debug card
This implementation is going to display the DIMM
information in the OCP debug-card.
Tested: information frame value of Dimm info
displayed in the OCP debug card with multi-host
Yosemitev2 platform.
Change-Id: Ia3f198ee99806e25c6fe8e995130d45a9ac0f23b
Signed-off-by: Karthikeyan Pasupathi <pkarthikeyan1509@gmail.com>
diff --git a/include/oemcommands.hpp b/include/oemcommands.hpp
index 65c3adf..a46db3a 100644
--- a/include/oemcommands.hpp
+++ b/include/oemcommands.hpp
@@ -89,6 +89,10 @@
CMD_OEM_Q_GET_DRIVE_INFO = 0x15,
};
+/* To handle the processor product
+ * name (ASCII code). */
+#define MAX_BUF 50
+
#define BMC_POS 0
#define SIZE_CPU_PPIN 8
#define SIZE_BOOT_ORDER 6
@@ -101,6 +105,9 @@
#define BIT_2 0x04
#define BIT_3 0x08
+#define DIMM_TYPE "type"
+#define DIMM_SPEED "speed"
+#define JSON_DIMM_TYPE_FILE "/usr/share/lcd-debug/dimm_type.json"
#define JSON_OEM_DATA_FILE "/etc/oemData.json"
#define KEY_PPIN_INFO "mb_cpu_ppin"
#define KEY_MC_CONFIG "mb_machine_config"
@@ -146,6 +153,9 @@
{"NET_IPV6", 9}, {"SATA_HDD", 2},
{"SATA_CD", 3}, {"OTHER", 4}};
+std::map<size_t, std::string> dimmVenMap = {
+ {0xce, "Samsung"}, {0xad, "Hynix"}, {0x2c, "Micron"}};
+
const char* chassisType[] = {"ORV1", "ORV2"};
const char* mbType[] = {"SS", "DS", "TYPE3"};
const char* riserType[] = {"NO_CARD", "2_SLOT", "3_SLOT"};
diff --git a/src/oemcommands.cpp b/src/oemcommands.cpp
index 50b7a71..7482e1c 100644
--- a/src/oemcommands.cpp
+++ b/src/oemcommands.cpp
@@ -53,6 +53,9 @@
static constexpr size_t maxFRUStringLength = 0x3F;
constexpr uint8_t cmdSetSystemGuid = 0xEF;
+constexpr uint8_t cmdSetQDimmInfo = 0x12;
+constexpr uint8_t cmdGetQDimmInfo = 0x13;
+
int plat_udbg_get_post_desc(uint8_t, uint8_t*, uint8_t, uint8_t*, uint8_t*,
uint8_t*);
int plat_udbg_get_gpio_desc(uint8_t, uint8_t*, uint8_t*, uint8_t*, uint8_t*,
@@ -237,6 +240,30 @@
return i;
}
+int readDimmType(std::string& data, uint8_t param)
+{
+ nlohmann::json dimmObj;
+ /* Get dimm type names stored in json file */
+ std::ifstream file(JSON_DIMM_TYPE_FILE);
+ if (file)
+ {
+ file >> dimmObj;
+ file.close();
+ }
+ else
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "DIMM type names file not found",
+ phosphor::logging::entry("DIMM_TYPE_FILE=%s", JSON_DIMM_TYPE_FILE));
+ return -1;
+ }
+
+ std::string dimmKey = "dimm_type" + std::to_string(param);
+ auto obj = dimmObj[dimmKey]["short_name"];
+ data = obj;
+ return 0;
+}
+
ipmi_ret_t getNetworkData(uint8_t lan_param, char* data)
{
ipmi_ret_t rc = IPMI_CC_OK;
@@ -403,6 +430,92 @@
return -1;
}
+int8_t sysConfig(std::vector<std::string>& data, size_t pos)
+{
+ nlohmann::json sysObj;
+ std::string dimmInfo = KEY_Q_DIMM_INFO + std::to_string(pos);
+ std::string result, typeName;
+ uint8_t res[MAX_BUF];
+
+ /* Get sysConfig data stored in json file */
+ std::ifstream file(JSON_OEM_DATA_FILE);
+ if (file)
+ {
+ file >> sysObj;
+ file.close();
+ }
+ else
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "oemData file not found",
+ phosphor::logging::entry("OEM_DATA_FILE=%s", JSON_OEM_DATA_FILE));
+ return -1;
+ }
+
+ if (sysObj.find(dimmInfo) == sysObj.end())
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "sysconfig key not available",
+ phosphor::logging::entry("SYS_JSON_KEY=%s", dimmInfo.c_str()));
+ return -1;
+ }
+ /* Get dimm type names stored in json file */
+ nlohmann::json dimmObj;
+ std::ifstream dimmFile(JSON_DIMM_TYPE_FILE);
+ if (file)
+ {
+ dimmFile >> dimmObj;
+ dimmFile.close();
+ }
+ else
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "DIMM type names file not found",
+ phosphor::logging::entry("DIMM_TYPE_FILE=%s", JSON_DIMM_TYPE_FILE));
+ return -1;
+ }
+ std::vector<std::string> a;
+ for (auto& j : dimmObj.items())
+ {
+ std::string name = j.key();
+ a.push_back(name);
+ }
+
+ uint8_t len = a.size();
+ for (uint8_t ii = 0; ii < len; ii++)
+ {
+ std::string indKey = std::to_string(ii);
+ std::string speedSize = sysObj[dimmInfo][indKey][DIMM_SPEED];
+ strToBytes(speedSize, res);
+ auto speed = (res[1] << 8 | res[0]);
+ size_t dimmSize = ((res[3] << 8 | res[2]) / 1000);
+
+ if (dimmSize == 0)
+ {
+ std::cerr << "Dimm information not available for slot_" +
+ std::to_string(ii)
+ << std::endl;
+ continue;
+ }
+ std::string type = sysObj[dimmInfo][indKey][DIMM_TYPE];
+ std::string dualInlineMem = sysObj[dimmInfo][indKey][KEY_DIMM_TYPE];
+ strToBytes(type, res);
+ size_t dimmType = res[0];
+ if (dimmVenMap.find(dimmType) == dimmVenMap.end())
+ {
+ typeName = "unknown";
+ }
+ else
+ {
+ typeName = dimmVenMap[dimmType];
+ }
+ result = dualInlineMem + "/" + typeName + "/" + std::to_string(speed) +
+ "MHz" + "/" + std::to_string(dimmSize) + "GB";
+ data.push_back(result);
+ }
+ return 0;
+}
+
typedef struct
{
uint8_t cur_power_state;
@@ -1461,41 +1574,44 @@
// Byte 1 - Module Manufacturer ID, LSB
// Byte 2 - Module Manufacturer ID, MSB
//
-ipmi_ret_t ipmiOemQSetDimmInfo(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
- ipmi_response_t, ipmi_data_len_t data_len,
- ipmi_context_t)
+ipmi::RspType<> ipmiOemQSetDimmInfo(ipmi::Context::ptr ctx, uint8_t, uint8_t,
+ uint8_t, uint8_t dimmIndex,
+ uint8_t paramSel,
+ std::vector<uint8_t> request)
{
- qDimmInfo_t* req = reinterpret_cast<qDimmInfo_t*>(request);
uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
std::stringstream ss;
std::string str;
- uint8_t len = *data_len;
+ uint8_t len = request.size();
+ std::string dimmType;
+ readDimmType(dimmType, dimmIndex);
+ auto hostId = ipmi::boot::findHost(ctx->hostIdx);
+ if (!hostId)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Invalid Host Id received");
+ return ipmi::responseInvalidCommand();
+ }
- *data_len = 0;
+ std::string dimmInfo = KEY_Q_DIMM_INFO + std::to_string(*hostId);
- /* check for requested data params */
- if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam)
+ if (len < 3 || paramSel < 1 || paramSel >= numParam)
{
phosphor::logging::log<phosphor::logging::level::ERR>(
"Invalid parameter received");
- return IPMI_CC_PARM_OUT_OF_RANGE;
+ return ipmi::responseParmOutOfRange();
}
- len = len - 5; // Get Actual data length
-
ss << std::hex;
- ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex;
- oemData[KEY_Q_DIMM_INFO][ss.str()][KEY_DIMM_INDEX] = req->dimmIndex;
-
- str = bytesToStr(req->data, len);
- oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]] =
- str.c_str();
+ ss << (int)dimmIndex;
+ oemData[dimmInfo][ss.str()][KEY_DIMM_INDEX] = dimmIndex;
+ oemData[dimmInfo][ss.str()][KEY_DIMM_TYPE] = dimmType;
+ str = bytesToStr(request.data(), len);
+ oemData[dimmInfo][ss.str()][dimmInfoKey[paramSel]] = str.c_str();
flushOemData();
-
- return IPMI_CC_OK;
+ return ipmi::responseSuccess();
}
-//----------------------------------------------------------------------
// Get Dimm Info (CMD_OEM_Q_GET_DIMM_INFO)
//----------------------------------------------------------------------
// Request:
@@ -1554,41 +1670,43 @@
// Byte 1 - Module Manufacturer ID, LSB
// Byte 2 - Module Manufacturer ID, MSB
//
-ipmi_ret_t ipmiOemQGetDimmInfo(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
- ipmi_response_t response,
- ipmi_data_len_t data_len, ipmi_context_t)
+ipmi::RspType<std::vector<uint8_t>>
+ ipmiOemQGetDimmInfo(ipmi::Context::ptr ctx, uint8_t, uint8_t, uint8_t,
+ uint8_t dimmIndex, uint8_t paramSel)
{
- qDimmInfo_t* req = reinterpret_cast<qDimmInfo_t*>(request);
uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*);
- uint8_t* res = reinterpret_cast<uint8_t*>(response);
+ uint8_t res[MAX_BUF];
std::stringstream ss;
std::string str;
+ std::string dimmType;
+ readDimmType(dimmType, dimmIndex);
+ auto hostId = ipmi::boot::findHost(ctx->hostIdx);
+ if (!hostId)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Invalid Host Id received");
+ return ipmi::responseInvalidCommand();
+ }
+ std::string dimmInfo = KEY_Q_DIMM_INFO + std::to_string(*hostId);
- *data_len = 0;
-
- /* check for requested data params */
- if (req->paramSel < 1 || req->paramSel >= numParam)
+ if (paramSel < 1 || paramSel >= numParam)
{
phosphor::logging::log<phosphor::logging::level::ERR>(
"Invalid parameter received");
- return IPMI_CC_PARM_OUT_OF_RANGE;
+ return ipmi::responseParmOutOfRange();
}
-
ss << std::hex;
- ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex;
-
- if (oemData[KEY_Q_DIMM_INFO].find(ss.str()) ==
- oemData[KEY_Q_DIMM_INFO].end())
- return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
-
- if (oemData[KEY_Q_DIMM_INFO][ss.str()].find(dimmInfoKey[req->paramSel]) ==
- oemData[KEY_Q_DIMM_INFO][ss.str()].end())
- return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
-
- str = oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]];
- *data_len = strToBytes(str, res);
-
- return IPMI_CC_OK;
+ ss << (int)dimmIndex;
+ oemData[dimmInfo][ss.str()][KEY_DIMM_TYPE] = dimmType;
+ if (oemData[dimmInfo].find(ss.str()) == oemData[dimmInfo].end())
+ return ipmi::responseCommandNotAvailable();
+ if (oemData[dimmInfo][ss.str()].find(dimmInfoKey[paramSel]) ==
+ oemData[dimmInfo][ss.str()].end())
+ return ipmi::responseCommandNotAvailable();
+ str = oemData[dimmInfo][ss.str()][dimmInfoKey[paramSel]];
+ int data_length = strToBytes(str, res);
+ std::vector<uint8_t> response(&res[0], &res[data_length]);
+ return ipmi::responseSuccess(response);
}
//----------------------------------------------------------------------
@@ -1893,12 +2011,12 @@
ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_PROC_INFO, NULL,
ipmiOemQGetProcInfo,
PRIVILEGE_USER); // Get Proc Info
- ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DIMM_INFO, NULL,
- ipmiOemQSetDimmInfo,
- PRIVILEGE_USER); // Set Dimm Info
- ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DIMM_INFO, NULL,
- ipmiOemQGetDimmInfo,
- PRIVILEGE_USER); // Get Dimm Info
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFour,
+ ipmi::cmdSetQDimmInfo, ipmi::Privilege::User,
+ ipmiOemQSetDimmInfo); // Set Dimm Info
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFour,
+ ipmi::cmdGetQDimmInfo, ipmi::Privilege::User,
+ ipmiOemQGetDimmInfo); // Get Dimm Info
ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DRIVE_INFO, NULL,
ipmiOemQSetDriveInfo,
PRIVILEGE_USER); // Set Drive Info
diff --git a/src/usb-dbg.cpp b/src/usb-dbg.cpp
index 7b76310..b886525 100644
--- a/src/usb-dbg.cpp
+++ b/src/usb-dbg.cpp
@@ -22,6 +22,7 @@
ipmi_ret_t getNetworkData(uint8_t lan_param, char* data);
int8_t getFruData(std::string& serial, std::string& name);
+int8_t sysConfig(std::vector<std::string>& data, size_t pos);
bool isMultiHostPlatform();
@@ -123,7 +124,7 @@
// return 0 on seccuess
int frame::append(const char* string, int indent)
{
- const size_t buf_size = 64;
+ const size_t buf_size = 128;
char lbuf[buf_size];
char* ptr;
int ret;
@@ -1029,8 +1030,19 @@
frame_info.append("MCU_ver:", 0);
frame_info.append(ESC_MCU_RUN_VER, 1);
- // TBD:
// Sys config present device
+ if (hostPosition != BMC_POSITION)
+ {
+ frame_info.append("Sys Conf. info:", 0);
+
+ // Dimm info
+ std::vector<std::string> data;
+ sysConfig(data, pos);
+ for (auto& info : data)
+ {
+ frame_info.append(info.c_str(), 1);
+ }
+ }
} // End of update frame
diff --git a/yosemitev2/dimm_type.json b/yosemitev2/dimm_type.json
new file mode 100644
index 0000000..cb5e60f
--- /dev/null
+++ b/yosemitev2/dimm_type.json
@@ -0,0 +1,34 @@
+{
+ "dimm_type0":
+ {
+ "short_name": "MEMA0"
+ },
+ "dimm_type1":
+ {
+ "short_name": "MEMA1"
+ },
+ "dimm_type2":
+ {
+ "short_name": "MEMB0"
+ },
+ "dimm_type3":
+ {
+ "short_name": "MEMB1"
+ },
+ "dimm_type4":
+ {
+ "short_name": "MEMD0"
+ },
+ "dimm_type5":
+ {
+ "short_name": "MEMD1"
+ },
+ "dimm_type6":
+ {
+ "short_name": "MEME0"
+ },
+ "dimm_type7":
+ {
+ "short_name": "MEME1"
+ }
+}