#include <ipmid/api.h>
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <boost/algorithm/string.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/process/child.hpp>
#include <boost/uuid/random_generator.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <chrono>
#include <commandutils.hpp>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <ipmid/api.hpp>
#include <ipmid/utils.hpp>
#include <map>
#include <phosphor-logging/log.hpp>
#include <random>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/bus/match.hpp>
#include <sdbusplus/server/object.hpp>
#include <sdbusplus/timer.hpp>
#ifdef INTEL_PFR_ENABLED
#include <spiDev.hpp>
#endif

static constexpr bool DEBUG = true;
static void registerFirmwareFunctions() __attribute__((constructor));

namespace ipmi
{
namespace firmware
{
constexpr Cmd cmdGetFwVersionInfo = 0x20;
constexpr Cmd cmdGetFwSecurityVersionInfo = 0x21;
constexpr Cmd cmdGetFwUpdateChannelInfo = 0x22;
constexpr Cmd cmdGetBmcExecutionContext = 0x23;
constexpr Cmd cmdFwGetRootCertData = 0x25;
constexpr Cmd cmdGetFwUpdateRandomNumber = 0x26;
constexpr Cmd cmdSetFirmwareUpdateMode = 0x27;
constexpr Cmd cmdExitFirmwareUpdateMode = 0x28;
constexpr Cmd cmdGetSetFwUpdateControl = 0x29;
constexpr Cmd cmdGetFirmwareUpdateStatus = 0x2A;
constexpr Cmd cmdSetFirmwareUpdateOptions = 0x2B;
constexpr Cmd cmdFwImageWriteData = 0x2c;
} // namespace firmware
} // namespace ipmi

namespace ipmi
{
// Custom completion codes
constexpr Cc ccUsbAttachOrDetachFailed = 0x80;
constexpr Cc ccNotSupportedInPresentState = 0xD5;

static inline auto responseUsbAttachOrDetachFailed()
{
    return response(ccUsbAttachOrDetachFailed);
}
static inline auto responseNotSupportedInPresentState()
{
    return response(ccNotSupportedInPresentState);
}
} // namespace ipmi

static constexpr const char *bmcStateIntf = "xyz.openbmc_project.State.BMC";
static constexpr const char *bmcStatePath = "/xyz/openbmc_project/state/bmc0";
static constexpr const char *bmcStateReady =
    "xyz.openbmc_project.State.BMC.BMCState.Ready";
static constexpr const char *bmcStateUpdateInProgress =
    "xyz.openbmc_project.State.BMC.BMCState.UpdateInProgress";

static constexpr char firmwareBufferFile[] = "/tmp/fw-download.bin";
static std::chrono::steady_clock::time_point fwRandomNumGenTs;
static constexpr auto fwRandomNumExpirySeconds = std::chrono::seconds(30);
static constexpr size_t fwRandomNumLength = 8;
static std::array<uint8_t, fwRandomNumLength> fwRandomNum;
constexpr char usbCtrlPath[] = "/usr/bin/usb-ctrl";
constexpr char fwUpdateMountPoint[] = "/tmp/usb-fwupd.mnt";
constexpr char fwUpdateUsbVolImage[] = "/tmp/usb-fwupd.img";
constexpr char fwUpdateUSBDevName[] = "fw-usb-mass-storage-dev";
constexpr size_t fwPathMaxLength = 255;

#ifdef INTEL_PFR_ENABLED
uint32_t imgLength = 0;
uint32_t imgType = 0;
bool block0Mapped = false;
static constexpr uint32_t perBlock0MagicNum = 0xB6EAFD19;

static constexpr const char *bmcActivePfmMTDDev = "/dev/mtd/pfm";
static constexpr const char *bmcRecoveryImgMTDDev = "/dev/mtd/rc-image";
static constexpr size_t pfmBaseOffsetInImage = 0x400;
static constexpr size_t rootkeyOffsetInPfm = 0xA0;
static constexpr size_t cskKeyOffsetInPfm = 0x124;
static constexpr size_t cskSignatureOffsetInPfm = 0x19c;
static constexpr size_t certKeyLen = 96;
static constexpr size_t cskSignatureLen = 96;

static constexpr const char *versionIntf =
    "xyz.openbmc_project.Software.Version";

enum class FwGetRootCertDataTag : uint8_t
{
    activeRootKey = 1,
    recoveryRootKey,
    activeCSK,
    recoveryCSK,
};

enum class FWDeviceIDTag : uint8_t
{
    bmcActiveImage = 1,
    bmcRecoveryImage,
};

const static boost::container::flat_map<FWDeviceIDTag, const char *>
    fwVersionIdMap{{FWDeviceIDTag::bmcActiveImage,
                    "/xyz/openbmc_project/software/bmc_active"},
                   {FWDeviceIDTag::bmcRecoveryImage,
                    "/xyz/openbmc_project/software/bmc_recovery"}};
#endif // INTEL_PFR_ENABLED

enum class ChannelIdTag : uint8_t
{
    reserved = 0,
    kcs = 1,
    ipmb = 2,
    rmcpPlus = 3
};

enum class BmcExecutionContext : uint8_t
{
    reserved = 0,
    linuxOs = 0x10,
    bootLoader = 0x11,
};

enum class FwUpdateCtrlReq : uint8_t
{
    getCurrentControlStatus = 0x00,
    imageTransferStart = 0x01,
    imageTransferComplete = 0x02,
    imageTransferAbort = 0x03,
    setFirmwareFilename = 0x04,
    attachUsbDevice = 0x05,
    detachUsbDevice = 0x06
};

constexpr std::size_t operator""_MB(unsigned long long v)
{
    return 1024u * 1024u * v;
}
static constexpr size_t maxFirmwareImageSize = 32_MB;

static bool localDownloadInProgress(void)
{
    struct stat sb;
    if (stat(firmwareBufferFile, &sb) < 0)
    {
        return false;
    }
    return true;
}

class TransferHashCheck
{
  public:
    enum class HashCheck : uint8_t
    {
        notRequested = 0,
        requested,
        sha2Success,
        sha2Failed = 0xe2,
    };

  protected:
    EVP_MD_CTX *ctx;
    std::vector<uint8_t> expectedHash;
    enum HashCheck check;
    bool started;

