/*
// 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 "biosxml.hpp"

#include <openssl/sha.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 <sdbusplus/bus.hpp>
#include <sdbusplus/message/types.hpp>

#include <filesystem>
#include <string_view>

namespace ipmi
{
static bool flushNVOOBdata();
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 algoSHA256 = 1;
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}}}}
*/

bios::BiosBaseTableType 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
};

namespace payload1
{

enum class AttributesType : uint8_t
{
    unknown = 0,
    string,
    integer,
    enumeration
};

using PendingAttributesType =
    std::map<std::string,
             std::tuple<std::string, std::variant<int64_t, std::string>>>;

AttributesType getAttrType(const std::string_view typeDbus)
{
    if (typeDbus == "xyz.openbmc_project.BIOSConfig.Manager."
                    "AttributeType.String")
    {
        return AttributesType::string;
    }
    else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
                         "Manager.AttributeType.Integer")
    {
        return AttributesType::integer;
    }
    else if (typeDbus == "xyz.openbmc_project.BIOSConfig."
                         "Manager.AttributeType.Enumeration")
    {
        return AttributesType::enumeration;
    }

    return AttributesType::unknown;
}

bool fillPayloadData(std::string& payloadData,
                     const std::variant<int64_t, std::string>& attributes,
                     const std::string_view key, AttributesType& attrType)
{
    payloadData += key;
    payloadData += '=';

    if (attrType == AttributesType::string ||
        attrType == AttributesType::enumeration)
    {
        if (!std::holds_alternative<std::string>(attributes))
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "fillPayloadData: No string data in attributes");
            return false;
        }
        payloadData += std::get<std::string>(attributes);
    }
    else if (attrType == AttributesType::integer)
    {
        if (!std::holds_alternative<int64_t>(attributes))
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "fillPayloadData: No int64_t data in attributes");
            return false;
        }
        payloadData += std::to_string(std::get<int64_t>(attributes));
    }
    else
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "fillPayloadData: Unsupported attribute type");
        return false;
    }

    payloadData += '\n';

    return true;
}

bool getPendingList(ipmi::Context::ptr ctx, std::string& payloadData)
{
    std::variant<PendingAttributesType> pendingAttributesData;
    boost::system::error_code ec;

    payloadData.clear();

    auto dbus = getSdBus();
    if (!dbus)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "getPendingList: getSdBus() failed");
        return false;
    }

    std::string service =
        getService(*dbus, biosConfigIntf, biosConfigBaseMgrPath);

    try
    {
        pendingAttributesData =
            dbus->yield_method_call<std::variant<PendingAttributesType>>(
                ctx->yield, ec, service,
                "/xyz/openbmc_project/bios_config/manager",
                "org.freedesktop.DBus.Properties", "Get",
                "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes");
    }
    catch (const std::exception& ex)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(ex.what());
        return false;
    }

    if (ec)
    {
        std::string err = "getPendingList: error while trying to get "
                          "PendingAttributes, error = ";
        err += ec.message();

        phosphor::logging::log<phosphor::logging::level::ERR>(err.c_str());

        return false;
    }

    const PendingAttributesType* pendingAttributes =
        std::get_if<PendingAttributesType>(&pendingAttributesData);
    if (!pendingAttributes)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "getPendingList: pendingAttributes is null");
        return false;
    }

    for (const auto& [key, attributes] : *pendingAttributes)
    {
        const std::string& itemType = std::get<0>(attributes);
        AttributesType attrType = getAttrType(itemType);

        if (!fillPayloadData(payloadData, std::get<1>(attributes), key,
                             attrType))
        {
            return false;
        }
    }

    if (payloadData.empty())
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "getPendingList: payloadData is empty");
        return false;
    }

    return true;
}
bool updatePayloadFile(std::string& payloadFilePath, std::string payloadData)
{
    std::ofstream payloadFile(payloadFilePath,
                              std::ios::out | std::ios::binary);

    payloadFile << payloadData;

    if (!payloadFile.good())
    {
        return false;
    }

    return true;
}

bool computeCheckSum(std::string& payloadFilePath,
                     boost::crc_32_type& calcChecksum)
{
    std::ifstream payloadFile(payloadFilePath.c_str(),
                              std::ios::in | std::ios::binary | std::ios::ate);

    if (!payloadFile.good())
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "computeCheckSum: Cannot open Payload1 file");
        return false;
    }

    payloadFile.seekg(0, payloadFile.end);
    int length = payloadFile.tellg();
    payloadFile.seekg(0, payloadFile.beg);

    if (maxGetPayloadDataSize < length)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "computeCheckSum: length > maxGetPayloadDataSize");
        return false;
    }

    std::unique_ptr<char[]> payloadBuffer(new char[length]);

    payloadFile.read(payloadBuffer.get(), length);
    uint32_t readCount = payloadFile.gcount();

    calcChecksum.process_bytes(payloadBuffer.get(), readCount);

    return true;
}

