yosemitev2:Multi-host CPU info displayed in OCP debug-card.

This implementation is going to display the processor
information in the OCP debug-card.

Tested: information frame value of processor info
displayed in the OCP debug card with multi-host
Yosemitev2 platform.

Signed-off-by: Karthikeyan Pasupathi <pkarthikeyan1509@gmail.com>
Change-Id: Iec29bae79a4c56d92184a69ea187549895f34db9
diff --git a/include/oemcommands.hpp b/include/oemcommands.hpp
index a46db3a..6165b5e 100644
--- a/include/oemcommands.hpp
+++ b/include/oemcommands.hpp
@@ -105,6 +105,8 @@
 #define BIT_2 0x04
 #define BIT_3 0x08
 
+#define KEY_PROC_NAME "product_name"
+#define KEY_BASIC_INFO "basic_info"
 #define DIMM_TYPE "type"
 #define DIMM_SPEED "speed"
 #define JSON_DIMM_TYPE_FILE "/usr/share/lcd-debug/dimm_type.json"
diff --git a/src/oemcommands.cpp b/src/oemcommands.cpp
index 30d183c..577f513 100644
--- a/src/oemcommands.cpp
+++ b/src/oemcommands.cpp
@@ -39,6 +39,7 @@
 #include <sstream>
 #include <string>
 #include <vector>
+#include <regex>
 
 #define SIZE_IANA_ID 3
 
@@ -516,6 +517,56 @@
     return 0;
 }
 
+int8_t procInfo(std::string& result, size_t pos)
+{
+    std::vector<char> data;
+    uint8_t res[MAX_BUF];
+    std::string procIndex = "00";
+    nlohmann::json proObj;
+    std::string procInfo = KEY_Q_PROC_INFO + std::to_string(pos);
+    /* Get processor data stored in json file */
+    std::ifstream file(JSON_OEM_DATA_FILE);
+    if (file)
+    {
+        file >> proObj;
+        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 (proObj.find(procInfo) == proObj.end())
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "processor info key not available",
+            phosphor::logging::entry("PROC_JSON_KEY=%s", procInfo.c_str()));
+        return -1;
+    }
+    std::string procName = proObj[procInfo][procIndex][KEY_PROC_NAME];
+    std::string basicInfo = proObj[procInfo][procIndex][KEY_BASIC_INFO];
+    // Processor Product Name
+    strToBytes(procName, res);
+    data.assign(reinterpret_cast<char*>(&res),
+                reinterpret_cast<char*>(&res) + sizeof(res));
+
+    std::string s(data.begin(), data.end());
+    std::regex regex(" ");
+    std::vector<std::string> productName(
+        std::sregex_token_iterator(s.begin(), s.end(), regex, -1),
+        std::sregex_token_iterator());
+
+    // Processor core and frequency
+    strToBytes(basicInfo, res);
+    uint16_t coreNum = res[0];
+    double procFrequency = (float)(res[4] << 8 | res[3]) / 1000;
+    result = "CPU:" + productName[2] + "/" + std::to_string(procFrequency) +
+             "GHz" + "/" + std::to_string(coreNum) + "c";
+    return 0;
+}
+
 typedef struct
 {
     uint8_t cur_power_state;
@@ -1422,37 +1473,38 @@
 // Byte 5 – Processor frequency in MHz (MSB)
 // Byte 6..7 – Revision
 //
-ipmi_ret_t ipmiOemQSetProcInfo(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
-                               ipmi_response_t, ipmi_data_len_t data_len,
-                               ipmi_context_t)
+
+ipmi::RspType<> ipmiOemQSetProcInfo(ipmi::Context::ptr ctx, uint8_t, uint8_t,
+                                    uint8_t, uint8_t procIndex,
+                                    uint8_t paramSel,
+                                    std::vector<uint8_t> request)
 {
-    qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request);
     uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
     std::stringstream ss;
     std::string str;
-    uint8_t len = *data_len;
-
-    *data_len = 0;
-
+    uint8_t len = request.size();
+    auto hostId = findHost(ctx->hostIdx);
+    if (!hostId)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Host Id received");
+        return ipmi::responseInvalidCommand();
+    }
+    std::string procInfo = KEY_Q_PROC_INFO + std::to_string(*hostId);
     /* check for requested data params */