  public:
    TransferHashCheck() : check(HashCheck::notRequested), started(false)
    {
    }
    ~TransferHashCheck()
    {
        if (ctx)
        {
            EVP_MD_CTX_destroy(ctx);
            ctx = NULL;
        }
    }
    void init(const std::vector<uint8_t> &expected)
    {
        expectedHash = expected;
        check = HashCheck::requested;
        ctx = EVP_MD_CTX_create();
        EVP_DigestInit(ctx, EVP_sha256());
    }
    void hash(const std::vector<uint8_t> &data)
    {
        if (!started)
        {
            started = true;
        }
        EVP_DigestUpdate(ctx, data.data(), data.size());
    }
    void clear()
    {
        // if not started, nothing to clear
        if (started)
        {
            if (ctx)
            {
                EVP_MD_CTX_destroy(ctx);
            }
            if (check != HashCheck::notRequested)
            {
                check = HashCheck::requested;
            }
            ctx = EVP_MD_CTX_create();
            EVP_DigestInit(ctx, EVP_sha256());
        }
    }
    enum HashCheck verify()
    {
        if (check == HashCheck::requested)
        {
            unsigned int len = 0;
            std::vector<uint8_t> digest(EVP_MD_size(EVP_sha256()));
            EVP_DigestFinal(ctx, digest.data(), &len);
            if (digest == expectedHash)
            {
                phosphor::logging::log<phosphor::logging::level::INFO>(
                    "Transfer sha2 verify passed.");
                check = HashCheck::sha2Success;
            }
            else
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "Transfer sha2 verify failed.");
                check = HashCheck::sha2Failed;
            }
        }
        return check;
    }
    uint8_t status() const
    {
        return static_cast<uint8_t>(check);
    }
};

class MappedFile
{
  public:
    MappedFile(const std::string &fname) : addr(nullptr), fsize(0)
    {
        std::error_code ec;
        size_t sz = std::filesystem::file_size(fname, ec);
        int fd = open(fname.c_str(), O_RDONLY);
        if (!ec || fd < 0)
        {
            return;
        }
        void *tmp = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
        close(fd);
        if (tmp == MAP_FAILED)
        {
            return;
        }
        addr = tmp;
        fsize = sz;
    }

    ~MappedFile()
    {
        if (addr)
        {
            munmap(addr, fsize);
        }
    }
    const uint8_t *data() const
    {
        return static_cast<const uint8_t *>(addr);
    }
    size_t size() const
    {
        return fsize;
    }

  private:
    size_t fsize;
    void *addr;
};

class FwUpdateStatusCache
{
  public:
    enum
    {
        fwStateInit = 0,
        fwStateIdle,
        fwStateDownload,
        fwStateVerify,
        fwStateProgram,
        fwStateUpdateSuccess,
        fwStateError = 0x0f,
        fwStateAcCycleRequired = 0x83,
    };
    uint8_t getState()
    {
        if ((fwUpdateState == fwStateIdle || fwUpdateState == fwStateInit) &&
            localDownloadInProgress())
        {
            fwUpdateState = fwStateDownload;
            progressPercent = 0;
        }
        return fwUpdateState;
    }
    void resetStatusCache()
    {
        unlink(firmwareBufferFile);
    }
    void setState(const uint8_t state)
    {
        switch (state)
        {
            case fwStateInit:
            case fwStateIdle:
            case fwStateError:
                resetStatusCache();
                break;
            case fwStateDownload:
            case fwStateVerify:
            case fwStateProgram:
            case fwStateUpdateSuccess:
                break;
            default:
                // Error
                break;
        }
        fwUpdateState = state;
    }
    uint8_t percent()
    {
        return progressPercent;
    }
    void updateActivationPercent(const std::string &objPath)
    {
        std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
        fwUpdateState = fwStateProgram;
        progressPercent = 0;
        match = std::make_shared<sdbusplus::bus::match::match>(
            *busp,
            sdbusplus::bus::match::rules::propertiesChanged(
                objPath, "xyz.openbmc_project.Software.ActivationProgress"),
            [&](sdbusplus::message::message &msg) {
                std::map<std::string, ipmi::DbusVariant> props;
                std::vector<std::string> inVal;
                std::string iface;
                try
                {
                    msg.read(iface, props, inVal);
                }
                catch (const std::exception &e)
                {
                    phosphor::logging::log<phosphor::logging::level::ERR>(
                        "Exception caught in get ActivationProgress");
                    return;
                }

                auto it = props.find("Progress");
                if (it != props.end())
                {
                    progressPercent = std::get<uint8_t>(it->second);
                    if (progressPercent == 100)
                    {
                        fwUpdateState = fwStateUpdateSuccess;
                    }
                }
            });
    }
    uint8_t activationTimerTimeout()
    {
        phosphor::logging::log<phosphor::logging::level::INFO>(
            "activationTimerTimeout: Increase percentage...",
            phosphor::logging::entry("PERCENT:%d", progressPercent));
        progressPercent = progressPercent + 5;
        if (progressPercent > 95)
        {
            /*changing the state to ready to update firmware utility */
            fwUpdateState = fwStateUpdateSuccess;
        }
        return progressPercent;
    }
    /* API for changing state to ERROR  */
    void firmwareUpdateAbortState()
    {
        unlink(firmwareBufferFile);
        // changing the state to error
        fwUpdateState = fwStateError;
    }
    void setDeferRestart(bool deferRestart)
    {
        deferRestartState = deferRestart;
    }
    void setInhibitDowngrade(bool inhibitDowngrade)
    {
        inhibitDowngradeState = inhibitDowngrade;
    }
    bool getDeferRestart()
    {
        return deferRestartState;
    }
    bool getInhibitDowngrade()
    {
        return inhibitDowngradeState;
    }

  protected:
    std::shared_ptr<sdbusplus::asio::connection> busp;
    std::shared_ptr<sdbusplus::bus::match::match> match;
    uint8_t fwUpdateState = 0;
    uint8_t progressPercent = 0;
    bool deferRestartState = false;
    bool inhibitDowngradeState = false;
};

static FwUpdateStatusCache fwUpdateStatus;
std::shared_ptr<TransferHashCheck> xferHashCheck;

static void activateImage(const std::string &objPath)
{
    // If flag is false  means to reboot
    if (fwUpdateStatus.getDeferRestart() == false)
    {
        phosphor::logging::log<phosphor::logging::level::INFO>(
            "activating Image: ",
            phosphor::logging::entry("OBJPATH =%s", objPath.c_str()));
        std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
        bus->async_method_call(
            [](const boost::system::error_code ec) {
                if (ec)
                {
                    phosphor::logging::log<phosphor::logging::level::ERR>(
                        "async_method_call error: activateImage failed");
                    return;
                }
            },
            "xyz.openbmc_project.Software.BMC.Updater", objPath,
            "org.freedesktop.DBus.Properties", "Set",
            "xyz.openbmc_project.Software.Activation", "RequestedActivation",
            std::variant<std::string>("xyz.openbmc_project.Software.Activation."
                                      "RequestedActivations.Active"));
    }
    else
    {
        phosphor::logging::log<phosphor::logging::level::INFO>(
            "Firmware image activation is deferred.");
    }
    fwUpdateStatus.setState(
        static_cast<uint8_t>(FwUpdateStatusCache::fwStateUpdateSuccess));
}

