IPMI OEM Commands for OOB bios config

Four IPMI OEM commands are defined and implemented for the
communication beteween BIOS and BMC.
cmdSetBIOSCap = 0xD3;
cmdGetBIOSCap = 0xD4;
cmdSetPayload = 0xD5;
cmdGetPayload = 0xD6;
cmdSetPasswordHashInfo = 0xD7;
cmdGetStoredPasswordHash = 0xD8;

Added the OTA Payload Type

Tested:
1. ipmitool is working well for these 6 commands
2. passed unit test w/ bios and bios.xml is generated successfully

Change-Id: Ic318c18ca6d59c3ad6e10df9ffb2b22a38a55ddf
Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
Signed-off-by: Suryakanth Sekar <suryakanth.sekar@linux.intel.com>
diff --git a/src/biosconfigcommands.cpp b/src/biosconfigcommands.cpp
new file mode 100644
index 0000000..1c6d060
--- /dev/null
+++ b/src/biosconfigcommands.cpp
@@ -0,0 +1,902 @@
+/*
+// Copyright (c) 2020 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <openssl/sha.h>
+#include <tinyxml2.h>
+
+#include <biosconfigcommands.hpp>
+#include <boost/crc.hpp>
+#include <boost/process/child.hpp>
+#include <boost/process/io.hpp>
+#include <ipmid/api.hpp>
+#include <ipmid/message.hpp>
+#include <ipmid/message/types.hpp>
+#include <ipmid/types.hpp>
+#include <ipmid/utils.hpp>
+#include <nlohmann/json.hpp>
+#include <oemcommands.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/message/types.hpp>
+
+#include <filesystem>
+
+namespace ipmi
+{
+static void registerBIOSConfigFunctions() __attribute__((constructor));
+
+// Define BIOS config related Completion Code
+using Cc = uint8_t;
+static constexpr Cc ipmiCCPayloadPayloadPacketMissed = 0x80;
+static constexpr Cc ipmiCCBIOSPasswordInitNotDone = 0x80;
+static constexpr Cc ipmiCCPayloadChecksumFailed = 0x81;
+static constexpr Cc ipmiCCNotSupportedInCurrentState = 0x82;
+static constexpr Cc ipmiCCPayloadPayloadInComplete = 0x83;
+static constexpr Cc ipmiCCBIOSCapabilityInitNotDone = 0x85;
+static constexpr Cc ipmiCCPayloadLengthIllegal = 0x85;
+
+static constexpr uint8_t userPasswordChanged = (1 << 5);
+static constexpr uint8_t adminPasswordChanged = (1 << 4);
+
+static constexpr const char* biosConfigFolder = "/var/oob";
+static constexpr const char* biosConfigNVPath = "/var/oob/nvoobdata.dat";
+static constexpr const uint8_t algoSHA384 = 2;
+static constexpr const uint8_t biosCapOffsetBit = 0x3;
+static constexpr uint16_t maxGetPayloadDataSize = 4096;
+static constexpr const char* biosXMLFilePath = "/var/oob/bios.xml";
+static constexpr const char* biosXMLFilePath1 = "/var/oob/tempbios.xml";
+
+static constexpr const char* biosConfigBaseMgrPath =
+    "/xyz/openbmc_project/bios_config/manager";
+static constexpr const char* biosConfigIntf =
+    "xyz.openbmc_project.BIOSConfig.Manager";
+static constexpr const char* resetBIOSSettingsProp = "ResetBIOSSettings";
+/*baseBIOSTable
+map{attributeName,struct{attributeType,readonlyStatus,displayname,
+              description,menuPath,current,default,
+              array{struct{optionstring,optionvalue}}}}
+*/
+std::map<std::string,
+         std::tuple<std::string, bool, std::string, std::string, std::string,
+                    std::variant<int64_t, std::string>,
+                    std::variant<int64_t, std::string>,
+                    std::map<std::string, std::variant<int64_t, std::string>>>>
+    AttributesData;
+
+NVOOBdata gNVOOBdata;
+
+enum class PTState : uint8_t
+{
+    StartTransfer = 0,
+    InProgress = 1,
+    EndTransfer = 2,
+    UserAbort = 3
+};
+enum class PStatus : uint8_t
+{
+    Unknown = 0,
+    Valid = 1,
+    Corrupted = 2
+};
+enum class PType : uint8_t
+{
+    IntelXMLType0 = 0,
+    IntelXMLType1 = 1,
+    OTAPayload = 5,
+};
+
+//
+// GetPayload Payload status enumeration
+//
+enum class GetPayloadParameter : uint8_t
+{
+    GetPayloadInfo = 0, // 0
+    GetPayloadData = 1, // 1
+    GetPayloadStatus = 2
+};
+
+/** @brief implement to set the BaseBIOSTable property
+ *  @returns status
+ */
+static int sendAllAttributes(ipmi::Context::ptr ctx)
+{
+    boost::system::error_code ec;
+    std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
+    std::string service =
+        getService(*dbus, biosConfigIntf, biosConfigBaseMgrPath);
+    ec.clear();
+    ctx->bus->yield_method_call<>(
+        ctx->yield, ec, service, biosConfigBaseMgrPath,
+        "org.freedesktop.DBus.Properties", "Set", biosConfigIntf,
+        "BaseBIOSTable", AttributesData);
+    if (ec)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Failed to sendAllAttributes");
+        return -1;
+    }
+    return 0;
+}
+
+/** @brief implement to flush the updated data in nv space
+ *  @returns status
+ */
+static uint8_t flushNVOOBdata()
+{
+    std::ofstream outFile(biosConfigNVPath, std::ios::binary | std::ios::app);
+    if (outFile.good())
+    {
+        outFile.seekp(std::ios_base::beg);
+        const char* writedata = reinterpret_cast<const char*>(&gNVOOBdata);
+        outFile.write(writedata, sizeof(struct NVOOBdata));
+        outFile.close();
+    }
+    return 0;
+}
+
+/** @brief implement to get the System State
+ *  @returns status
+ */
+
+static int getSystemOSState(std::string& OsStatus)
+{
+
+    try
+    {
+        std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
+        Value variant =
+            getDbusProperty(*dbus, "xyz.openbmc_project.State.OperatingSystem",
+                            "/xyz/openbmc_project/state/os",
+                            "xyz.openbmc_project.State.OperatingSystem.Status",
+                            "OperatingSystemState");
+        OsStatus = std::get<std::string>(variant);
+        return ipmi::ccSuccess;
+    }
+    catch (const std::exception& e)
+    {
+        return ipmi::ccUnspecifiedError;
+    }
+}
+
+/** @brief implement to get the Rest BIOS property
+ *  @returns status
+ */
+static int getResetBIOSSettings(uint8_t& ResetFlag)
+{
+
+    try
+    {
+        std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
+        std::string service =
+            getService(*dbus, biosConfigIntf, biosConfigBaseMgrPath);
+        Value variant = getDbusProperty(*dbus, service, biosConfigBaseMgrPath,
+                                        biosConfigIntf, resetBIOSSettingsProp);
+        ResetFlag = static_cast<uint8_t>(std::get<std::uint8_t>(variant));
+        return ipmi::ccSuccess;
+    }
+    catch (const std::exception& e)
+    {
+        return ipmi::ccUnspecifiedError;
+    }
+}
+
+/** @brief implement generate naive- dbus from XML file
+ *  @returns status
+ */
+static int generateAttributesData()
+{
+    // Open the bios.xml and parse it
+    // Extract the needed data and store it in AttributesData variable
+    // Close the bios.xml
+    phosphor::logging::log<phosphor::logging::level::ERR>(
+        "generateAttributesData");
+    tinyxml2::XMLDocument xmlDoc;
+
+    xmlDoc.LoadFile(biosXMLFilePath);
+    tinyxml2::XMLNode* pRoot = xmlDoc.FirstChild();
+    if (pRoot == nullptr)
+    {
+        return 0;
+    }
+    tinyxml2::XMLElement* pElement = pRoot->FirstChildElement("biosknobs");
+    if (pElement == nullptr)
+    {
+        return 0;
+    }
+    tinyxml2::XMLElement* pKnobsElement = pElement->FirstChildElement("knob");
+
+    while (pKnobsElement != nullptr)
+    {
+        bool readOnlyStatus = false;
+        std::string attrType =
+            "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.String";
+        std::string name, curvalue, dname, menupath, defaultvalue, description;
+        name = pKnobsElement->Attribute("name")
+                   ? pKnobsElement->Attribute("name")
+                   : "";
+        curvalue = pKnobsElement->Attribute("CurrentVal")
+                       ? pKnobsElement->Attribute("CurrentVal")
+                       : "";
+        dname = pKnobsElement->Attribute("prompt")
+                    ? pKnobsElement->Attribute("prompt")
+                    : "";
+        menupath = pKnobsElement->Attribute("SetupPgPtr")
+                       ? pKnobsElement->Attribute("SetupPgPtr")
+                       : "";
+        defaultvalue = pKnobsElement->Attribute("default")
+                           ? pKnobsElement->Attribute("default")
+                           : "";
+        description = pKnobsElement->Attribute("description")
+                          ? pKnobsElement->Attribute("description")
+                          : "";
+        phosphor::logging::log<phosphor::logging::level::INFO>(name.c_str());
+        if (!name.empty() && !curvalue.empty() && !dname.empty() &&
+            !menupath.empty() && !defaultvalue.empty())
+        {
+            std::string rootPath = "./" + std::string(menupath);
+
+            std::map<std::string, std::variant<int64_t, std::string>> optionMap;
+            tinyxml2::XMLElement* pOptionsElement =
+                pKnobsElement->FirstChildElement("options");
+            nlohmann::json optionsArray = nlohmann::json::array();
+            if (pOptionsElement != nullptr)
+            {
+                tinyxml2::XMLElement* pOptionElement =
+                    pOptionsElement->FirstChildElement("option");
+                while (pOptionElement != nullptr)
+                {
+                    const std::string text = pOptionElement->Attribute("text");
+                    const std::string attrValue =
+                        pOptionElement->Attribute("value");
+                    if (!text.empty() && !attrValue.empty())
+                    {
+
+                        optionMap.emplace(std::make_pair(std::move(text),
+                                                         std::move(attrValue)));
+                    }
+                    pOptionElement =
+                        pOptionElement->NextSiblingElement("option");
+                }
+            }
+
+            AttributesData.emplace(std::make_pair(
+                name,
+                std::make_tuple(attrType, readOnlyStatus, dname, description,
+                                rootPath, curvalue, defaultvalue, optionMap)));
+        }
+        pKnobsElement = pKnobsElement->NextSiblingElement("knob");
+    }
+
+    return 0;
+}
+
+/** @brief implement executing the linux command to uncompress and generate the
+ * xmlfile
+ *  @param[in] linux command
+ *  @returns status
+ */
+template <typename... ArgTypes>
+static int generateBIOSXMLFile(const char* path, ArgTypes&&... tArgs)
+{
+
+    boost::process::child execProg(path, const_cast<char*>(tArgs)...,
+                                   boost::process::std_out > biosXMLFilePath);
+    execProg.wait();
+    return execProg.exit_code();
+}
+
+/** @brief implements to clean up the temp/ existing payload file
+ **/
+static void cleanUpPayloadFile(uint8_t& payloadType)
+{
+    // Clear the payload Information
+    std::string FilePath = "/var/oob/temp" + std::to_string(payloadType);
+    unlink(FilePath.c_str());
+    FilePath = "/var/oob/Payload" + std::to_string(payloadType);
+    unlink(FilePath.c_str());
+    if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType0))
+    {
+        unlink("/var/oob/Payload1");
+        gNVOOBdata.payloadInfo[static_cast<uint8_t>(ipmi::PType::IntelXMLType1)]
+            .payloadStatus = static_cast<uint8_t>(ipmi::PStatus::Unknown);
+    }
+}
+
+/** @brief implements to create the oob folders and nv space
+ **/
+static Cc InitNVOOBdata()
+{
+    FILE* fptr;
+    uint16_t size;
+
+    if (!(std::filesystem::exists(biosConfigFolder)))
+    {
+        std::filesystem::create_directory(biosConfigFolder);
+    }
+
+    std::ifstream ifs(biosConfigNVPath,
+                      std::ios::in | std::ios::binary | std::ios::ate);
+
+    if (ifs.good())
+    {
+
+        ifs.read(reinterpret_cast<char*>(&gNVOOBdata),
+                 sizeof(struct NVOOBdata));
+        ifs.close();
+        return ipmi::ccSuccess;
+    }
+    return ipmi::ccResponseError;
+}
+
+/** @brief implements check the command interface is
+ ** system interface or not
+ **  true mean System interface and false mean LAN or IPMB
+ **/
+static bool IsSystemInterface(ipmi::Context::ptr ctx)
+{
+    ChannelInfo chInfo;
+    Cc status = false;
+
+    try
+    {
+        getChannelInfo(ctx->channel, chInfo);
+    }
+    catch (sdbusplus::exception_t& e)
+    {
+        return false;
+    }
+    if (chInfo.mediumType !=
+        static_cast<uint8_t>(EChannelMediumType::systemInterface))
+    {
+        return false;
+    }
+    return true;
+}
+
+ipmi::RspType<> ipmiOEMSetBIOSCap(ipmi::Context::ptr ctx,
+                                  uint8_t BIOSCapabilties, uint8_t reserved1,
+                                  uint8_t reserved2, uint8_t reserved3)
+{
+    std::string OSState;
+    getSystemOSState(OSState);
+
+    if (OSState != "OperatingState" && IsSystemInterface(ctx))
+    {
+        if (reserved1 != 0 || reserved2 != 0 || reserved3 != 0)
+        {
+            return ipmi::responseInvalidFieldRequest();
+        }
+
+        gNVOOBdata.mBIOSCapabilities.OOBCapability = BIOSCapabilties;
+        gNVOOBdata.mIsBIOSCapInitDone = true;
+
+        flushNVOOBdata();
+        return ipmi::responseSuccess();
+    }
+    else
+    {
+
+        return ipmi::response(ipmiCCNotSupportedInCurrentState);
+    }
+}
+
+ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t>
+    ipmiOEMGetBIOSCap(ipmi::Context::ptr ctx)
+{
+    if (gNVOOBdata.mIsBIOSCapInitDone)
+    {
+        return ipmi::responseSuccess(gNVOOBdata.mBIOSCapabilities.OOBCapability,
+                                     0, 0, 0);
+    }
+    else
+    {
+        return ipmi::response(ipmiCCBIOSCapabilityInitNotDone);
+    }
+}
+
+ipmi::RspType<uint32_t> ipmiOEMSetPayload(ipmi::Context::ptr ctx,
+                                          uint8_t paramSel, uint8_t payloadType,
+                                          std::vector<uint8_t> payload)
+{
+    uint8_t biosCapOffsetBit = 2; // BIT:1 0-OOB BIOS config not supported
+                                  //      1-OOB BIOS config is supported
+
+    if (!(gNVOOBdata.mBIOSCapabilities.OOBCapability & (biosCapOffsetBit)))
+    {
+        return ipmi::response(ipmiCCBIOSCapabilityInitNotDone);
+    }
+    // Validate the Payload Type
+    if (payloadType > maxPayloadSupported)
+    {
+        return ipmi::responseInvalidFieldRequest();
+    }
+
+    // We should support this Payload type 0 command only in KCS Interface
+    if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType0))
+    {
+        std::string OSState;
+
+        getSystemOSState(OSState);
+        if (!IsSystemInterface(ctx) || OSState == "OperatingState")
+        {
+            return ipmi::responseCommandNotAvailable();
+        }
+    }
+
+    switch (static_cast<PTState>(paramSel))
+    {
+        case ipmi::PTState::StartTransfer:
+        {
+            PayloadStartTransfer* pPayloadStartTransfer =
+                reinterpret_cast<PayloadStartTransfer*>(payload.data());
+            if (payload.size() < sizeof(PayloadStartTransfer))
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "ipmiOEMSetPayload: BIOS Config Payload size is not "
+                    "correct");
+                return ipmi::responseReqDataLenInvalid();
+            }
+            cleanUpPayloadFile(payloadType);
+
+            gNVOOBdata.payloadInfo[payloadType].payloadReservationID = rand();
+            gNVOOBdata.payloadInfo[payloadType].payloadTotalChecksum =
+                pPayloadStartTransfer->payloadTotalChecksum;
+            gNVOOBdata.payloadInfo[payloadType].payloadTotalSize =
+                pPayloadStartTransfer->payloadTotalSize;
+            gNVOOBdata.payloadInfo[payloadType].payloadVersion =
+                pPayloadStartTransfer->payloadVersion;
+            gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten = 0;
+            gNVOOBdata.payloadInfo[payloadType].payloadStatus =
+                static_cast<uint8_t>(ipmi::PStatus::Unknown);
+
+            return ipmi::responseSuccess(
+                gNVOOBdata.payloadInfo[payloadType].payloadReservationID);
+        }
+        break;
+
+        case ipmi::PTState::InProgress:
+        {
+            PayloadInProgress* pPayloadInProgress =
+                reinterpret_cast<PayloadInProgress*>(payload.data());
+            PayloadInfo payloadInfo = gNVOOBdata.payloadInfo[payloadType];
+
+            if (payload.size() < sizeof(PayloadInProgress))
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "BIOS Config Payload size is not correct");
+                return ipmi::responseReqDataLenInvalid();
+            }
+
+            if (pPayloadInProgress->payloadReservationID !=
+                payloadInfo.payloadReservationID)
+            {
+                return ipmi::responseInvalidReservationId();
+            }
+            payloadInfo.payloadCurrentSize =
+                pPayloadInProgress->payloadCurrentSize;
+            // Need to verify the current Payload Checksum
+            const uint8_t* data =
+                reinterpret_cast<const uint8_t*>(payload.data());
+            // we have to remove the current size, current offset, current
+            // length,checksum bytes , reservation bytes
+            boost::crc_32_type calcChecksum;
+            calcChecksum.process_bytes(data + 16, payload.size() - 16);
+            if (calcChecksum.checksum() !=
+                pPayloadInProgress->payloadCurrentChecksum)
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "ipmiOEMSetPayload: Payload Checksum Failed");
+                return ipmi::response(ipmiCCPayloadChecksumFailed);
+            }
+            // store the data in temp file
+            std::string FilePath =
+                "/var/oob/temp" + std::to_string(payloadType);
+
+            std::ofstream outFile(FilePath, std::ios::binary | std::ios::app);
+            outFile.seekp(pPayloadInProgress->payloadOffset);
+            // we have to remove the current size, current offset, current
+            // length,checksum bytes , reservation bytes
+
+            const char* writedata =
+                reinterpret_cast<const char*>(payload.data());
+            outFile.write(writedata + 16, payload.size() - 16);
+            outFile.close();
+
+            gNVOOBdata.payloadInfo[payloadType].payloadStatus =
+                static_cast<uint8_t>(ipmi::PStatus::Unknown);
+            gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten +=
+                payloadInfo.payloadCurrentSize;
+            return ipmi::responseSuccess(payloadInfo.payloadCurrentSize);
+        }
+        break;
+        case ipmi::PTState::EndTransfer:
+        {
+            PayloadEndTransfer* pPayloadEndTransfer =
+                reinterpret_cast<PayloadEndTransfer*>(payload.data());
+            PayloadInfo payloadInfo = gNVOOBdata.payloadInfo[payloadType];
+            if (pPayloadEndTransfer->payloadReservationID !=
+                payloadInfo.payloadReservationID)
+            {
+                return ipmi::responseInvalidReservationId();
+            }
+            gNVOOBdata.payloadInfo[payloadType].payloadStatus =
+                static_cast<uint8_t>(ipmi::PStatus::Unknown);
+
+            if (gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten !=
+                gNVOOBdata.payloadInfo[payloadType].payloadTotalSize)
+            {
+
+                return ipmi::response(ipmiCCPayloadPayloadInComplete);
+            }
+            std::string tempFilePath =
+                "/var/oob/temp" + std::to_string(payloadType);
+            std::string PayloadFilePath =
+                "/var/oob/Payload" + std::to_string(payloadType);
+            auto renamestatus =
+                std::rename(tempFilePath.c_str(), PayloadFilePath.c_str());
+            if (renamestatus)
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "ipmiOEMSetPayload: Renaming Payload file - failed");
+            }
+
+            gNVOOBdata.payloadInfo[payloadType].payloadFilePath =
+                PayloadFilePath;
+            if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType0))
+            {
+                // Unzip the Intel format XML file type 0
+                auto response = generateBIOSXMLFile("/usr/bin/lzcat", "-d",
+                                                    PayloadFilePath.c_str());
+                if (response)
+                {
+
+                    phosphor::logging::log<phosphor::logging::level::ERR>(
+                        "ipmiOEMSetPayload: generateBIOSXMLFile - failed");
+                    gNVOOBdata.payloadInfo[payloadType].payloadStatus =
+                        static_cast<uint8_t>(ipmi::PStatus::Corrupted);
+                    return ipmi::response(ipmiCCPayloadPayloadPacketMissed);
+                }
+            }
+            gNVOOBdata.payloadInfo[payloadType].payloadStatus =
+                static_cast<uint8_t>(ipmi::PStatus::Valid);
+
+            struct stat filestat;
+
+            /* Get entry's information. */
+            if (!stat(PayloadFilePath.c_str(), &filestat))
+            {
+                gNVOOBdata.payloadInfo[payloadType].payloadTimeStamp =
+                    filestat.st_mtime;
+                gNVOOBdata.payloadInfo[payloadType].payloadTotalSize =
+                    filestat.st_size;
+                gNVOOBdata.payloadInfo[payloadType].payloadFilePath =
+                    PayloadFilePath;
+            }
+            else
+            {
+                return ipmi::responseResponseError();
+            }
+
+            phosphor::logging::log<phosphor::logging::level::INFO>(
+                " ipmiOEMSetPayload : Convert XML into native-dbus DONE");
+            generateAttributesData();
+
+            phosphor::logging::log<phosphor::logging::level::INFO>(
+                " ipmiOEMSetPayload : BaseBIOSTable Property  is set");
+            sendAllAttributes(ctx);
+
+            flushNVOOBdata();
+            return ipmi::responseSuccess(
+                gNVOOBdata.payloadInfo[payloadType].actualTotalPayloadWritten);
+        }
+        break;
+        case ipmi::PTState::UserAbort:
+        {
+            PayloadEndTransfer* pPayloadEndTransfer =
+                reinterpret_cast<PayloadEndTransfer*>(payload.data());
+            PayloadInfo payloadInfo = gNVOOBdata.payloadInfo[payloadType];
+            if (pPayloadEndTransfer->payloadReservationID !=
+                payloadInfo.payloadReservationID)
+            {
+                return ipmi::responseInvalidReservationId();
+            }
+            gNVOOBdata.payloadInfo[payloadType].payloadReservationID = 0;
+            gNVOOBdata.payloadInfo[payloadType].payloadType = 0;
+            gNVOOBdata.payloadInfo[payloadType].payloadTotalSize = 0;
+            // Delete the temp file
+            std::string tempFilePath =
+                "/var/oob/temp" + std::to_string(payloadType);
+            unlink(tempFilePath.c_str());
+            flushNVOOBdata();
+            return ipmi::responseSuccess();
+        }
+        break;
+        default:
+            return ipmi::responseInvalidFieldRequest();
+    }
+    return ipmi::responseResponseError();
+}
+
+ipmi::RspType<message::Payload>
+    ipmiOEMGetPayload(ipmi::Context::ptr ctx, uint8_t paramSel,
+                      uint8_t payloadType, ipmi::message::Payload& payload)
+{
+    //      1-OOB BIOS config is supported
+    message::Payload retValue;
+
+    if (!(gNVOOBdata.mBIOSCapabilities.OOBCapability & (biosCapOffsetBit)))
+    {
+        return ipmi::response(ipmiCCBIOSCapabilityInitNotDone);
+    }
+    // Validate the Payload Type
+    if (payloadType > maxPayloadSupported)
+    {
+        return ipmi::responseInvalidFieldRequest();
+    }
+
+    struct PayloadInfo res = gNVOOBdata.payloadInfo[payloadType];
+
+    switch (static_cast<GetPayloadParameter>(paramSel))
+    {
+        case ipmi::GetPayloadParameter::GetPayloadInfo:
+        {
+            retValue.pack(res.payloadVersion);
+            retValue.pack(res.payloadType);
+            retValue.pack(res.payloadTotalSize);
+            retValue.pack(res.payloadTotalChecksum);
+            retValue.pack(res.payloadflag);
+            retValue.pack(res.payloadStatus);
+            retValue.pack(res.payloadTimeStamp);
+
+            return ipmi::responseSuccess(std::move(retValue));
+        }
+
+        break;
+        case ipmi::GetPayloadParameter::GetPayloadData:
+        {
+            if (res.payloadStatus ==
+                (static_cast<uint8_t>(ipmi::PStatus::Valid)))
+            {
+                std::vector<uint32_t> reqData;
+                if (payload.unpack(reqData) || !payload.fullyUnpacked())
+                {
+                    return ipmi::responseReqDataLenInvalid();
+                }
+                uint32_t offset = reqData.at(0);
+                uint32_t length = reqData.at(1);
+
+                std::ifstream ifs(res.payloadFilePath, std::ios::in |
+                                                           std::ios::binary |
+                                                           std::ios::ate);
+                std::ifstream::pos_type fileSize = ifs.tellg();
+                // Total file data within given offset
+                if (fileSize < static_cast<uint64_t>(offset))
+                {
+                    ifs.close();
+                    return ipmi::responseInvalidFieldRequest();
+                }
+
+                ifs.seekg(offset, std::ios::beg);
+                std::array<uint8_t, maxGetPayloadDataSize> Buffer;
+                ifs.read(reinterpret_cast<char*>(Buffer.data()), length);
+                uint32_t readCount = ifs.gcount();
+                ifs.close();
+
+                boost::crc_32_type calcChecksum;
+                calcChecksum.process_bytes(
+                    reinterpret_cast<char*>(Buffer.data()), readCount);
+                uint32_t chkSum = calcChecksum.checksum();
+                retValue.pack(payloadType);
+                retValue.pack(readCount);
+                retValue.pack(chkSum);
+
+                for (int i = 0; i < readCount; i++)
+                {
+                    retValue.pack(Buffer.at(i));
+                }
+                return ipmi::responseSuccess(std::move(retValue));
+            }
+            else
+            {
+                return ipmi::responseResponseError();
+            }
+        }
+        break;
+        case ipmi::GetPayloadParameter::GetPayloadStatus:
+        {
+            retValue.pack(gNVOOBdata.payloadInfo[payloadType].payloadStatus);
+            return ipmi::responseSuccess(std::move(retValue));
+        }
+        break;
+        default:
+            return ipmi::responseInvalidFieldRequest();
+    }
+    return ipmi::responseInvalidFieldRequest();
+}
+
+ipmi::RspType<> ipmiOEMSetBIOSHashInfo(
+    ipmi::Context::ptr ctx, std::array<uint8_t, maxSeedSize>& pwdSeed,
+    uint8_t algoInfo, std::array<uint8_t, maxHashSize>& adminPwdHash,
+    std::array<uint8_t, maxHashSize>& userPwdHash)
+{
+
+    std::string OSState;
+
+    // We should support this command only in KCS Interface
+    if (!IsSystemInterface(ctx))
+    {
+        return ipmi::responseCommandNotAvailable();
+    }
+    getSystemOSState(OSState);
+    // We should not support this command after System Booted - After Exit Boot
+    // service called
+
+    if (OSState != "OperatingState")
+    {
+
+        if (algoInfo != algoSHA384)
+        {
+            // Atpresent, we are supporting only SHA384- HASH algo in BIOS side
+            return ipmi::responseInvalidFieldRequest();
+        }
+        std::string HashFilePath = "/var/lib/bios-settings-manager/seedData";
+
+        nlohmann::json json;
+        json["Seed"] = pwdSeed;
+        json["HashAlgo"] = "SHA384";
+        json["IsAdminPwdChanged"] = false;
+        json["AdminPwdHash"] = adminPwdHash;
+        json["IsUserPwdChanged"] = false;
+        json["UserPwdHash"] = userPwdHash;
+        std::ofstream ofs(HashFilePath, std::ios::out);
+        const auto& writeData = json.dump();
+        ofs << writeData;
+        ofs.close();
+        return ipmi::responseSuccess();
+    }
+    else
+    {
+
+        return ipmi::response(ipmiCCNotSupportedInCurrentState);
+    }
+}
+
+ipmi::RspType<uint8_t, std::array<uint8_t, maxHashSize>,
+              std::array<uint8_t, maxHashSize>>
+    ipmiOEMGetBIOSHash(ipmi::Context::ptr ctx)
+{
+
+    std::string OSState;
+    nlohmann::json data = nullptr;
+
+    // We should support this command only in KCS Interface
+    if (!IsSystemInterface(ctx))
+    {
+        return ipmi::responseCommandNotAvailable();
+    }
+
+    getSystemOSState(OSState);
+    // We should not support this command after System Booted - After Exit Boot
+    // service called
+
+    if (OSState != "OperatingState")
+    {
+        std::string HashFilePath =
+            "/var/lib/bios-settings-manager/passwordData";
+
+        std::ifstream devIdFile(HashFilePath);
+        if (devIdFile.is_open())
+        {
+
+            try
+            {
+                data = nlohmann::json::parse(devIdFile, nullptr, false);
+            }
+            catch (const nlohmann::json::parse_error& e)
+            {
+                return ipmi::responseResponseError();
+            }
+
+            if (data.is_discarded())
+            {
+                return ipmi::responseResponseError();
+            }
+
+            std::array<uint8_t, maxHashSize> newAdminHash;
+            std::array<uint8_t, maxHashSize> newUserHash;
+            uint8_t flag = 0;
+            uint8_t adminPwdChangedFlag = 0;
+            uint8_t userPwdChangedFlag = 0;
+            if (!data.is_discarded())
+            {
+
+                adminPwdChangedFlag = data["IsAdminPwdChanged"];
+                newAdminHash = data["AdminPwdHash"];
+                newUserHash = data["UserPwdHash"];
+                userPwdChangedFlag = data["IsUserPwdChanged"];
+            }
+
+            // 0: BIT 4 - New Admin Password Not Present
+            // 1: BIT 4 - New Admin Password Hash Present
+            // 0: BIT 5 - New User Password Not Present
+            // 1: BIT 5 - New User Password Hash Present
+            // 0: BIT 0 - Default Setting flag is not set
+            // 1: BIT 0 - Default Setting flag is set
+            auto status = getResetBIOSSettings(flag);
+            if (status)
+            {
+                return ipmi::responseResponseError();
+            }
+            if (adminPwdChangedFlag)
+            {
+                flag |= adminPasswordChanged;
+            }
+            if (userPwdChangedFlag)
+            {
+                flag |= userPasswordChanged;
+            }
+
+            std::copy(std::begin(newAdminHash), std::end(newAdminHash),
+                      std::begin(newAdminHash));
+            std::copy(std::begin(newUserHash), std::end(newUserHash),
+                      std::begin(newUserHash));
+            return ipmi::responseSuccess(flag, newAdminHash, newUserHash);
+        }
+        else
+        {
+            return ipmi::responseResponseError();
+        }
+    }
+    else
+    {
+
+        return ipmi::response(ipmiCCNotSupportedInCurrentState);
+    }
+}
+
+static void registerBIOSConfigFunctions(void)
+{
+    phosphor::logging::log<phosphor::logging::level::INFO>(
+        "BIOSConfig module initialization");
+    InitNVOOBdata();
+
+    registerHandler(prioOemBase, intel::netFnGeneral,
+                    intel::general::cmdSetBIOSCap, Privilege::Admin,
+                    ipmiOEMSetBIOSCap);
+
+    registerHandler(prioOemBase, intel::netFnGeneral,
+                    intel::general::cmdGetBIOSCap, Privilege::User,
+                    ipmiOEMGetBIOSCap);
+    registerHandler(prioOemBase, intel::netFnGeneral,
+                    intel::general::cmdSetBIOSPwdHashInfo, Privilege::Admin,
+                    ipmiOEMSetBIOSHashInfo);
+
+    registerHandler(prioOemBase, intel::netFnGeneral,
+                    intel::general::cmdGetBIOSPwdHash, Privilege::User,
+                    ipmiOEMGetBIOSHash);
+
+    registerHandler(prioOemBase, intel::netFnGeneral,
+                    intel::general::cmdGetPayload, Privilege::User,
+                    ipmiOEMGetPayload);
+    registerHandler(prioOemBase, intel::netFnGeneral,
+                    intel::general::cmdSetPayload, Privilege::Admin,
+                    ipmiOEMSetPayload);
+
+    return;
+}
+
+} // namespace ipmi