-    if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam)
+    if (len < 5 || 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->procIndex;
-    oemData[KEY_Q_PROC_INFO][ss.str()][KEY_PROC_INDEX] = req->procIndex;
-
-    str = bytesToStr(req->data, len);
-    oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]] = str.c_str();
+    ss << std::setw(2) << std::setfill('0') << (int)procIndex;
+    oemData[procInfo][ss.str()][KEY_PROC_INDEX] = procIndex;
+    str = bytesToStr(request.data(), len);
+    oemData[procInfo][ss.str()][cpuInfoKey[paramSel]] = str.c_str();
     flushOemData();
-
-    return IPMI_CC_OK;
+    return ipmi::responseSuccess();
 }
 
 //----------------------------------------------------------------------
@@ -1480,41 +1532,40 @@
 // Byte 5 – Processor frequency in MHz (MSB)
 // Byte 6..7 – Revision
 //
-ipmi_ret_t ipmiOemQGetProcInfo(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>>
+    ipmiOemQGetProcInfo(ipmi::Context::ptr ctx, uint8_t, uint8_t, uint8_t,
+                        uint8_t procIndex, uint8_t paramSel)
 {
-    qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request);
     uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*);
-    uint8_t* res = reinterpret_cast<uint8_t*>(response);
     std::stringstream ss;
     std::string str;
-
-    *data_len = 0;
-
-    /* check for requested data params */
-    if (req->paramSel < 1 || req->paramSel >= numParam)
+    uint8_t res[MAX_BUF];
+    auto hostId = findHost(ctx->hostIdx);
+    if (!hostId)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Invalid Host Id received");
+        return ipmi::responseInvalidCommand();
+    }
+    std::string procInfo = KEY_Q_PROC_INFO + std::to_string(*hostId);
+    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->procIndex;
-
-    if (oemData[KEY_Q_PROC_INFO].find(ss.str()) ==
-        oemData[KEY_Q_PROC_INFO].end())
-        return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
-
-    if (oemData[KEY_Q_PROC_INFO][ss.str()].find(cpuInfoKey[req->paramSel]) ==
-        oemData[KEY_Q_PROC_INFO][ss.str()].end())
-        return CC_PARAM_NOT_SUPP_IN_CURR_STATE;
-
-    str = oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]];
-    *data_len = strToBytes(str, res);
-
-    return IPMI_CC_OK;
+    ss << std::setw(2) << std::setfill('0') << (int)procIndex;
+    if (oemData[procInfo].find(ss.str()) == oemData[procInfo].end())
+        return ipmi::responseCommandNotAvailable();
+    if (oemData[procInfo][ss.str()].find(cpuInfoKey[paramSel]) ==
+        oemData[procInfo][ss.str()].end())
+        return ipmi::responseCommandNotAvailable();
+    str = oemData[procInfo][ss.str()][cpuInfoKey[paramSel]];
+    int dataLen = strToBytes(str, res);
+    std::vector<uint8_t> response(&res[0], &res[dataLen]);
+    return ipmi::responseSuccess(response);
 }
 
 //----------------------------------------------------------------------
@@ -2005,12 +2056,12 @@
     ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_PPR, NULL, ipmiOemGetPpr,
                          PRIVILEGE_USER); // Get PPR
     /* FB OEM QC Commands */
-    ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_PROC_INFO, NULL,
-                         ipmiOemQSetProcInfo,
-                         PRIVILEGE_USER); // Set Proc Info
-    ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_PROC_INFO, NULL,
-                         ipmiOemQGetProcInfo,
-                         PRIVILEGE_USER); // Get Proc Info
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFour,
+                          CMD_OEM_Q_SET_PROC_INFO, ipmi::Privilege::User,
+                          ipmiOemQSetProcInfo); // Set Proc Info
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFour,
+                          CMD_OEM_Q_GET_PROC_INFO, ipmi::Privilege::User,
+                          ipmiOemQGetProcInfo); // Get Proc Info
     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFour,
                           ipmi::cmdSetQDimmInfo, ipmi::Privilege::User,
                           ipmiOemQSetDimmInfo); // Set Dimm Info
diff --git a/src/usb-dbg.cpp b/src/usb-dbg.cpp
index b886525..da3c341 100644
--- a/src/usb-dbg.cpp
+++ b/src/usb-dbg.cpp
@@ -23,6 +23,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);
+int8_t procInfo(std::string& result, size_t pos);
 
 bool isMultiHostPlatform();
 
@@ -1042,6 +1043,11 @@
             {
                 frame_info.append(info.c_str(), 1);
             }
+
+            // Processor info
+            std::string result;
+            procInfo(result, pos);
+            frame_info.append(result.c_str(), 1);
         }
 
     } // End of update frame