static bool getFirmwareUpdateMode()
{
    std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
    try
    {
        auto service = ipmi::getService(*busp, bmcStateIntf, bmcStatePath);
        ipmi::Value state = ipmi::getDbusProperty(
            *busp, service, bmcStatePath, bmcStateIntf, "CurrentBMCState");
        std::string bmcState = std::get<std::string>(state);
        return (bmcState == bmcStateUpdateInProgress);
    }
    catch (const std::exception &e)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Exception caught while getting BMC state.",
            phosphor::logging::entry("EXCEPTION=%s", e.what()));
        throw;
    }
}

static void setFirmwareUpdateMode(const bool mode)
{

    std::string bmcState(bmcStateReady);
    if (mode)
    {
        bmcState = bmcStateUpdateInProgress;
    }

    std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
    try
    {
        auto service = ipmi::getService(*busp, bmcStateIntf, bmcStatePath);
        ipmi::setDbusProperty(*busp, service, bmcStatePath, bmcStateIntf,
                              "CurrentBMCState", bmcState);
    }
    catch (const std::exception &e)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Exception caught while setting BMC state.",
            phosphor::logging::entry("EXCEPTION=%s", e.what()));
        throw;
    }
}

/** @brief check if channel IPMB
 *
 *  This function checks if the command is from IPMB
 *
 * @param[in] ctx - context of current session.
 *  @returns true if the medium is IPMB else return true.
 **/
ipmi::Cc checkIPMBChannel(const ipmi::Context::ptr &ctx, bool &isIPMBChannel)
{
    ipmi::ChannelInfo chInfo;

    if (ipmi::getChannelInfo(ctx->channel, chInfo) != ipmi::ccSuccess)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Failed to get Channel Info",
            phosphor::logging::entry("CHANNEL=%d", ctx->channel));
        return ipmi::ccUnspecifiedError;
    }

    if (static_cast<ipmi::EChannelMediumType>(chInfo.mediumType) ==
        ipmi::EChannelMediumType::ipmb)
    {
        isIPMBChannel = true;
    }
    return ipmi::ccSuccess;
}

static void postTransferCompleteHandler(
    std::unique_ptr<sdbusplus::bus::match::match> &fwUpdateMatchSignal)
{
    // Setup timer for watching signal
    static phosphor::Timer timer(
        [&fwUpdateMatchSignal]() { fwUpdateMatchSignal = nullptr; });

    static phosphor::Timer activationStatusTimer([]() {
        if (fwUpdateStatus.activationTimerTimeout() > 95)
        {
            activationStatusTimer.stop();
            fwUpdateStatus.setState(
                static_cast<uint8_t>(FwUpdateStatusCache::fwStateVerify));
        }
    });

    timer.start(std::chrono::microseconds(5000000), false);

    // callback function for capturing signal
    auto callback = [&](sdbusplus::message::message &m) {
        bool flag = false;

        std::vector<std::pair<
            std::string,
            std::vector<std::pair<std::string, std::variant<std::string>>>>>
            intfPropsPair;
        sdbusplus::message::object_path objPath;

        try
        {
            m.read(objPath, intfPropsPair); // Read in the object path
                                            // that was just created
        }
        catch (const std::exception &e)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Exception caught in reading created object path.");
            return;
        }
        // constructing response message
        phosphor::logging::log<phosphor::logging::level::INFO>(
            "New Interface Added.",
            phosphor::logging::entry("OBJPATH=%s", objPath.str.c_str()));
        for (auto &interface : intfPropsPair)
        {
            if (interface.first == "xyz.openbmc_project.Software.Activation")
            {
                // There are chances of getting two signals for
                // InterfacesAdded. So cross check and discrad second instance.
                if (fwUpdateMatchSignal == nullptr)
                {
                    return;
                }
                // Found our interface, disable callbacks
                fwUpdateMatchSignal = nullptr;

                phosphor::logging::log<phosphor::logging::level::INFO>(
                    "Start activationStatusTimer for status.");
                try
                {
                    timer.stop();
                    activationStatusTimer.start(
                        std::chrono::microseconds(3000000), true);
                }
                catch (const std::exception &e)
                {
                    phosphor::logging::log<phosphor::logging::level::ERR>(
                        "Exception caught in start activationStatusTimer.",
                        phosphor::logging::entry("ERROR=%s", e.what()));
                }

                fwUpdateStatus.updateActivationPercent(objPath.str);
                activateImage(objPath.str);
            }
        }
    };

    // Adding matcher
    fwUpdateMatchSignal = std::make_unique<sdbusplus::bus::match::match>(
        *getSdBus(),
        "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
        "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
        callback);
}
static bool startFirmwareUpdate(const std::string &uri)
{
    // fwupdate URIs start with file:// or usb:// or tftp:// etc. By the time
    // the code gets to this point, the file should be transferred start the
    // request (creating a new file in /tmp/images causes the update manager to
    // check if it is ready for activation)
    static std::unique_ptr<sdbusplus::bus::match::match> fwUpdateMatchSignal;
    postTransferCompleteHandler(fwUpdateMatchSignal);
    std::filesystem::rename(
        uri, "/tmp/images/" +
                 boost::uuids::to_string(boost::uuids::random_generator()()));
    return true;
}

static int transferImageFromFile(const std::string &uri, bool move = true)
{
    std::error_code ec;
    phosphor::logging::log<phosphor::logging::level::INFO>(
        "Transfer Image From File.",
        phosphor::logging::entry("URI=%s", uri.c_str()));
    if (move)
    {
        std::filesystem::rename(uri, firmwareBufferFile, ec);
    }
    else
    {
        std::filesystem::copy(uri, firmwareBufferFile,
                              std::filesystem::copy_options::overwrite_existing,
                              ec);
    }
    if (xferHashCheck)
    {
        MappedFile mappedfw(uri);
        xferHashCheck->hash(
            {mappedfw.data(), mappedfw.data() + mappedfw.size()});
    }
    if (ec.value())
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Image copy failed.");
    }
    return ec.value();
}

template <typename... ArgTypes>
static int executeCmd(const char *path, ArgTypes &&... tArgs)
{
    boost::process::child execProg(path, const_cast<char *>(tArgs)...);
    execProg.wait();
    return execProg.exit_code();
}

