Add Fii-oem-ipmi command

Signed-off-by: Mohaimen Alsamarai <mohaimen.alsamarai@fii-na.com>
Change-Id: I6026b28564ad9c689347aac19d41234c150ebb67
diff --git a/src/bioscommands.cpp b/src/bioscommands.cpp
new file mode 100644
index 0000000..71fc2ae
--- /dev/null
+++ b/src/bioscommands.cpp
@@ -0,0 +1,110 @@
+/********************************************************************************
+*                       HON HAI Precision IND.Co., LTD.                         *
+*            Personal Computer & Enterprise Product Business Group              *
+*                      Enterprise Product Business Gro:qup                      *
+*                                                                               *
+*     Copyright (c) 2010 by FOXCONN/CESBG/CABG/SRD. All rights reserved.        *
+*     All data and information contained in this document is confidential       *
+*     and proprietary information of FOXCONN/CESBG/CABG/SRD and all rights      *
+*     are reserved. By accepting this material the recipient agrees that        *
+*     the information contained therein is held in confidence and in trust      *
+*     and will not be used, copied, reproduced in whole or in part, nor its     *
+*     contents revealed in any manner to others without the express written     *
+*     permission of FOXCONN/CESBG/CABG/SRD.                                     *
+*                                                                               *
+********************************************************************************/
+
+#include <common.hpp>
+#include <bioscommands.hpp>
+
+namespace ipmi
+{
+    static void registerBIOSFunctions() __attribute__((constructor));
+
+    ipmi::RspType<std::vector<uint8_t>> FiiBIOSBootCount(boost::asio::yield_context yield, std::vector<uint8_t> reqParams)
+    {
+        bool op;
+        std::vector<uint8_t> boot_count;
+        uint32_t counter = 0, ret;
+
+        if (reqParams.empty())
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(" Fii bios cmd : command format error.");
+
+            return ipmi::responseReqDataLenInvalid();
+        }
+
+        op = reqParams[0] & 0b11;
+        // check the boot count file exist or not
+        std::fstream fptr(BOOT_COUNT_FILE);
+
+        if (!fptr.is_open())
+        {
+            std::cerr << " Fii bios cmd : file didn't exist and try to create one\n";
+            ret = system("mkdir -p /etc/conf");
+            std::ofstream outfile (BOOT_COUNT_FILE);
+            outfile << "0" << std::endl;
+            outfile.close();
+            boot_count.push_back(static_cast<uint8_t>(counter));
+            boot_count.push_back(static_cast<uint8_t>(counter >> 8));
+            boot_count.push_back(static_cast<uint8_t>(counter >> 16));
+            boot_count.push_back(static_cast<uint8_t>(counter >> 24));
+        }
+        else
+        {
+            std::string str;
+            while (std::getline(fptr, str))
+            {
+                //boot_count.push_back(static_cast<uint8_t>(std::stoul(str)));
+                counter = (std::stoul(str));
+                //std::cerr << " Fii bios cmd : " << counter << std::endl;
+            }
+            boot_count.push_back(static_cast<uint8_t>(counter));
+            boot_count.push_back(static_cast<uint8_t>(counter >> 8));
+            boot_count.push_back(static_cast<uint8_t>(counter >> 16));
+            boot_count.push_back(static_cast<uint8_t>(counter >> 24));
+            fptr.close();
+        }
+        if (op == OP_CODE_READ)
+        {
+            return ipmi::responseSuccess(boot_count);
+        }
+        else if (op == OP_CODE_WRITE)
+        {
+            uint32_t value = 0;
+            if (reqParams.size() == 1)
+            {
+                value = boot_count[0] + (boot_count[1] << 8) + (boot_count[2] << 16) + (boot_count[3] << 24);
+                value += 1;
+                boot_count.clear();
+                boot_count.push_back(static_cast<uint8_t>(value));
+                boot_count.push_back(static_cast<uint8_t>(value >> 8));
+                boot_count.push_back(static_cast<uint8_t>(value >> 16));
+                boot_count.push_back(static_cast<uint8_t>(value >> 24));
+            }
+            else if (reqParams.size() == FII_CMD_BIOS_BOOT_COUNT_LEN)
+            {
+                value = reqParams[1] + + (reqParams[2] << 8) + (reqParams[3] << 16) + (reqParams[4] << 24);
+                boot_count.clear();
+                boot_count.insert(boot_count.begin(), reqParams.begin()+1, reqParams.end());
+            }
+            std::ofstream fptr_w(BOOT_COUNT_FILE, std::ios::out | std::ios::trunc);
+            fptr_w << value << std::endl;
+            fptr_w.close();
+        }
+        else
+        {
+            return ipmi::responseInvalidCommand();
+        }
+        return ipmi::responseSuccess(boot_count);
+    }
+
+    void registerBIOSFunctions()
+    {
+        std::fprintf(stderr, "Registering OEM:[0x34], Cmd:[%#04X] for Fii BIOS OEM Commands\n", FII_CMD_BIOS_BOOT_COUNT);
+        ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnOemThree, FII_CMD_BIOS_BOOT_COUNT, ipmi::Privilege::User,
+                FiiBIOSBootCount);
+
+        return;
+    }
+}
diff --git a/src/systemcommands.cpp b/src/systemcommands.cpp
new file mode 100644
index 0000000..f0d5887
--- /dev/null
+++ b/src/systemcommands.cpp
@@ -0,0 +1,70 @@
+/********************************************************************************
+*                       HON HAI Precision IND.Co., LTD.                         *
+*            Personal Computer & Enterprise Product Business Group              *
+*                      Enterprise Product Business Gro:qup                      *
+*                                                                               *
+*     Copyright (c) 2010 by FOXCONN/CESBG/CABG/SRD. All rights reserved.        *
+*     All data and information contained in this document is confidential       *
+*     and proprietary information of FOXCONN/CESBG/CABG/SRD and all rights      *
+*     are reserved. By accepting this material the recipient agrees that        *
+*     the information contained therein is held in confidence and in trust      *
+*     and will not be used, copied, reproduced in whole or in part, nor its     *
+*     contents revealed in any manner to others without the express written     *
+*     permission of FOXCONN/CESBG/CABG/SRD.                                     *
+*                                                                               *
+********************************************************************************/
+
+#include <common.hpp>
+#include <systemcommands.hpp>
+
+#include <stdio.h>
+
+namespace ipmi
+    {
+    static void registerSystemFunctions() __attribute__((constructor));
+
+    ipmi::RspType<std::vector<uint8_t>> FiiSysPCIeInfo(boost::asio::yield_context yield)
+    {
+        std::vector<uint8_t> rsp;
+        char buffer[128], *token;
+        uint32_t value;
+        FILE *pipe = popen(PCIEINFO_COMMAND, "r");
+
+        // Read pcie bifurcation information
+        // it return two bytes, 1st byte bifurcation, 2nd byte present pin
+        if (!pipe) throw std::runtime_error("popen() failed !!!");
+        while (fgets(buffer, sizeof(buffer), pipe) != NULL)
+        {
+            std::cerr << " Command : " << buffer << std::endl;
+        }
+        pclose(pipe);
+
+        token = std::strtok(buffer, " ");
+        if (token == NULL)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Fii system cmd : Error geting PCIe Info came back null");
+            ipmi::responseUnspecifiedError();
+        }
+        token = std::strtok(NULL, " ");
+        while (token != NULL)
+        {
+            //std::cerr << " Command token: " << token << std::endl;
+            value = std::stoul(token, nullptr, 16);
+            //std::cerr << " Command value: " << value << ":" << std::hex << value << std::endl;
+            rsp.push_back(static_cast<uint8_t>(value & 0xFF));
+            token = std::strtok(NULL, " ");
+        }
+
+        return ipmi::responseSuccess(rsp);
+    }
+
+    void registerSystemFunctions()
+    {
+        std::fprintf(stderr, "Registering OEM:[0x34], Cmd:[%#04X] for Fii System OEM Commands\n", FII_CMD_SYS_PCIE_INFO);
+        ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnOemThree, FII_CMD_SYS_PCIE_INFO, ipmi::Privilege::User,
+                FiiSysPCIeInfo);
+
+        return;
+    }
+}