bool updatePayloadInfo(std::string& payloadFilePath)
{
    boost::crc_32_type calcChecksum;

    uint8_t payloadType = static_cast<uint8_t>(ipmi::PType::IntelXMLType1);
    auto& payloadInfo = gNVOOBdata.payloadInfo[payloadType];

    if (!computeCheckSum(payloadFilePath, calcChecksum))
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "updatePayloadInfo: Cannot compute checksum for Payload1 file");
        return false;
    }

    payloadInfo.payloadVersion = 0;
    payloadInfo.payloadflag = 0;
    payloadInfo.payloadReservationID = rand();

    payloadInfo.payloadType = payloadType;

    payloadInfo.payloadTotalChecksum = calcChecksum.checksum();
    payloadInfo.payloadCurrentChecksum = payloadInfo.payloadTotalChecksum;

    payloadInfo.payloadStatus = (static_cast<uint8_t>(ipmi::PStatus::Valid));

    struct stat filestat;
    /* Get entry's information. */
    if (!stat(payloadFilePath.c_str(), &filestat))
    {
        payloadInfo.payloadTimeStamp = filestat.st_mtime;
        payloadInfo.payloadTotalSize = filestat.st_size;
        payloadInfo.payloadCurrentSize = filestat.st_size;
        payloadInfo.actualTotalPayloadWritten = filestat.st_size;
    }
    else
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "updatePayloadInfo: Cannot get file status for Payload1 file");
        return false;
    }

    if (!flushNVOOBdata())
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "updatePayloadInfo: flushNVOOBdata failed");
        return false;
    }

    return true;
}

bool update(ipmi::Context::ptr ctx)
{
    std::string payloadFilePath =
        "/var/oob/Payload" +
        std::to_string(static_cast<uint8_t>(ipmi::PType::IntelXMLType1));

    std::string payloadData;

    if (!getPendingList(ctx, payloadData))
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "payload1::update : getPendingList() failed");
        return false;
    }

    if (!updatePayloadFile(payloadFilePath, payloadData))
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "payload1::update : updatePayloadFile() failed");
        return false;
    }

    if (!updatePayloadInfo(payloadFilePath))
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "payload1::update : updatePayloadInfo() failed");
        return false;
    }

    return true;
}
} // namespace payload1

/** @brief implement to set the BaseBIOSTable property
 *  @returns status
 */
static bool sendAllAttributes(std::string service)
{
    std::shared_ptr<sdbusplus::asio::connection> pSdBusPlus = getSdBus();

    if (pSdBusPlus)
    {
        try
        {
            pSdBusPlus->async_method_call(
                [](const boost::system::error_code ec) {
                    /* No more need to keep attributes data in memory */
                    attributesData.clear();

                    if (ec)
                    {
                        phosphor::logging::log<phosphor::logging::level::ERR>(
                            "sendAllAttributes error: send all attributes - "
                            "failed");
                        return;
                    }

                    phosphor::logging::log<phosphor::logging::level::INFO>(
                        "sendAllAttributes: send all attributes - done");
                },
                service, biosConfigBaseMgrPath,
                "org.freedesktop.DBus.Properties", "Set", biosConfigIntf,
                "BaseBIOSTable",
                std::variant<bios::BiosBaseTableType>(attributesData));

            return true;
        }
        catch (const std::exception& ex)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(ex.what());
        }
    }

    return false;
}

/** @brief implement to flush the updated data in nv space
 *  @returns status
 */
static bool flushNVOOBdata()
{
    std::ofstream outFile(biosConfigNVPath, std::ios::binary);

    outFile.seekp(std::ios_base::beg);
    const char* writedata = reinterpret_cast<const char*>(&gNVOOBdata);
    outFile.write(writedata, sizeof(struct NVOOBdata));

    if (!outFile.good())
    {
        return false;
    }

    return true;
}

/** @brief implement to get the System State
 *  @returns status
 */
static bool getPostCompleted()
{
    /*
     * In case of failure we treat postCompleted as true.
     * So that BIOS config commands is not accepted by BMC by mistake.
     */
    bool postCompleted = true;

    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");
        auto& value = std::get<std::string>(variant);

        // The short strings "Standby" is deprecated in favor of the
        // full enum strings. Support for the short strings will be
        // removed in the future.
        postCompleted = (value == "Standby") ||
                        (value == "xyz.openbmc_project.State.OperatingSystem."
                                  "Status.OSStatus.Standby");
    }
    catch (const std::exception& e)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "'getDbusProperty' failed to read "
            "xyz.openbmc_project.State.OperatingSystem");
    }

    return postCompleted;
}