static int transferImageFromUsb(const std::string &uri)
{
    int ret, sysret;
    char fwpath[fwPathMaxLength];
    phosphor::logging::log<phosphor::logging::level::INFO>(
        "Transfer Image From USB.",
        phosphor::logging::entry("URI=%s", uri.c_str()));
    ret = executeCmd(usbCtrlPath, "mount", fwUpdateUsbVolImage,
                     fwUpdateMountPoint);
    if (ret)
    {
        return ret;
    }

    std::string usb_path = std::string(fwUpdateMountPoint) + "/" + uri;
    ret = transferImageFromFile(usb_path, false);

    executeCmd(usbCtrlPath, "cleanup", fwUpdateUsbVolImage, fwUpdateMountPoint);
    return ret;
}

static bool transferFirmwareFromUri(const std::string &uri)
{
    static constexpr char fwUriFile[] = "file://";
    static constexpr char fwUriUsb[] = "usb://";
    phosphor::logging::log<phosphor::logging::level::INFO>(
        "Transfer Image From URI.",
        phosphor::logging::entry("URI=%s", uri.c_str()));
    if (boost::algorithm::starts_with(uri, fwUriFile))
    {
        std::string fname = uri.substr(sizeof(fwUriFile) - 1);
        if (fname != firmwareBufferFile)
        {
            return 0 == transferImageFromFile(fname);
        }
        return true;
    }
    if (boost::algorithm::starts_with(uri, fwUriUsb))
    {
        std::string fname = uri.substr(sizeof(fwUriUsb) - 1);
        return 0 == transferImageFromUsb(fname);
    }
    return false;
}

/* Get USB-mass-storage device status: inserted => true, ejected => false */
static bool getUsbStatus()
{
    std::filesystem::path usbDevPath =
        std::filesystem::path("/sys/kernel/config/usb_gadget") /
        fwUpdateUSBDevName;
    return (std::filesystem::exists(usbDevPath) ? true : false);
}

/* Insert the USB-mass-storage device status: success => 0, failure => non-0 */
static int attachUsbDevice()
{
    if (getUsbStatus())
    {
        return 1;
    }
    int ret = executeCmd(usbCtrlPath, "setup", fwUpdateUsbVolImage,
                         std::to_string(maxFirmwareImageSize / 1_MB).c_str());
    if (!ret)
    {
        ret = executeCmd(usbCtrlPath, "insert", fwUpdateUSBDevName,
                         fwUpdateUsbVolImage);
    }
    return ret;
}

/* Eject the USB-mass-storage device status: success => 0, failure => non-0 */
static int detachUsbDevice()
{
    if (!getUsbStatus())
    {
        return 1;
    }
    return executeCmd(usbCtrlPath, "eject", fwUpdateUSBDevName);
}
static uint8_t getActiveBootImage(ipmi::Context::ptr ctx)
{
    constexpr uint8_t undefinedImage = 0x00;
    constexpr uint8_t primaryImage = 0x01;
    constexpr uint8_t secondaryImage = 0x02;
    constexpr const char *secondaryFitImageStartAddr = "22480000";

    uint8_t bootImage = primaryImage;
    boost::system::error_code ec;
    std::string value = ctx->bus->yield_method_call<std::string>(
        ctx->yield, ec, "xyz.openbmc_project.U_Boot.Environment.Manager",
        "/xyz/openbmc_project/u_boot/environment/mgr",
        "xyz.openbmc_project.U_Boot.Environment.Manager", "Read", "bootcmd");
    if (ec)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Failed to read the bootcmd value");
        /* don't fail, just give back undefined until it is ready */
        bootImage = undefinedImage;
    }

    /* cheking for secondary FitImage Address 22480000  */
    else if (value.find(secondaryFitImageStartAddr) != std::string::npos)
    {
        bootImage = secondaryImage;
    }
    else
    {
        bootImage = primaryImage;
    }

    return bootImage;
}

#ifdef INTEL_PFR_ENABLED
using fwVersionInfoType = std::tuple<uint8_t,   // ID Tag
                                     uint8_t,   // Major Version Number
                                     uint8_t,   // Minor Version Number
                                     uint32_t,  // Build Number
                                     uint32_t,  // Build Timestamp
                                     uint32_t>; // Update Timestamp
ipmi::RspType<uint8_t, std::vector<fwVersionInfoType>> ipmiGetFwVersionInfo()
{
    // Byte 1 - Count (N) Number of devices data is being returned for.
    // Bytes  2:16 - Device firmare information(fwVersionInfoType)
    // Bytes - 17:(15xN) - Repeat of 2 through 16

    std::vector<fwVersionInfoType> fwVerInfoList;
    std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
    for (const auto &fwDev : fwVersionIdMap)
    {
        std::string verStr;
        try
        {
            auto service = ipmi::getService(*busp, versionIntf, fwDev.second);

            ipmi::Value result = ipmi::getDbusProperty(
                *busp, service, fwDev.second, versionIntf, "Version");
            verStr = std::get<std::string>(result);
        }
        catch (const std::exception &e)
        {
            phosphor::logging::log<phosphor::logging::level::INFO>(
                "Failed to fetch Version property",
                phosphor::logging::entry("ERROR=%s", e.what()),
                phosphor::logging::entry("PATH=%s", fwDev.second),
                phosphor::logging::entry("INTERFACE=%s", versionIntf));
            continue;
        }

        if (verStr.empty())
        {
            phosphor::logging::log<phosphor::logging::level::INFO>(
                "Version is empty.",
                phosphor::logging::entry("PATH=%s", fwDev.second),
                phosphor::logging::entry("INTERFACE=%s", versionIntf));
            continue;
        }

        // BMC Version format: <major>.<minor>-<build bum>-<build hash>
        std::vector<std::string> splitVer;
        boost::split(splitVer, verStr, boost::is_any_of(".-"));
        if (splitVer.size() < 3)
        {
            phosphor::logging::log<phosphor::logging::level::INFO>(
                "Invalid Version format.",
                phosphor::logging::entry("Version=%s", verStr.c_str()),
                phosphor::logging::entry("PATH=%s", fwDev.second));
            continue;
        }

        uint8_t majorNum = 0;
        uint8_t minorNum = 0;
        uint32_t buildNum = 0;
        try
        {
            majorNum = std::stoul(splitVer[0], nullptr, 16);
            minorNum = std::stoul(splitVer[1], nullptr, 16);
            buildNum = std::stoul(splitVer[2], nullptr, 16);
        }
        catch (const std::exception &e)
        {
            phosphor::logging::log<phosphor::logging::level::INFO>(
                "Failed to convert stoul.",
                phosphor::logging::entry("ERROR=%s", e.what()));
            continue;
        }

        // Build Timestamp - Not supported.
        // Update Timestamp - TODO: Need to check with CPLD team.
        fwVerInfoList.emplace_back(
            fwVersionInfoType(static_cast<uint8_t>(fwDev.first), majorNum,
                              minorNum, buildNum, 0, 0));
    }

    return ipmi::responseSuccess(fwVerInfoList.size(), fwVerInfoList);
}
using fwSecurityVersionInfoType = std::tuple<uint8_t,  // ID Tag
                                             uint8_t,  // BKC Version
                                             uint8_t>; // SVN Version
ipmi::RspType<uint8_t, std::vector<fwSecurityVersionInfoType>>
    ipmiGetFwSecurityVersionInfo()
{
    // TODO: Need to add support.
    return ipmi::responseInvalidCommand();
}

ipmi::RspType<std::array<uint8_t, certKeyLen>,
              std::optional<std::array<uint8_t, cskSignatureLen>>>
    ipmiGetFwRootCertData(const ipmi::Context::ptr &ctx, uint8_t certId)
{
    bool isIPMBChannel = false;

    if (checkIPMBChannel(ctx, isIPMBChannel) != ipmi::ccSuccess)
    {
        return ipmi::responseUnspecifiedError();
    }
    if (isIPMBChannel)
    {
        phosphor::logging::log<phosphor::logging::level::INFO>(
            "Command not supported. Failed to get root certificate data.");
        return ipmi::responseCommandNotAvailable();
    }

    size_t certKeyOffset = 0;
    size_t cskSigOffset = 0;
    std::string mtdDev;

    switch (static_cast<FwGetRootCertDataTag>(certId))
    {
        case FwGetRootCertDataTag::activeRootKey:
        {
            mtdDev = bmcActivePfmMTDDev;
            certKeyOffset = rootkeyOffsetInPfm;
            break;
        }
        case FwGetRootCertDataTag::recoveryRootKey:
        {
            mtdDev = bmcRecoveryImgMTDDev;
            certKeyOffset = pfmBaseOffsetInImage + rootkeyOffsetInPfm;
            break;
        }
        case FwGetRootCertDataTag::activeCSK:
        {
            mtdDev = bmcActivePfmMTDDev;
            certKeyOffset = cskKeyOffsetInPfm;
            cskSigOffset = cskSignatureOffsetInPfm;
            break;
        }
        case FwGetRootCertDataTag::recoveryCSK:
        {
            mtdDev = bmcRecoveryImgMTDDev;
            certKeyOffset = pfmBaseOffsetInImage + cskKeyOffsetInPfm;
            cskSigOffset = pfmBaseOffsetInImage + cskSignatureOffsetInPfm;
            break;
        }
        default:
        {
            return ipmi::responseInvalidFieldRequest();
        }
    }

    std::array<uint8_t, certKeyLen> certKey = {0};

    try
    {
        SPIDev spiDev(mtdDev);
        spiDev.spiReadData(certKeyOffset, certKeyLen, certKey.data());

        if (cskSigOffset)
        {
            std::array<uint8_t, cskSignatureLen> cskSignature = {0};
            spiDev.spiReadData(cskSigOffset, cskSignatureLen,
                               cskSignature.data());
            return ipmi::responseSuccess(certKey, cskSignature);
        }
    }
    catch (const std::exception &e)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Exception caught in ipmiGetFwRootCertData",
            phosphor::logging::entry("MSG=%s", e.what()));
        return ipmi::responseUnspecifiedError();
    }

    return ipmi::responseSuccess(certKey, std::nullopt);
}
#endif // INTEL_PFR_ENABLED

static constexpr uint8_t channelListSize = 3;
/** @brief implements Maximum Firmware Transfer size command
 *  @parameter
 *   -  none
 *  @returns IPMI completion code plus response data
 *   - count - channel count
 *   - channelList - channel list information
 */
ipmi::RspType<uint8_t, // channel count
              std::array<std::tuple<uint8_t, uint32_t>,
                         channelListSize> // Channel List
              >
    ipmiFirmwareMaxTransferSize()
{
    constexpr size_t kcsMaxBufSize = 128;
    constexpr size_t rmcpPlusMaxBufSize = 50 * 1024;
    // Byte 1 - Count (N) Number of devices data is being returned for.
    // Byte 2 - ID Tag 00 – reserved 01 – kcs 02 – rmcp+, 03 - ipmb
    // Byte 3-6 - transfer size (little endian)
    // Bytes - 7:(5xN) - Repeat of 2 through 6
    constexpr std::array<std::tuple<uint8_t, uint32_t>, channelListSize>
        channelList = {
            {{static_cast<uint8_t>(ChannelIdTag::kcs), kcsMaxBufSize},
             {static_cast<uint8_t>(ChannelIdTag::rmcpPlus),
              rmcpPlusMaxBufSize}}};

    return ipmi::responseSuccess(channelListSize, channelList);
}

ipmi::RspType<uint8_t, uint8_t>
    ipmiGetBmcExecutionContext(ipmi::Context::ptr ctx)
{
    // Byte 1 - Current execution context
    //          0x10 - Linux OS, 0x11 - Bootloader, Forced-firmware updat mode
    // Byte 2 - Partition pointer
    //          0x01 - primary, 0x02 - secondary
    uint8_t partitionPtr = getActiveBootImage(ctx);

    return ipmi::responseSuccess(
        static_cast<uint8_t>(BmcExecutionContext::linuxOs), partitionPtr);
}
/** @brief Get Firmware Update Random Number
 *
 *  This function generate the random number used for
 *  setting the firmware update mode as authentication key.
 *
 * @param[in] ctx - context of current session
 *  @returns IPMI completion code along with
 *   - random number
 **/
ipmi::RspType<std::array<uint8_t, fwRandomNumLength>>
    ipmiGetFwUpdateRandomNumber(const ipmi::Context::ptr &ctx)
{
    phosphor::logging::log<phosphor::logging::level::INFO>(
        "Generate FW update random number");
    bool isIPMBChannel = false;

    if (checkIPMBChannel(ctx, isIPMBChannel) != ipmi::ccSuccess)
    {
        return ipmi::responseUnspecifiedError();
    }
    if (isIPMBChannel)
    {
        phosphor::logging::log<phosphor::logging::level::INFO>(
            "Channel not supported. Failed to fetch FW update random number");
        return ipmi::responseCommandNotAvailable();
    }
    std::random_device rd;
    std::default_random_engine gen(rd());
    std::uniform_int_distribution<> dist{0, 255};

    fwRandomNumGenTs = std::chrono::steady_clock::now();

    for (int i = 0; i < fwRandomNumLength; i++)
    {
        fwRandomNum[i] = dist(gen);
    }

    return ipmi::responseSuccess(fwRandomNum);
}