/** @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);

        std::string_view ResetStr = std::get<std::string>(variant);
        if (ResetStr ==
            "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag.NoAction")
        {
            ResetFlag = 0;
        }
        else if (ResetStr == "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag."
                             "FactoryDefaults")
        {
            ResetFlag = 1;
        }
        else if (ResetStr == "xyz.openbmc_project.BIOSConfig.Manager.ResetFlag."
                             "FailSafeDefaults")
        {
            ResetFlag = 2;
        }
        else
        {
            return ipmi::ccUnspecifiedError;
        }

        return ipmi::ccSuccess;
    }
    catch (const std::exception& e)
    {
        return ipmi::ccUnspecifiedError;
    }
}

/** @brief Get attributes data (bios base table) from bios.xml
 */
static bool generateAttributesData()
{
    try
    {
        bios::Xml biosxml(biosXMLFilePath);

        if (!biosxml.doDepexCompute())
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "'depex' compute failed");
        }

        if (!biosxml.getBaseTable(attributesData))
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Failed to get bios base table");
        }
    }
    catch (const std::exception& ex)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(ex.what());
        return false;
    }

    return true;
}

/** @brief Generate attributes data from bios.xml
 * and send attributes data (bios base table) to dbus using set method.
 */
static void generateAndSendAttributesData(std::string service,
                                          uint8_t payloadType)
{
    if (!generateAttributesData())
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "generateAndSendAttributesData: generateAttributesData - failed");
        gNVOOBdata.payloadInfo[payloadType].payloadStatus =
            static_cast<uint8_t>(ipmi::PStatus::Corrupted);
        return;
    }

    phosphor::logging::log<phosphor::logging::level::INFO>(
        "generateAndSendAttributesData : generateAttributesData is done");

    if (!sendAllAttributes(service))
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "generateAndSendAttributesData: sendAllAttributes - failed");
        gNVOOBdata.payloadInfo[payloadType].payloadStatus =
            static_cast<uint8_t>(ipmi::PStatus::Corrupted);
        return;
    }

    phosphor::logging::log<phosphor::logging::level::INFO>(
        "generateAndSendAttributesData : sendAllAttributes is done");
    gNVOOBdata.payloadInfo[payloadType].payloadStatus =
        static_cast<uint8_t>(ipmi::PStatus::Valid);
}