/** @brief Set Firmware Update Mode
 *
 *  This function sets BMC into firmware update mode
 *  after validating Random number obtained from the Get
 *  Firmware Update Random Number command
 *
 * @param[in] ctx - context of current session
 * @parameter randNum - Random number(token)
 * @returns IPMI completion code
 **/
ipmi::RspType<>
    ipmiSetFirmwareUpdateMode(const ipmi::Context::ptr &ctx,
                              std::array<uint8_t, fwRandomNumLength> &randNum)
{
    phosphor::logging::log<phosphor::logging::level::INFO>(
        "Start FW update mode");

    bool isIPMBChannel = false;

    if (checkIPMBChannel(ctx, isIPMBChannel) != ipmi::ccSuccess)
    {
        return ipmi::responseUnspecifiedError();
    }
    if (isIPMBChannel)
    {
        phosphor::logging::log<phosphor::logging::level::INFO>(
            "Channel not supported. Failed to set FW update mode");
        return ipmi::responseCommandNotAvailable();
    }
    /* Firmware Update Random number is valid for 30 seconds only */
    auto timeElapsed = (std::chrono::steady_clock::now() - fwRandomNumGenTs);
    if (std::chrono::duration_cast<std::chrono::microseconds>(timeElapsed)
            .count() > std::chrono::duration_cast<std::chrono::microseconds>(
                           fwRandomNumExpirySeconds)
                           .count())
    {
        phosphor::logging::log<phosphor::logging::level::INFO>(
            "Firmware update random number expired.");
        return ipmi::responseInvalidFieldRequest();
    }

    /* Validate random number */
    for (int i = 0; i < fwRandomNumLength; i++)
    {
        if (fwRandomNum[i] != randNum[i])
        {
            phosphor::logging::log<phosphor::logging::level::INFO>(
                "Invalid random number specified.");
            return ipmi::responseInvalidFieldRequest();
        }
    }

    try
    {
        if (getFirmwareUpdateMode())
        {
            phosphor::logging::log<phosphor::logging::level::INFO>(
                "Already firmware update is in progress.");
            return ipmi::responseBusy();
        }
    }
    catch (const std::exception &e)
    {
        return ipmi::responseUnspecifiedError();
    }

    // FIXME? c++ doesn't off an option for exclusive file creation
    FILE *fp = fopen(firmwareBufferFile, "wx");
    if (!fp)
    {
        phosphor::logging::log<phosphor::logging::level::INFO>(
            "Unable to open file.");
        return ipmi::responseUnspecifiedError();
    }
    fclose(fp);

    try
    {
        setFirmwareUpdateMode(true);
    }
    catch (const std::exception &e)
    {
        unlink(firmwareBufferFile);
        return ipmi::responseUnspecifiedError();
    }

    return ipmi::responseSuccess();
}

/** @brief implements exit firmware update mode command
 *  @param None
 *
 *  @returns IPMI completion code
 */
ipmi::RspType<> ipmiExitFirmwareUpdateMode(const ipmi::Context::ptr &ctx)
{
    phosphor::logging::log<phosphor::logging::level::INFO>(
        "Exit FW update mode");
    bool isIPMBChannel = false;

    if (checkIPMBChannel(ctx, isIPMBChannel) != ipmi::ccSuccess)
    {
        return ipmi::responseUnspecifiedError();
    }
    if (isIPMBChannel)
    {
        phosphor::logging::log<phosphor::logging::level::INFO>(
            "Command not supported. Failed to exit firmware update mode");
        return ipmi::responseCommandNotAvailable();
    }

    switch (fwUpdateStatus.getState())
    {
        case FwUpdateStatusCache::fwStateInit:
        case FwUpdateStatusCache::fwStateIdle:
            return ipmi::responseInvalidFieldRequest();
            break;
        case FwUpdateStatusCache::fwStateDownload:
        case FwUpdateStatusCache::fwStateVerify:
            break;
        case FwUpdateStatusCache::fwStateProgram:
            break;
        case FwUpdateStatusCache::fwStateUpdateSuccess:
        case FwUpdateStatusCache::fwStateError:
            break;
        case FwUpdateStatusCache::fwStateAcCycleRequired:
            return ipmi::responseInvalidFieldRequest();
            break;
    }
    fwUpdateStatus.firmwareUpdateAbortState();

    try
    {
        setFirmwareUpdateMode(false);
    }
    catch (const std::exception &e)
    {
        return ipmi::responseUnspecifiedError();
    }

    return ipmi::responseSuccess();
}

/** @brief implements Get/Set Firmware Update Control
 *  @param[in] ctx - context of current session
 *  @parameter
 *   - Byte 1: Control Byte
 *   - Byte 2: Firmware filename length (Optional)
 *   - Byte 3:N: Firmware filename data (Optional)
 *  @returns IPMI completion code plus response data
 *   - Byte 2: Current control status
 **/
ipmi::RspType<bool, bool, bool, bool, uint4_t>
    ipmiGetSetFirmwareUpdateControl(const ipmi::Context::ptr &ctx,
                                    const uint8_t controlReq,
                                    const std::optional<std::string> &fileName)
{
    bool isIPMBChannel = false;

    if (checkIPMBChannel(ctx, isIPMBChannel) != ipmi::ccSuccess)
    {
        return ipmi::responseUnspecifiedError();
    }
    if (isIPMBChannel)
    {
        phosphor::logging::log<phosphor::logging::level::INFO>(
            "Channel not supported. Failed to get or set FW update control");
        return ipmi::responseCommandNotAvailable();
    }

    static std::string fwXferUriPath;
    static bool imageTransferStarted = false;
    static bool imageTransferCompleted = false;
    static bool imageTransferAborted = false;

    if ((controlReq !=
         static_cast<uint8_t>(FwUpdateCtrlReq::setFirmwareFilename)) &&
        (fileName))
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Invalid request field (Filename).");
        return ipmi::responseInvalidFieldRequest();
    }

    static bool usbAttached = getUsbStatus();

    switch (static_cast<FwUpdateCtrlReq>(controlReq))
    {
        case FwUpdateCtrlReq::getCurrentControlStatus:
            phosphor::logging::log<phosphor::logging::level::INFO>(
                "ipmiGetSetFirmwareUpdateControl: Get status");
            break;
        case FwUpdateCtrlReq::imageTransferStart:
        {
            phosphor::logging::log<phosphor::logging::level::INFO>(
                "ipmiGetSetFirmwareUpdateControl: Set transfer start");
            imageTransferStarted = true;
            // reset buffer to empty (truncate file)
            std::ofstream out(firmwareBufferFile,
                              std::ofstream::binary | std::ofstream::trunc);
            fwXferUriPath = std::string("file://") + firmwareBufferFile;
            if (xferHashCheck)
            {
                xferHashCheck->clear();
            }
            // Setting state to download
            fwUpdateStatus.setState(
                static_cast<uint8_t>(FwUpdateStatusCache::fwStateDownload));
#ifdef INTEL_PFR_ENABLED
            imgLength = 0;
            imgType = 0;
            block0Mapped = false;
#endif
        }
        break;
        case FwUpdateCtrlReq::imageTransferComplete:
        {
            phosphor::logging::log<phosphor::logging::level::INFO>(
                "ipmiGetSetFirmwareUpdateControl: Set transfer complete.");
            if (usbAttached)
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "USB should be detached to perform this operation.");
                return ipmi::responseNotSupportedInPresentState();
            }
            // finish transfer based on URI
            if (!transferFirmwareFromUri(fwXferUriPath))
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "transferFirmwareFromUri failed.");
                return ipmi::responseUnspecifiedError();
            }
            // transfer complete
            if (xferHashCheck)
            {
                if (TransferHashCheck::HashCheck::sha2Success !=
                    xferHashCheck->verify())
                {
                    phosphor::logging::log<phosphor::logging::level::ERR>(
                        "xferHashCheck failed.");
                    return ipmi::responseUnspecifiedError();
                }
            }
            // Set state to verify and start the update
            fwUpdateStatus.setState(
                static_cast<uint8_t>(FwUpdateStatusCache::fwStateVerify));
            // start the request
            if (!startFirmwareUpdate(firmwareBufferFile))
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "startFirmwareUpdate failed.");
                return ipmi::responseUnspecifiedError();
            }
            imageTransferCompleted = true;
        }
        break;
        case FwUpdateCtrlReq::imageTransferAbort:
            phosphor::logging::log<phosphor::logging::level::INFO>(
                "ipmiGetSetFirmwareUpdateControl: Set transfer abort.");
            if (usbAttached)
            {
                if (detachUsbDevice())
                {
                    phosphor::logging::log<phosphor::logging::level::ERR>(
                        "Detach USB device failed.");
                    return ipmi::responseUsbAttachOrDetachFailed();
                }
                usbAttached = false;
            }
            // During abort request reset the state to Init by cleaning update
            // file.
            fwUpdateStatus.firmwareUpdateAbortState();
            imageTransferAborted = true;
            break;
        case FwUpdateCtrlReq::setFirmwareFilename:
            phosphor::logging::log<phosphor::logging::level::INFO>(
                "ipmiGetSetFirmwareUpdateControl: Set filename.");
            if (!fileName || ((*fileName).length() == 0))
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "Invalid Filename specified.");
                return ipmi::responseInvalidFieldRequest();
            }

            fwXferUriPath = *fileName;
            break;
        case FwUpdateCtrlReq::attachUsbDevice:
            phosphor::logging::log<phosphor::logging::level::INFO>(
                "ipmiGetSetFirmwareUpdateControl: Attach USB device.");
            if (usbAttached)
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "USB device is already attached.");
                return ipmi::responseInvalidFieldRequest();
            }
            if (attachUsbDevice())
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "Attach USB device failed.");
                return ipmi::responseUsbAttachOrDetachFailed();
            }
            usbAttached = true;
            break;
        case FwUpdateCtrlReq::detachUsbDevice:
            phosphor::logging::log<phosphor::logging::level::INFO>(
                "ipmiGetSetFirmwareUpdateControl: Detach USB device.");
            if (!usbAttached)
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "USB device is not attached.");
                return ipmi::responseInvalidFieldRequest();
            }
            if (detachUsbDevice())
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "Detach USB device failed.");
                return ipmi::responseUsbAttachOrDetachFailed();
            }
            usbAttached = false;
            break;
        default:
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Invalid control option specified.");
            return ipmi::responseInvalidFieldRequest();
    }

    return ipmi::responseSuccess(imageTransferStarted, imageTransferCompleted,
                                 imageTransferAborted, usbAttached, uint4_t(0));
}

/** @brief implements firmware get status command
 *  @parameter
 *   -  none
 *  @returns IPMI completion code plus response data
 *   - status     -  processing status
 *   - percentage -  percentage completion
 *   - check      -  channel integrity check status
 **/
ipmi::RspType<uint8_t, // status
              uint8_t, // percentage
              uint8_t  // check
              >
    ipmiGetFirmwareUpdateStatus()

{
    // Byte 1 - status (0=init, 1=idle, 2=download, 3=validate, 4=write,
    //                  5=ready, f=error, 83=ac cycle required)
    // Byte 2 - percent
    // Byte 3 - integrity check status (0=none, 1=req, 2=sha2ok, e2=sha2fail)
    uint8_t status = fwUpdateStatus.getState();
    uint8_t percent = fwUpdateStatus.percent();
    uint8_t check = xferHashCheck ? xferHashCheck->status() : 0;

    // Status code.
    return ipmi::responseSuccess(status, percent, check);
}

ipmi::RspType<bool, bool, bool, uint5_t> ipmiSetFirmwareUpdateOptions(
    const ipmi::Context::ptr &ctx, bool noDowngradeMask, bool deferRestartMask,
    bool sha2CheckMask, uint5_t reserved1, bool noDowngrade, bool deferRestart,
    bool sha2Check, uint5_t reserved2,
    std::optional<std::vector<uint8_t>> integrityCheckVal)
{
    phosphor::logging::log<phosphor::logging::level::INFO>(
        "Set firmware update options.");
    bool isIPMBChannel = false;

    if (checkIPMBChannel(ctx, isIPMBChannel) != ipmi::ccSuccess)
    {
        return ipmi::responseUnspecifiedError();
    }
    if (isIPMBChannel)
    {
        phosphor::logging::log<phosphor::logging::level::INFO>(
            "Channel not supported. Failed to set firmware update options");
        return ipmi::responseCommandNotAvailable();
    }
    bool noDowngradeState = fwUpdateStatus.getInhibitDowngrade();
    bool deferRestartState = fwUpdateStatus.getDeferRestart();
    bool sha2CheckState = xferHashCheck ? true : false;

    if (noDowngradeMask && (noDowngradeState != noDowngrade))
    {
        fwUpdateStatus.setInhibitDowngrade(noDowngrade);
        noDowngradeState = noDowngrade;
    }
    if (deferRestartMask && (deferRestartState != deferRestart))
    {
        fwUpdateStatus.setDeferRestart(deferRestart);
        deferRestartState = deferRestart;
    }
    if (sha2CheckMask)
    {
        if (sha2Check)
        {
            auto hashSize = EVP_MD_size(EVP_sha256());
            if ((*integrityCheckVal).size() != hashSize)
            {
                phosphor::logging::log<phosphor::logging::level::DEBUG>(
                    "Invalid size of Hash specified.");
                return ipmi::responseInvalidFieldRequest();
            }
            xferHashCheck = std::make_shared<TransferHashCheck>();
            xferHashCheck->init(*integrityCheckVal);
        }
        else
        {
            // delete the xferHashCheck object
            xferHashCheck.reset();
        }
        sha2CheckState = sha2CheckMask;
    }
    return ipmi::responseSuccess(noDowngradeState, deferRestartState,
                                 sha2CheckState, reserved1);
}