/** @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);

    if (ifs.good())
    {

        ifs.seekg(std::ios_base::beg);
        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 (const 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)
{
    if (!getPostCompleted() && 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))
    {
        if (!IsSystemInterface(ctx) || getPostCompleted())
        {
            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);
            gNVOOBdata.payloadInfo[payloadType].payloadType = payloadType;

            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)
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "BIOS Config Payload reservation ID is not correct");
                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");
            }

            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);
                }
                phosphor::logging::log<phosphor::logging::level::INFO>(
                    " ipmiOEMSetPayload : Convert XML into native-dbus DONE");

                /* So that we don't block the call */
                auto io = getIoContext();
                auto dbus = getSdBus();
                if (io && dbus)
                {
                    std::string service = getService(*dbus, biosConfigIntf,
                                                     biosConfigBaseMgrPath);

                    boost::asio::post(*io, [service, payloadType] {
                        generateAndSendAttributesData(service, payloadType);
                    });
                }
                else
                {
                    phosphor::logging::log<phosphor::logging::level::INFO>(
                        "ipmiOEMSetPayload: Unable to get io context or sdbus");
                    return ipmi::responseResponseError();
                }
            }

            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;
            }
            else
            {
                return ipmi::responseResponseError();
            }
            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();
    }

    if (payloadType == static_cast<uint8_t>(ipmi::PType::IntelXMLType1))
    {
        if (!payload1::update(ctx))
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "ipmiOEMGetPayload: unable to update NVOOBdata for payloadType "
                "= IntelXMLType1");
            return ipmi::response(ipmi::ccUnspecifiedError);
        }
    }

    struct PayloadInfo res = gNVOOBdata.payloadInfo[payloadType];

    switch (static_cast<GetPayloadParameter>(paramSel))
    {
        case ipmi::GetPayloadParameter::GetPayloadInfo:
        {
            std::string payloadFilePath =
                "/var/oob/Payload" + std::to_string(payloadType);

            std::ifstream ifs(payloadFilePath,
                              std::ios::in | std::ios::binary | std::ios::ate);

            if (!ifs.good())
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "ipmiOEMGetPayload: Payload File Error");
                // File does not exist code here
                return ipmi::response(ipmi::ccUnspecifiedError);
            }

            ifs.close();
            retValue.pack(res.payloadVersion);
            retValue.pack(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::string payloadFilePath =
                    "/var/oob/Payload" + std::to_string(payloadType);

                if (length < static_cast<uint32_t>(maxGetPayloadDataSize))
                {
                    phosphor::logging::log<phosphor::logging::level::ERR>(
                        "ipmiOEMGetPayload: length > maxGetPayloadDataSize",
                        phosphor::logging::entry("LENGTH=%d", length),
                        phosphor::logging::entry("maxGetPayloadDataSize=%d",
                                                 maxGetPayloadDataSize));
                    return ipmi::responseInvalidFieldRequest();
                }

                std::ifstream ifs(payloadFilePath, std::ios::in |
                                                       std::ios::binary |
                                                       std::ios::ate);

                if (!ifs.good())
                {
                    phosphor::logging::log<phosphor::logging::level::ERR>(
                        "ipmiOEMGetPayload: Payload File Error");
                    // File does not exist code here
                    return ipmi::response(ipmi::ccUnspecifiedError);
                }
                std::ifstream::pos_type fileSize = ifs.tellg();
                // Total file data within given offset
                if (fileSize < static_cast<uint64_t>(offset))
                {
                    phosphor::logging::log<phosphor::logging::level::ERR>(
                        "ipmiOEMGetPayload: filesize < offset");
                    return ipmi::responseInvalidFieldRequest();
                }

                if ((static_cast<uint64_t>(fileSize) - offset) < length)
                {
                    phosphor::logging::log<phosphor::logging::level::ERR>(
                        "ipmiOEMGetPayload: (filesize - offset) < length ");
                    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)
{
    // We should support this command only in KCS Interface
    if (!IsSystemInterface(ctx))
    {
        return ipmi::responseCommandNotAvailable();
    }

    // We should not support this command after System Booted - After Exit Boot
    // service called
    if (getPostCompleted())
    {
        return ipmi::response(ipmiCCNotSupportedInCurrentState);
    }

    nlohmann::json json;

    if ((algoInfo & 0xF) == algoSHA384)
    {
        json["HashAlgo"] = "SHA384";
    }
    else if ((algoInfo & 0xF) == algoSHA256)
    {
        json["HashAlgo"] = "SHA256";
    }
    else
    {
        return ipmi::responseInvalidFieldRequest();
    }

    json["Seed"] = pwdSeed;
    json["IsAdminPwdChanged"] = false;
    json["AdminPwdHash"] = adminPwdHash;
    json["IsUserPwdChanged"] = false;

    std::array<uint8_t, maxHashSize> userPwdHash;
    userPwdHash.fill({}); // initializing with 0 as user password hash field
                          // is not used presently
    json["UserPwdHash"] = userPwdHash;
    json["StatusFlag"] = algoInfo;

    std::string hashFilePath = "/var/lib/bios-settings-manager/seedData";
    std::ofstream ofs(hashFilePath, std::ios::out);
    const auto& writeData = json.dump();
    ofs << writeData;
    ofs.close();
    return ipmi::responseSuccess();
}

ipmi::RspType<std::array<uint8_t, maxSeedSize>, uint8_t,
              std::array<uint8_t, maxHashSize>>
    ipmiOEMGetBIOSHash(ipmi::Context::ptr ctx)
{
    nlohmann::json data = nullptr;

    // We should support this command only in KCS Interface
    if (!IsSystemInterface(ctx))
    {
        return ipmi::responseCommandNotAvailable();
    }

    // We should not support this command after System Booted - After Exit Boot
    // service called
    if (!getPostCompleted())
    {
        std::string HashFilePath = "/var/lib/bios-settings-manager/seedData";

        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, maxSeedSize> seed;

            uint8_t flag = 0;
            uint8_t adminPwdChangedFlag = 0;
            if (!data.is_discarded())
            {

                adminPwdChangedFlag = data["IsAdminPwdChanged"];
                newAdminHash = data["AdminPwdHash"];
                seed = data["Seed"];
            }

            auto status = getResetBIOSSettings(flag);
            if (status)
            {
                return ipmi::responseResponseError();
            }
            if (adminPwdChangedFlag)
            {
                flag |= adminPasswordChanged;
            }

            std::copy(std::begin(newAdminHash), std::end(newAdminHash),
                      std::begin(newAdminHash));

            return ipmi::responseSuccess(seed, flag, newAdminHash);
        }
        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