ipmi::RspType<uint32_t>
    ipmiFwImageWriteData(const std::vector<uint8_t> &writeData)
{
    const uint8_t ccCmdNotSupportedInPresentState = 0xD5;
    size_t writeDataLen = writeData.size();

    if (!writeDataLen)
    {
        return ipmi::responseReqDataLenInvalid();
    }

    if (fwUpdateStatus.getState() != FwUpdateStatusCache::fwStateDownload)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Invalid firmware update state.");
        return ipmi::response(ccCmdNotSupportedInPresentState);
    }

    std::ofstream out(firmwareBufferFile,
                      std::ofstream::binary | std::ofstream::app);
    if (!out)
    {
        phosphor::logging::log<phosphor::logging::level::DEBUG>(
            "Error while opening file.");
        return ipmi::responseUnspecifiedError();
    }

    uint64_t fileDataLen = out.tellp();

    if ((fileDataLen + writeDataLen) > maxFirmwareImageSize)
    {
        phosphor::logging::log<phosphor::logging::level::DEBUG>(
            "Firmware image size exceeds the limit");
        return ipmi::responseInvalidFieldRequest();
    }

    const char *data = reinterpret_cast<const char *>(writeData.data());
    out.write(data, writeDataLen);
    out.close();

    if (xferHashCheck)
    {
        xferHashCheck->hash(writeData);
    }

#ifdef INTEL_PFR_ENABLED
    /* PFR image block 0 - As defined in HAS */
    struct PFRImageBlock0
    {
        uint32_t tag;
        uint32_t pcLength;
        uint32_t pcType;
        uint32_t reserved1;
        uint8_t hash256[32];
        uint8_t hash384[48];
        uint8_t reserved2[32];
    } __attribute__((packed));

    /* Get the PFR block 0 data and read the uploaded image
     * information( Image type, length etc) */
    if (((fileDataLen + writeDataLen) >= sizeof(PFRImageBlock0)) &&
        (!block0Mapped))
    {
        struct PFRImageBlock0 block0Data = {0};

        std::ifstream inFile(firmwareBufferFile,
                             std::ios::binary | std::ios::in);
        inFile.read(reinterpret_cast<char *>(&block0Data), sizeof(block0Data));
        inFile.close();

        uint32_t magicNum = block0Data.tag;

        /* Validate the magic number */
        if (magicNum != perBlock0MagicNum)
        {
            phosphor::logging::log<phosphor::logging::level::DEBUG>(
                "PFR image magic number not matched");
            return ipmi::responseInvalidFieldRequest();
        }
        // Note:imgLength, imgType and block0Mapped are in global scope, as
        // these are used in cascaded updates.
        imgLength = block0Data.pcLength;
        imgType = block0Data.pcType;
        block0Mapped = true;
    }
#endif // end of INTEL_PFR_ENABLED
    return ipmi::responseSuccess(writeDataLen);
}

static void registerFirmwareFunctions()
{
    // guarantee that we start with an already timed out timestamp
    fwRandomNumGenTs =
        std::chrono::steady_clock::now() - fwRandomNumExpirySeconds;
    fwUpdateStatus.setState(
        static_cast<uint8_t>(FwUpdateStatusCache::fwStateInit));

    unlink(firmwareBufferFile);

#ifdef INTEL_PFR_ENABLED
    // Following commands are supported only for PFR enabled platforms
    // CMD:0x20 - Get Firmware Version Information
    // CMD:0x21 - Get Firmware Security Version Information
    // CMD:0x25 - Get Root Certificate Data

    // get firmware version information
    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnFirmware,
                          ipmi::firmware::cmdGetFwVersionInfo,
                          ipmi::Privilege::Admin, ipmiGetFwVersionInfo);

    // get firmware security version information
    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnFirmware,
                          ipmi::firmware::cmdGetFwSecurityVersionInfo,
                          ipmi::Privilege::Admin, ipmiGetFwSecurityVersionInfo);

    // get root certificate data
    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnFirmware,
                          ipmi::firmware::cmdFwGetRootCertData,
                          ipmi::Privilege::Admin, ipmiGetFwRootCertData);
#endif

    // get firmware update channel information (max transfer sizes)
    ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnFirmware,
                          ipmi::firmware::cmdGetFwUpdateChannelInfo,
                          ipmi::Privilege::Admin, ipmiFirmwareMaxTransferSize);

    // get bmc execution context
    ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnFirmware,
                          ipmi::firmware::cmdGetBmcExecutionContext,
                          ipmi::Privilege::Admin, ipmiGetBmcExecutionContext);

    // Get Firmware Update Random number
    ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnFirmware,
                          ipmi::firmware::cmdGetFwUpdateRandomNumber,
                          ipmi::Privilege::Admin, ipmiGetFwUpdateRandomNumber);

    // Set Firmware Update Mode
    ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnFirmware,
                          ipmi::firmware::cmdSetFirmwareUpdateMode,
                          ipmi::Privilege::Admin, ipmiSetFirmwareUpdateMode);

    // Exit Firmware Update Mode
    ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnFirmware,
                          ipmi::firmware::cmdExitFirmwareUpdateMode,
                          ipmi::Privilege::Admin, ipmiExitFirmwareUpdateMode);

    // Get/Set Firmware Update Control
    ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnFirmware,
                          ipmi::firmware::cmdGetSetFwUpdateControl,
                          ipmi::Privilege::Admin,
                          ipmiGetSetFirmwareUpdateControl);

    // Get Firmware Update Status
    ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnFirmware,
                          ipmi::firmware::cmdGetFirmwareUpdateStatus,
                          ipmi::Privilege::Admin, ipmiGetFirmwareUpdateStatus);

    // Set Firmware Update Options
    ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnFirmware,
                          ipmi::firmware::cmdSetFirmwareUpdateOptions,
                          ipmi::Privilege::Admin, ipmiSetFirmwareUpdateOptions);
    // write image data
    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnFirmware,
                          ipmi::firmware::cmdFwImageWriteData,
                          ipmi::Privilege::Admin, ipmiFwImageWriteData);
    return;
}
