Firmware update commmands re-write

Firmware update commands re-write
 * Updated to new API style
 * Coding guidelines for all names
 * Restricted few commands for PFR
 * Few updates as per new OpenBMC EPS
 * Changes for fw update status
 * Removed legacy API's used for FW update

Tested:
 - Tested firmware update using fwpiaupd.efi tool
   in usb and kcs trasfer mode.
 - Tested all firmware update commands over LAN.

Change-Id: I666cb139b2ca61d352e1cb6b1c18d045b7b1f197
Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
diff --git a/src/firmware-update.cpp b/src/firmware-update.cpp
index d949a33..d3236d5 100644
--- a/src/firmware-update.cpp
+++ b/src/firmware-update.cpp
@@ -7,7 +7,7 @@
 #include <unistd.h>
 
 #include <boost/algorithm/string.hpp>
-#include <boost/asio.hpp>
+#include <boost/container/flat_map.hpp>
 #include <boost/process/child.hpp>
 #include <boost/uuid/random_generator.hpp>
 #include <boost/uuid/uuid_io.hpp>
@@ -20,35 +20,98 @@
 #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>
-#include <sstream>
 #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,
@@ -60,269 +123,349 @@
                     "/xyz/openbmc_project/software/bmc_active"},
                    {FWDeviceIDTag::bmcRecoveryImage,
                     "/xyz/openbmc_project/software/bmc_recovery"}};
+#endif // INTEL_PFR_ENABLED
 
-#endif
+enum class ChannelIdTag : uint8_t
+{
+    reserved = 0,
+    kcs = 1,
+    ipmb = 2,
+    rmcpPlus = 3
+};
 
-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";
+enum class BmcExecutionContext : uint8_t
+{
+    reserved = 0,
+    linuxOs = 0x10,
+    bootLoader = 0x11,
+};
 
-static constexpr const char *secondaryFitImageStartAddr = "22480000";
-static uint8_t getActiveBootImage(void);
-static void register_netfn_firmware_functions() __attribute__((constructor));
-
-// oem return code for firmware update control
-constexpr ipmi_ret_t IPMI_CC_REQ_INVALID_PHASE = 0xd5;
-constexpr ipmi_ret_t IPMI_CC_USB_ATTACH_FAIL = 0x80;
-
-static constexpr bool DEBUG = false;
-
-static constexpr char FW_UPDATE_SERVER_DBUS_NAME[] =
-    "xyz.openbmc_project.fwupdate1.server";
-
-static constexpr char FW_UPDATE_SERVER_PATH[] =
-    "/xyz/openbmc_project/fwupdate1";
-static constexpr char FW_UPDATE_SERVER_INFO_PATH[] =
-    "/xyz/openbmc_project/fwupdate1/info";
-static constexpr char FW_UPDATE_ACTIVE_INFO_PATH[] =
-    "/xyz/openbmc_project/fwupdate1/info/bmc_active";
-static constexpr char FW_UPDATE_BACKUP_INFO_PATH[] =
-    "/xyz/openbmc_project/fwupdate1/info/bmc_backup";
-
-static constexpr char FW_UPDATE_INTERFACE[] = "xyz.openbmc_project.fwupdate1";
-static constexpr char FW_UPDATE_INFO_INTERFACE[] =
-    "xyz.openbmc_project.fwupdate1.fwinfo";
-static constexpr char FW_UPDATE_SECURITY_INTERFACE[] =
-    "xyz.openbmc_project.fwupdate1.security";
+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 int FIRMWARE_BUFFER_MAX_SIZE = 32_MB;
+static constexpr size_t maxFirmwareImageSize = 32_MB;
 
-static constexpr char FIRMWARE_BUFFER_FILE[] = "/tmp/fw-download.bin";
-static bool local_download_is_active(void)
+static bool localDownloadInProgress(void)
 {
     struct stat sb;
-    if (stat(FIRMWARE_BUFFER_FILE, &sb) < 0)
+    if (stat(firmwareBufferFile, &sb) < 0)
+    {
         return false;
+    }
     return true;
 }
 
-class fw_update_status_cache
+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
     {
-        FW_STATE_INIT = 0,
-        FW_STATE_IDLE,
-        FW_STATE_DOWNLOAD,
-        FW_STATE_VERIFY,
-        FW_STATE_WRITE,
-        FW_STATE_READY,
-        FW_STATE_ERROR = 0x0f,
-        FW_STATE_AC_CYCLE_REQUIRED = 0x83,
+        fwStateInit = 0,
+        fwStateIdle,
+        fwStateDownload,
+        fwStateVerify,
+        fwStateProgram,
+        fwStateUpdateSuccess,
+        fwStateError = 0x0f,
+        fwStateAcCycleRequired = 0x83,
     };
-    uint8_t state()
+    uint8_t getState()
     {
-        if (DEBUG)
-            std::cerr << "fw-state: 0x" << std::hex << (int)_state << '\n';
-        if ((_state == FW_STATE_IDLE || _state == FW_STATE_INIT) &&
-            local_download_is_active())
+        if ((fwUpdateState == fwStateIdle || fwUpdateState == fwStateInit) &&
+            localDownloadInProgress())
         {
-            _state = FW_STATE_DOWNLOAD;
-            _percent = 0;
+            fwUpdateState = fwStateDownload;
+            progressPercent = 0;
         }
-        return _state;
+        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 _percent;
+        return progressPercent;
     }
-    std::string msg()
+    void updateActivationPercent(const std::string &objPath)
     {
-        return _msg;
-    }
-    std::string get_software_obj_path()
-    {
-        return _software_obj_path;
-    }
-    void set_software_obj_path(std::string &obj_path)
-    {
-        _software_obj_path = obj_path;
-        _state = FW_STATE_WRITE;
-        _percent = 0;
-        _match = std::make_shared<sdbusplus::bus::match::match>(
-            *_bus,
+        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(
-                _software_obj_path,
-                "xyz.openbmc_project.Software.ActivationProgress"),
+                objPath, "xyz.openbmc_project.Software.ActivationProgress"),
             [&](sdbusplus::message::message &msg) {
-                if (DEBUG)
-                    std::cerr << "propertiesChanged lambda\n";
                 std::map<std::string, ipmi::DbusVariant> props;
-                std::vector<std::string> inval;
+                std::vector<std::string> inVal;
                 std::string iface;
-                msg.read(iface, props, inval);
-                _parse_props(props);
+                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 activation_timer_timeout()
+    uint8_t activationTimerTimeout()
     {
-        std::cerr << "activation_timer_timout(): increase percentage...\n";
-        _percent = _percent + 5;
-        if (_percent >= 95)
+        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 */
-            _state = FW_STATE_READY;
+            fwUpdateState = fwStateUpdateSuccess;
         }
-        std::cerr << " _percent = " << (int)_percent << "\n";
-        return _percent;
+        return progressPercent;
     }
     /* API for changing state to ERROR  */
     void firmwareUpdateAbortState()
     {
-        unlink(FIRMWARE_BUFFER_FILE);
+        unlink(firmwareBufferFile);
         // changing the state to error
-        _state = FW_STATE_ERROR;
+        fwUpdateState = fwStateError;
     }
     void setDeferRestart(bool deferRestart)
     {
-        _deferRestart = deferRestart;
+        deferRestartState = deferRestart;
     }
     void setInhibitDowngrade(bool inhibitDowngrade)
     {
-        _inhibitDowngrade = inhibitDowngrade;
+        inhibitDowngradeState = inhibitDowngrade;
     }
     bool getDeferRestart()
     {
-        return _deferRestart;
+        return deferRestartState;
     }
     bool getInhibitDowngrade()
     {
-        return _inhibitDowngrade;
+        return inhibitDowngradeState;
     }
 
   protected:
-    void _parse_props(std::map<std::string, ipmi::DbusVariant> &properties)
-    {
-        if (DEBUG)
-            std::cerr << "propertiesChanged (" << properties.size()
-                      << " elements)";
-        for (const auto &t : properties)
-        {
-            auto key = t.first;
-            auto value = t.second;
-            if (key == "state")
-            {
-                auto state = std::get<std::string>(value);
-                if (DEBUG)
-                    std::cerr << ", state=" << state;
-                if (state == "INIT")
-                    _state = FW_STATE_INIT;
-                else if (state == "IDLE")
-                    _state = FW_STATE_IDLE;
-                else if (state == "DOWNLOAD")
-                    _state = FW_STATE_DOWNLOAD;
-                else if (state == "VERIFY")
-                    _state = FW_STATE_VERIFY;
-                else if (state == "WRITE")
-                    _state = FW_STATE_WRITE;
-                else if (state == "READY")
-                    _state = FW_STATE_READY;
-                else if (state == "ERROR")
-                    _state = FW_STATE_ERROR;
-                else if (state == "AC_CYCLE_REQUIRED")
-                    _state = FW_STATE_AC_CYCLE_REQUIRED;
-                else
-                {
-                    _state = FW_STATE_ERROR;
-                    _msg = "internal error";
-                }
-            }
-            else if (key == "percent")
-            {
-                _percent = std::get<int32_t>(value);
-                if (DEBUG)
-                    std::cerr << ", pct=" << (int)_percent;
-            }
-            else if (key == "msg")
-            {
-                _msg = std::get<std::string>(value);
-                if (DEBUG)
-                    std::cerr << ", msg='" << _msg << '\'';
-            }
-            else if (key == "Progress")
-            {
-                _percent = std::get<uint8_t>(value);
-                ;
-                if (_percent == 100)
-                    _state = FW_STATE_READY;
-            }
-        }
-        if ((_state == FW_STATE_IDLE || _state == FW_STATE_INIT) &&
-            local_download_is_active())
-        {
-            _state = FW_STATE_DOWNLOAD;
-            _percent = 0;
-        }
-        if (DEBUG)
-            std::cerr << '\n';
-    }
-
-    std::shared_ptr<sdbusplus::asio::connection> _bus;
-    std::shared_ptr<sdbusplus::bus::match::match> _match;
-    uint8_t _state = 0;
-    uint8_t _percent = 0;
-    bool _deferRestart = false;
-    bool _inhibitDowngrade = false;
-    std::string _msg;
-
-  private:
-    std::string _software_obj_path;
+    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 fw_update_status_cache fw_update_status;
+static FwUpdateStatusCache fwUpdateStatus;
+std::shared_ptr<TransferHashCheck> xferHashCheck;
 
-static std::chrono::steady_clock::time_point fw_random_number_timestamp;
-static constexpr int FW_RANDOM_NUMBER_LENGTH = 8;
-static constexpr auto FW_RANDOM_NUMBER_TTL = std::chrono::seconds(30);
-static uint8_t fw_random_number[FW_RANDOM_NUMBER_LENGTH];
-
-static ipmi_ret_t ipmi_firmware_get_fw_random_number(
-    ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
-    ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context)
+static void activateImage(const std::string &objPath)
 {
-    std::random_device rd;
-    std::default_random_engine gen(rd());
-    std::uniform_int_distribution<> dist{0, 255};
-
-    if (*data_len != 0)
+    // If flag is false  means to reboot
+    if (fwUpdateStatus.getDeferRestart() == false)
     {
-        *data_len = 0;
-        return IPMI_CC_REQ_DATA_LEN_INVALID;
+        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"));
     }
-
-    fw_random_number_timestamp = std::chrono::steady_clock::now();
-
-    uint8_t *msg_reply = static_cast<uint8_t *>(response);
-    for (int i = 0; i < FW_RANDOM_NUMBER_LENGTH; i++)
-        fw_random_number[i] = msg_reply[i] = dist(gen);
-
-    if (DEBUG)
-        std::cerr << "FW Rand Num: 0x" << std::hex << (int)msg_reply[0] << " 0x"
-                  << (int)msg_reply[1] << " 0x" << (int)msg_reply[2] << " 0x"
-                  << (int)msg_reply[3] << " 0x" << (int)msg_reply[4] << " 0x"
-                  << (int)msg_reply[5] << " 0x" << (int)msg_reply[6] << " 0x"
-                  << (int)msg_reply[7] << '\n';
-
-    *data_len = FW_RANDOM_NUMBER_LENGTH;
-
-    return IPMI_CC_OK;
+    else
+    {
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "Firmware image activation is deferred.");
+    }
+    fwUpdateStatus.setState(
+        static_cast<uint8_t>(FwUpdateStatusCache::fwStateUpdateSuccess));
 }
 
 static bool getFirmwareUpdateMode()
@@ -370,422 +513,130 @@
     }
 }
 
-/** @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
- *
- *  @parameter
- *   -  randNum - Random number(token)
- *  @returns IPMI completion code
- **/
-ipmi::RspType<> ipmiSetFirmwareUpdateMode(
-    std::array<uint8_t, FW_RANDOM_NUMBER_LENGTH> &randNum)
-{
-    /* Firmware Update Random number is valid for 30 seconds only */
-    auto timeElapsed =
-        (std::chrono::steady_clock::now() - fw_random_number_timestamp);
-    if (std::chrono::duration_cast<std::chrono::microseconds>(timeElapsed)
-            .count() > std::chrono::duration_cast<std::chrono::microseconds>(
-                           FW_RANDOM_NUMBER_TTL)
-                           .count())
-    {
-        phosphor::logging::log<phosphor::logging::level::INFO>(
-            "Firmware update random number expired.");
-        return ipmi::responseInvalidFieldRequest();
-    }
-
-    /* Validate random number */
-    for (int i = 0; i < FW_RANDOM_NUMBER_LENGTH; i++)
-    {
-        if (fw_random_number[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(FIRMWARE_BUFFER_FILE, "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(FIRMWARE_BUFFER_FILE);
-        return ipmi::responseUnspecifiedError();
-    }
-
-    return ipmi::responseSuccess();
-}
-
-/** @brief implements exit firmware update mode command
- *  @param None
- *
- *  @returns IPMI completion code
- */
-ipmi::RspType<> ipmiFirmwareExitFwUpdateMode()
-{
-
-    if (DEBUG)
-    {
-        std::cerr << "Exit FW update mode \n";
-    }
-    switch (fw_update_status.state())
-    {
-        case fw_update_status_cache::FW_STATE_INIT:
-        case fw_update_status_cache::FW_STATE_IDLE:
-            return ipmi::responseInvalidFieldRequest();
-            break;
-        case fw_update_status_cache::FW_STATE_DOWNLOAD:
-        case fw_update_status_cache::FW_STATE_VERIFY:
-            break;
-        case fw_update_status_cache::FW_STATE_WRITE:
-            break;
-        case fw_update_status_cache::FW_STATE_READY:
-        case fw_update_status_cache::FW_STATE_ERROR:
-            break;
-        case fw_update_status_cache::FW_STATE_AC_CYCLE_REQUIRED:
-            return ipmi::responseInvalidFieldRequest();
-            break;
-    }
-    fw_update_status.firmwareUpdateAbortState();
-
-    try
-    {
-        setFirmwareUpdateMode(false);
-    }
-    catch (const std::exception &e)
-    {
-        return ipmi::responseUnspecifiedError();
-    }
-
-    return ipmi::responseSuccess();
-}
-
-static void post_transfer_complete_handler(
-    std::unique_ptr<sdbusplus::bus::match::match> &fw_update_matcher);
-static bool request_start_firmware_update(const std::string &uri)
-{
-    if (DEBUG)
-        std::cerr << "request start firmware update()\n";
-
-    // 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> fw_update_matcher;
-    post_transfer_complete_handler(fw_update_matcher);
-    std::filesystem::rename(
-        uri, "/tmp/images/" +
-                 boost::uuids::to_string(boost::uuids::random_generator()()));
-    return true;
-}
-
-class transfer_hash_check
-{
-  public:
-    enum hash_check
-    {
-        CHECK_NOT_REQUESTED = 0,
-        CHECK_REQUESTED,
-        CHECK_PASSED_SHA2,
-        CHECK_RESVD1,
-        CHECK_FAILED_SHA2 = 0xe2,
-        CHECK_RESVD2 = 0xe3,
-    };
-
-  protected:
-    EVP_MD_CTX *_ctx;
-    std::vector<uint8_t> _expected;
-    enum hash_check _check;
-    bool _started;
-
-  public:
-    transfer_hash_check() : _check(CHECK_NOT_REQUESTED), _started(false)
-    {
-    }
-    ~transfer_hash_check()
-    {
-        if (_ctx)
-        {
-            EVP_MD_CTX_destroy(_ctx);
-            _ctx = NULL;
-        }
-    }
-    void init(const std::vector<uint8_t> &expected)
-    {
-        _expected = expected;
-        _check = CHECK_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 != CHECK_NOT_REQUESTED)
-                _check = CHECK_REQUESTED;
-            _ctx = EVP_MD_CTX_create();
-            EVP_DigestInit(_ctx, EVP_sha256());
-        }
-    }
-    enum hash_check check()
-    {
-        if (_check == CHECK_REQUESTED)
-        {
-            unsigned int len;
-            std::vector<uint8_t> digest(EVP_MD_size(EVP_sha256()));
-            EVP_DigestFinal(_ctx, digest.data(), &len);
-            if (digest == _expected)
-            {
-                if (DEBUG)
-                    std::cerr << "transfer sha2 check passed\n";
-                _check = CHECK_PASSED_SHA2;
-            }
-            else
-            {
-                if (DEBUG)
-                    std::cerr << "transfer sha2 check failed\n";
-                _check = CHECK_FAILED_SHA2;
-            }
-        }
-        return _check;
-    }
-    uint8_t status() const
-    {
-        return static_cast<uint8_t>(_check);
-    }
-};
-
-std::shared_ptr<transfer_hash_check> xfer_hash_check;
-
-static void activate_image(const char *obj_path)
-{
-    // If flag is false  means to reboot
-    if (fw_update_status.getDeferRestart() == false)
-    {
-
-        if (DEBUG)
-        {
-            std::cerr << "activateImage()...\n";
-            std::cerr << "obj_path = " << obj_path << "\n";
-        }
-        phosphor::logging::log<phosphor::logging::level::INFO>(
-            "activating Image: ",
-            phosphor::logging::entry("OBJPATH =%s", obj_path));
-        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: activate_image failed");
-                    return;
-                }
-            },
-            "xyz.openbmc_project.Software.BMC.Updater", obj_path,
-            "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.");
-    }
-}
-
-static void post_transfer_complete_handler(
-    std::unique_ptr<sdbusplus::bus::match::match> &fw_update_matcher)
+static void postTransferCompleteHandler(
+    std::unique_ptr<sdbusplus::bus::match::match> &fwUpdateMatchSignal)
 {
     // Setup timer for watching signal
     static phosphor::Timer timer(
-        [&fw_update_matcher]() { fw_update_matcher = nullptr; });
+        [&fwUpdateMatchSignal]() { fwUpdateMatchSignal = nullptr; });
 
-    static phosphor::Timer activation_status_timer([]() {
-        if (fw_update_status.activation_timer_timeout() >= 95)
+    static phosphor::Timer activationStatusTimer([]() {
+        if (fwUpdateStatus.activationTimerTimeout() >= 95)
         {
-            activation_status_timer.stop();
+            activationStatusTimer.stop();
+            fwUpdateStatus.setState(
+                static_cast<uint8_t>(FwUpdateStatusCache::fwStateVerify));
         }
     });
 
     timer.start(std::chrono::microseconds(5000000), false);
 
     // callback function for capturing signal
-    auto callback = [&fw_update_matcher](sdbusplus::message::message &m) {
-        if (DEBUG)
-            std::cerr << "[complete] Match fired\n";
+    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>>>>>
-            interfaces_properties;
-
-        sdbusplus::message::object_path obj_path;
+            intfPropsPair;
+        sdbusplus::message::object_path objPath;
 
         try
         {
-            m.read(obj_path, interfaces_properties); // Read in the object path
-                                                     // that was just created
+            m.read(objPath, intfPropsPair); // Read in the object path
+                                            // that was just created
         }
-        catch (std::exception &e)
+        catch (const std::exception &e)
         {
-            std::cerr
-                << "[complete] Failed at post_transfer_complete-handler : "
-                << e.what() << "\n";
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "Exception caught in reading created object path.");
+            return;
         }
         // constructing response message
-        if (DEBUG)
-            std::cerr << "[complete] obj path = " << obj_path.str << "\n";
-        for (auto &interface : interfaces_properties)
+        phosphor::logging::log<phosphor::logging::level::INFO>(
+            "New Interface Added.",
+            phosphor::logging::entry("OBJPATH=%s", objPath.str.c_str()));
+        for (auto &interface : intfPropsPair)
         {
-            if (DEBUG)
-                std::cerr << "[complete] interface = " << interface.first
-                          << "\n";
-
             if (interface.first == "xyz.openbmc_project.Software.Activation")
             {
-                // cancel timer only when
-                // xyz.openbmc_project.Software.Activation interface is
-                // added
+                // 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;
 
-                if (DEBUG)
-                    std::cerr << "[complete] Attempt to cancel timer...\n";
+                phosphor::logging::log<phosphor::logging::level::INFO>(
+                    "Start activationStatusTimer for status.");
                 try
                 {
                     timer.stop();
-                    activation_status_timer.start(
+                    activationStatusTimer.start(
                         std::chrono::microseconds(3000000), true);
                 }
-                catch (std::exception &e)
+                catch (const std::exception &e)
                 {
-                    std::cerr << "[complete] cancel timer error: " << e.what()
-                              << "\n";
+                    phosphor::logging::log<phosphor::logging::level::ERR>(
+                        "Exception caught in start activationStatusTimer.",
+                        phosphor::logging::entry("ERROR=%s", e.what()));
                 }
 
-                fw_update_status.set_software_obj_path(obj_path.str);
-                activate_image(obj_path.str.c_str());
-                if (DEBUG)
-                    std::cerr << "[complete] returned from activeImage()\n";
-
-                fw_update_matcher = nullptr;
+                fwUpdateStatus.updateActivationPercent(objPath.str);
+                activateImage(objPath.str);
             }
         }
     };
 
     // Adding matcher
-    fw_update_matcher = std::make_unique<sdbusplus::bus::match::match>(
+    fwUpdateMatchSignal = std::make_unique<sdbusplus::bus::match::match>(
         *getSdBus(),
         "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
         "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
         callback);
 }
-
-class MappedFile
+static bool startFirmwareUpdate(const std::string &uri)
 {
-  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;
-    }
+    // 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;
+}
 
-    ~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;
-};
-
-static int transfer_from_file(const std::string &uri, bool move = true)
+static int transferImageFromFile(const std::string &uri, bool move = true)
 {
     std::error_code ec;
-    if (DEBUG)
-        std::cerr << "transfer_from_file(" << uri << ")\n";
+    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, FIRMWARE_BUFFER_FILE, ec);
+        std::filesystem::rename(uri, firmwareBufferFile, ec);
     }
     else
     {
-        std::filesystem::copy(uri, FIRMWARE_BUFFER_FILE,
+        std::filesystem::copy(uri, firmwareBufferFile,
                               std::filesystem::copy_options::overwrite_existing,
                               ec);
     }
-    if (xfer_hash_check)
+    if (xferHashCheck)
     {
         MappedFile mappedfw(uri);
-        xfer_hash_check->hash(
+        xferHashCheck->hash(
             {mappedfw.data(), mappedfw.data() + mappedfw.size()});
     }
     if (ec.value())
     {
-        std::cerr << "cp/mv returns: " << ec.message() << "(" << ec.value()
-                  << ")\n";
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Image copy failed.");
     }
     return ec.value();
 }
@@ -798,265 +649,116 @@
     return execProg.exit_code();
 }
 
-constexpr char USB_CTRL_PATH[] = "/usr/bin/usb-ctrl";
-constexpr char FWUPDATE_MOUNT_POINT[] = "/tmp/usb-fwupd.mnt";
-constexpr char FWUPDATE_USB_VOL_IMG[] = "/tmp/usb-fwupd.img";
-constexpr char FWUPDATE_USB_DEV_NAME[] = "fw-usb-mass-storage-dev";
-constexpr size_t fwPathMaxLength = 255;
-static int transfer_from_usb(const std::string &uri)
+static int transferImageFromUsb(const std::string &uri)
 {
     int ret, sysret;
     char fwpath[fwPathMaxLength];
-    if (DEBUG)
-        std::cerr << "transfer_from_usb(" << uri << ")\n";
-    ret = executeCmd(USB_CTRL_PATH, "mount", FWUPDATE_USB_VOL_IMG,
-                     FWUPDATE_MOUNT_POINT);
+    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(FWUPDATE_MOUNT_POINT) + "/" + uri;
-    ret = transfer_from_file(usb_path, false);
+    std::string usb_path = std::string(fwUpdateMountPoint) + "/" + uri;
+    ret = transferImageFromFile(usb_path, false);
 
-    executeCmd(USB_CTRL_PATH, "cleanup", FWUPDATE_USB_VOL_IMG,
-               FWUPDATE_MOUNT_POINT);
+    executeCmd(usbCtrlPath, "cleanup", fwUpdateUsbVolImage, fwUpdateMountPoint);
     return ret;
 }
 
-static bool transfer_firmware_from_uri(const std::string &uri)
+static bool transferFirmwareFromUri(const std::string &uri)
 {
-    static constexpr char FW_URI_FILE[] = "file://";
-    static constexpr char FW_URI_USB[] = "usb://";
-    if (DEBUG)
-        std::cerr << "transfer_firmware_from_uri(" << uri << ")\n";
-    if (boost::algorithm::starts_with(uri, FW_URI_FILE))
+    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(FW_URI_FILE) - 1);
-        if (fname != FIRMWARE_BUFFER_FILE)
+        std::string fname = uri.substr(sizeof(fwUriFile) - 1);
+        if (fname != firmwareBufferFile)
         {
-            return 0 == transfer_from_file(fname);
+            return 0 == transferImageFromFile(fname);
         }
         return true;
     }
-    if (boost::algorithm::starts_with(uri, FW_URI_USB))
+    if (boost::algorithm::starts_with(uri, fwUriUsb))
     {
-        std::string fname = uri.substr(sizeof(FW_URI_USB) - 1);
-        return 0 == transfer_from_usb(fname);
+        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 int usb_get_status()
+static bool getUsbStatus()
 {
-    static constexpr char usb_gadget_base[] = "/sys/kernel/config/usb_gadget/";
-    auto usb_device =
-        std::filesystem::path(usb_gadget_base) / FWUPDATE_USB_DEV_NAME;
-    std::error_code ec;
-    return std::filesystem::exists(usb_device, ec) && !ec;
+    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 usb_attach_device()
+static int attachUsbDevice()
 {
-    if (usb_get_status())
+    if (getUsbStatus())
     {
         return 1;
     }
-    int ret =
-        executeCmd(USB_CTRL_PATH, "setup", FWUPDATE_USB_VOL_IMG,
-                   std::to_string(FIRMWARE_BUFFER_MAX_SIZE / 1_MB).c_str());
+    int ret = executeCmd(usbCtrlPath, "setup", fwUpdateUsbVolImage,
+                         std::to_string(maxFirmwareImageSize / 1_MB).c_str());
     if (!ret)
     {
-        ret = executeCmd(USB_CTRL_PATH, "insert", FWUPDATE_USB_DEV_NAME,
-                         FWUPDATE_USB_VOL_IMG);
+        ret = executeCmd(usbCtrlPath, "insert", fwUpdateUSBDevName,
+                         fwUpdateUsbVolImage);
     }
     return ret;
 }
 
 /* Eject the USB-mass-storage device status: success => 0, failure => non-0 */
-static int usb_detach_device()
+static int detachUsbDevice()
 {
-    if (!usb_get_status())
+    if (!getUsbStatus())
     {
         return 1;
     }
-    return executeCmd(USB_CTRL_PATH, "eject", FWUPDATE_USB_DEV_NAME);
+    return executeCmd(usbCtrlPath, "eject", fwUpdateUSBDevName);
 }
-
-constexpr uint8_t controls_init = 0x00;
-constexpr uint8_t controls_transfer_started = 0x01;
-constexpr uint8_t controls_transfer_completed = 0x02;
-constexpr uint8_t controls_transfer_aborted = 0x04;
-constexpr uint8_t controls_usb_attached = 0x08;
-
-struct fw_update_control_request
+static uint8_t getActiveBootImage(ipmi::Context::ptr ctx)
 {
-    enum knob
+    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)
     {
-        CTRL_GET = 0,
-        CTRL_XFER_START,
-        CTRL_XFER_COMPLETE,
-        CTRL_XFER_ABORT,
-        CTRL_SET_FILENAME,
-        CTRL_USB_ATTACH,
-        CTRL_USB_DETACH,
-    } __attribute__((packed));
-    enum knob control;
-    uint8_t nlen;
-    char filename[fwPathMaxLength];
-} __attribute__((packed));
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Failed to read the bootcmd value");
+        return ipmi::ccUnspecifiedError;
+    }
 
-static ipmi_ret_t ipmi_firmware_control(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
-                                        ipmi_request_t request,
-                                        ipmi_response_t response,
-                                        ipmi_data_len_t data_len,
-                                        ipmi_context_t context)
-{
-    static std::string fw_xfer_uri;
-
-    if (DEBUG)
-        std::cerr << "FW update control\n";
-    *data_len = 0;
-
-    static uint8_t controls = controls_init;
-    ipmi_ret_t rc = IPMI_CC_OK;
-    auto ctrl_req = reinterpret_cast<fw_update_control_request *>(request);
-    auto ctrl_resp = reinterpret_cast<uint8_t *>(response);
-
-    if (usb_get_status())
+    /* cheking for secondary FitImage Address 22480000  */
+    if (value.find(secondaryFitImageStartAddr) != std::string::npos)
     {
-        controls |= controls_usb_attached;
+        bootImage = secondaryImage;
     }
     else
     {
-        controls &= ~controls_usb_attached;
+        bootImage = primaryImage;
     }
 
-    switch (ctrl_req->control)
-    {
-        case fw_update_control_request::CTRL_GET:
-            break;
-        case fw_update_control_request::CTRL_XFER_START:
-        {
-            controls |= controls_transfer_started;
-            // reset buffer to empty (truncate file)
-            std::ofstream out(FIRMWARE_BUFFER_FILE,
-                              std::ofstream::binary | std::ofstream::trunc);
-            fw_xfer_uri = std::string("file://") + FIRMWARE_BUFFER_FILE;
-            if (xfer_hash_check)
-            {
-                xfer_hash_check->clear();
-            }
-#ifdef INTEL_PFR_ENABLED
-            imgLength = 0;
-            imgType = 0;
-            block0Mapped = false;
-#endif
-            if (DEBUG)
-                std::cerr << "transfer start\n";
-        }
-        break;
-        case fw_update_control_request::CTRL_XFER_COMPLETE:
-        {
-            if (usb_get_status())
-            {
-                rc = IPMI_CC_REQ_INVALID_PHASE;
-            }
-            // finish transfer based on URI
-            if (!transfer_firmware_from_uri(fw_xfer_uri))
-            {
-                rc = IPMI_CC_UNSPECIFIED_ERROR;
-                break;
-            }
-            // transfer complete
-            if (xfer_hash_check)
-            {
-                if (transfer_hash_check::CHECK_PASSED_SHA2 !=
-                    xfer_hash_check->check())
-                {
-                    if (DEBUG)
-                        std::cerr << "xfer_hash_check returns not "
-                                     "CHECK_PASSED_SHA2\n";
-                    rc = IPMI_CC_UNSPECIFIED_ERROR;
-                    break;
-                }
-            }
-            // start the request
-            if (!request_start_firmware_update(FIRMWARE_BUFFER_FILE))
-            {
-                if (DEBUG)
-                    std::cerr
-                        << "request_start_firmware_update returns failure\n";
-                rc = IPMI_CC_UNSPECIFIED_ERROR;
-            }
-            if (rc == IPMI_CC_OK)
-            {
-                controls |= controls_transfer_completed;
-            }
-        }
-        break;
-        case fw_update_control_request::CTRL_XFER_ABORT:
-            if (DEBUG)
-                std::cerr << "send abort request\n";
-            if (usb_get_status())
-            {
-                if (0 != usb_detach_device())
-                {
-                    rc = IPMI_CC_USB_ATTACH_FAIL;
-                }
-            }
-            fw_update_status.firmwareUpdateAbortState();
-            controls |= controls_transfer_aborted;
-            break;
-        case fw_update_control_request::CTRL_SET_FILENAME:
-            fw_xfer_uri.clear();
-            fw_xfer_uri.insert(0, ctrl_req->filename, ctrl_req->nlen);
-            break;
-        case fw_update_control_request::CTRL_USB_ATTACH:
-            if (usb_get_status())
-            {
-                rc = IPMI_CC_INVALID_FIELD_REQUEST;
-            }
-            else if (0 != usb_attach_device())
-            {
-                rc = IPMI_CC_USB_ATTACH_FAIL;
-            }
-            else
-            {
-                rc = IPMI_CC_OK;
-            }
-            break;
-        case fw_update_control_request::CTRL_USB_DETACH:
-            if (!usb_get_status())
-            {
-                rc = IPMI_CC_INVALID_FIELD_REQUEST;
-            }
-            if (0 != usb_detach_device())
-            {
-                rc = IPMI_CC_USB_ATTACH_FAIL;
-            }
-            else
-            {
-                rc = IPMI_CC_OK;
-            }
-            break;
-        default:
-            if (DEBUG)
-                std::cerr << "control byte " << std::hex << ctrl_req->control
-                          << " unknown\n";
-            rc = IPMI_CC_INVALID_FIELD_REQUEST;
-            break;
-    }
-
-    if (rc == IPMI_CC_OK)
-    {
-        *ctrl_resp = controls;
-        *data_len = sizeof(*ctrl_resp);
-    }
-
-    return rc;
+    return bootImage;
 }
 
 #ifdef INTEL_PFR_ENABLED
@@ -1142,434 +844,16 @@
 
     return ipmi::responseSuccess(fwVerInfoList.size(), fwVerInfoList);
 }
-#endif
-
-struct fw_security_revision_info
+using fwSecurityVersionInfoType = std::tuple<uint8_t,  // ID Tag
+                                             uint8_t,  // BKC Version
+                                             uint8_t>; // SVN Version
+ipmi::RspType<uint8_t, std::vector<fwSecurityVersionInfoType>>
+    ipmiGetFwSecurityVersionInfo()
 {
-    uint8_t id_tag;
-    uint16_t sec_rev;
-} __attribute__((packed));
-
-static ipmi_ret_t ipmi_firmware_get_fw_security_revision(
-    ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
-    ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context)
-{
-    if (DEBUG)
-        std::cerr << "Get FW security revision info\n";
-
-    // Byte 1 - Count (N) Number of devices data is being returned for.
-    // Byte 2 - ID Tag 00 – reserved 01 – BMC Active Image 02 – BBU Active Image
-    //                 03 – BMC Backup Image 04 – BBU Backup Image 05 – BBR
-    //                 Image
-    // Byte 3 - Major Version Number
-    // Byte 4 - Minor Version Number
-    // Bytes 5:8 - Build Number
-    // Bytes 9:12 - Build Timestamp Format: LSB first, same format as SEL
-    // timestamp
-    // Bytes 13:16 - Update Timestamp
-    // Bytes - 17:(15xN) - Repeat of 2 through 16
-
-    uint8_t count = 0;
-    auto ret_count = reinterpret_cast<uint8_t *>(response);
-    auto info =
-        reinterpret_cast<struct fw_security_revision_info *>(ret_count + 1);
-
-    std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
-    for (uint8_t id_tag = 1; id_tag < 6; id_tag++)
-    {
-        const char *fw_path;
-        switch (id_tag)
-        {
-            case 1:
-                fw_path = FW_UPDATE_ACTIVE_INFO_PATH;
-                break;
-            case 2:
-                fw_path = FW_UPDATE_BACKUP_INFO_PATH;
-                break;
-            case 3:
-            case 4:
-            case 5:
-                continue; // skip for now
-                break;
-        }
-        auto method =
-            bus->new_method_call(FW_UPDATE_SERVER_DBUS_NAME, fw_path,
-                                 "org.freedesktop.DBus.Properties", "GetAll");
-        method.append(FW_UPDATE_INFO_INTERFACE, "security_version");
-        ipmi::DbusVariant sec_rev;
-        try
-        {
-            auto reply = bus->call(method);
-
-            if (reply.is_method_error())
-                continue;
-
-            reply.read(sec_rev);
-        }
-        catch (sdbusplus::exception::SdBusError &e)
-        {
-            std::cerr << "SDBus Error: " << e.what();
-            return IPMI_CC_UNSPECIFIED_ERROR;
-        }
-
-        info->id_tag = id_tag;
-        info->sec_rev = std::get<int>(sec_rev);
-        count++;
-        info++;
-    }
-    *ret_count = count;
-
-    // Status code.
-    ipmi_ret_t rc = IPMI_CC_OK;
-    *data_len = sizeof(count) + count * sizeof(*info);
-
-    return rc;
+    // TODO: Need to add support.
+    return ipmi::responseInvalidCommand();
 }
 
-struct fw_channel_size
-{
-    uint8_t channel_id;
-    uint32_t channel_size;
-} __attribute__((packed));
-
-enum
-{
-    CHANNEL_RESVD = 0,
-    CHANNEL_KCS,
-    CHANNEL_RMCP_PLUS,
-    CHANNEL_USB_DATA,
-    CHANNEL_USB_MASS_STORAGE,
-} channel_transfer_type;
-
-static constexpr uint8_t channelListSize = 2;
-/** @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 uint8_t KCSMaxBufSize = 128;
-    constexpr uint32_t RMCPPLUSMaxBufSize = 50 * 1024;
-    if (DEBUG)
-        std::cerr << "Get FW max transfer size\n";
-    // Byte 1 - Count (N) Number of devices data is being returned for.
-    // Byte 2 - ID Tag 00 – reserved 01 – kcs 02 – rmcp+,
-    //                 03 – usb data, 04 – usb mass storage
-    // 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 = {{{CHANNEL_KCS, KCSMaxBufSize},
-                        {CHANNEL_RMCP_PLUS, RMCPPLUSMaxBufSize}}};
-    return ipmi::responseSuccess(channelListSize, channelList);
-}
-
-enum
-{
-    EXEC_CTX_RESVD = 0,
-    EXEC_CTX_FULL_LINUX = 0x10,
-    EXEC_CTX_SAFE_MODE_LINUX = 0x11,
-} bmc_execution_context;
-
-struct fw_execution_context
-{
-    uint8_t context;
-    uint8_t image_selection;
-} __attribute__((packed));
-
-static ipmi_ret_t ipmi_firmware_get_fw_execution_context(
-    ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
-    ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context)
-{
-    if (DEBUG)
-        std::cerr << "Get FW execution context\n";
-
-    // Byte 1 - execution context
-    //          0x10 - full linux stack, 0x11 - safe-mode linux stack
-    // Byte 2 - current image selection
-    //          1 - primary, 2 - secondary
-
-    auto info = reinterpret_cast<struct fw_execution_context *>(response);
-    info->context = EXEC_CTX_FULL_LINUX;
-
-    info->image_selection = getActiveBootImage();
-
-    // Status code.
-    ipmi_ret_t rc = IPMI_CC_OK;
-    *data_len = sizeof(*info);
-
-    return rc;
-}
-
-uint8_t getActiveBootImage(void)
-{
-    // 0x01 -  primaryImage
-    constexpr uint8_t primaryImage = 0x01;
-    // 0x02 -  secondaryImage
-    constexpr uint8_t secondaryImage = 0x02;
-    uint8_t bootImage = primaryImage;
-
-    std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
-    auto method = bus->new_method_call(
-        "xyz.openbmc_project.U_Boot.Environment.Manager",
-        "/xyz/openbmc_project/u_boot/environment/mgr",
-        "xyz.openbmc_project.U_Boot.Environment.Manager", "Read");
-    method.append("bootcmd");
-    std::string value;
-    try
-    {
-        auto reply = bus->call(method);
-        reply.read(value);
-    }
-    catch (sdbusplus::exception::SdBusError &e)
-    {
-        std::cerr << "SDBus Error: " << e.what();
-        return IPMI_CC_UNSPECIFIED_ERROR;
-    }
-    /* cheking for secondary FitImage Address 22480000  */
-    if (value.find(secondaryFitImageStartAddr) != std::string::npos)
-    {
-        bootImage = secondaryImage;
-    }
-    else
-    {
-        bootImage = primaryImage;
-    }
-
-    return bootImage;
-}
-/** @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
-              >
-    ipmiFrmwareGetStatus()
-
-{
-    if (DEBUG)
-        std::cerr << "Get FW update status\n";
-    // 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 = fw_update_status.state();
-    uint8_t percent = fw_update_status.percent();
-    uint8_t check = xfer_hash_check ? xfer_hash_check->status() : 0;
-
-    // Status code.
-    return ipmi::responseSuccess(status, percent, check);
-}
-
-static constexpr uint8_t FW_UPDATE_OPTIONS_NO_DOWNREV = (1 << 0);
-static constexpr uint8_t FW_UPDATE_OPTIONS_DEFER_RESTART = (1 << 1);
-static constexpr uint8_t FW_UPDATE_OPTIONS_SHA2_CHECK = (1 << 2);
-static constexpr uint8_t FW_UPDATE_OPTIONS_RESVD1 = (1 << 3);
-struct fw_update_options_request
-{
-    uint8_t mask;
-    uint8_t options;
-} __attribute__((packed));
-
-uint32_t fw_update_options = 0;
-static ipmi_ret_t ipmi_firmware_update_options(
-    ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
-    ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context)
-{
-    if (DEBUG)
-        std::cerr << "Get/set FW update options\n";
-
-    // request:
-    // Byte 1 - mask
-    // Byte 2 - options
-    // Byte 3-34 - optional integrity check expected value
-    // response:
-    // Byte 1 - set options
-
-    auto fw_options =
-        reinterpret_cast<struct fw_update_options_request *>(request);
-
-    const char *path = FW_UPDATE_SERVER_INFO_PATH;
-    const char *iface = FW_UPDATE_SECURITY_INTERFACE;
-    if ((fw_options->mask & FW_UPDATE_OPTIONS_NO_DOWNREV) &&
-        (fw_options->options & FW_UPDATE_OPTIONS_NO_DOWNREV) !=
-            (fw_update_options & FW_UPDATE_OPTIONS_NO_DOWNREV))
-    {
-        if (fw_options->options & FW_UPDATE_OPTIONS_NO_DOWNREV)
-        {
-            fw_update_options |= FW_UPDATE_OPTIONS_NO_DOWNREV;
-            /*setting flag to flase for deferring downgrade support*/
-            fw_update_status.setInhibitDowngrade(true);
-        }
-        else
-        {
-            fw_update_options &= ~FW_UPDATE_OPTIONS_NO_DOWNREV;
-            /*setting flag to true for downgrade support*/
-            fw_update_status.setInhibitDowngrade(false);
-        }
-    }
-    if ((fw_options->mask & FW_UPDATE_OPTIONS_DEFER_RESTART) &&
-        (fw_options->options & FW_UPDATE_OPTIONS_DEFER_RESTART) !=
-            (fw_update_options & FW_UPDATE_OPTIONS_DEFER_RESTART))
-    {
-        if (fw_options->options & FW_UPDATE_OPTIONS_DEFER_RESTART)
-        {
-            fw_update_options |= FW_UPDATE_OPTIONS_DEFER_RESTART;
-            /* setting flag to true to stop image activation */
-            fw_update_status.setDeferRestart(true);
-        }
-        else
-        {
-            /* setting flag to false for image activation */
-            fw_update_options &= ~FW_UPDATE_OPTIONS_DEFER_RESTART;
-            fw_update_status.setDeferRestart(false);
-        }
-    }
-    if (fw_options->mask & FW_UPDATE_OPTIONS_SHA2_CHECK)
-    {
-        auto hash_size = EVP_MD_size(EVP_sha256());
-        if (fw_options->options & FW_UPDATE_OPTIONS_SHA2_CHECK)
-        {
-            if (*data_len != (sizeof(*fw_options) + hash_size))
-            {
-                *data_len = 0;
-                return IPMI_CC_REQ_DATA_LEN_INVALID;
-            }
-            xfer_hash_check = std::make_shared<transfer_hash_check>();
-            auto exp_hash = reinterpret_cast<uint8_t *>(fw_options + 1);
-            xfer_hash_check->init({exp_hash, exp_hash + hash_size});
-            fw_update_options |= FW_UPDATE_OPTIONS_SHA2_CHECK;
-        }
-        else
-        {
-            fw_update_options &= ~FW_UPDATE_OPTIONS_SHA2_CHECK;
-            // delete the xfer_hash_check object
-            xfer_hash_check.reset();
-        }
-    }
-    auto options_rsp = reinterpret_cast<uint8_t *>(response);
-    *options_rsp = fw_update_options;
-
-    if (DEBUG)
-        std::cerr << "current fw_update_options = " << std::hex
-                  << fw_update_options << '\n';
-    // Status code.
-    *data_len = sizeof(*options_rsp);
-    return IPMI_CC_OK;
-}
-
-struct fw_cert_info
-{
-    uint16_t cert_len;
-    uint64_t serial;
-    uint8_t subject_len;
-    char subject[255];
-} __attribute__((packed));
-
-static ipmi_ret_t ipmi_firmware_get_root_cert_info(
-    ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
-    ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context)
-{
-    if (DEBUG)
-        std::cerr << "Get FW root cert info\n";
-
-    // request:
-    // Byte 1 - certificate ID: request which certificate (ignored)
-
-    // response:
-    // Byte 1-2  - certificate length (little endian)
-    // Byte 3-10 - serial number (little endian)
-    // Byte 11   - subject length
-    // Byte 12-N - subject data
-
-    auto cert_info = reinterpret_cast<struct fw_cert_info *>(response);
-    std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
-    auto method = bus->new_method_call(
-        FW_UPDATE_SERVER_DBUS_NAME, FW_UPDATE_SERVER_INFO_PATH,
-        "org.freedesktop.DBus.Properties", "GetAll");
-    method.append(FW_UPDATE_SECURITY_INTERFACE);
-    std::string subject;
-    uint64_t serial;
-    std::string cert;
-    try
-    {
-        auto reply = bus->call(method);
-
-        std::vector<std::pair<std::string, ipmi::DbusVariant>> properties;
-        reply.read(properties);
-
-        for (const auto &t : properties)
-        {
-            auto key = t.first;
-            auto value = t.second;
-            if (key == "certificate_subject")
-            {
-                subject = std::get<std::string>(value);
-            }
-            else if (key == "cetificate_serial")
-            {
-                serial = std::get<uint64_t>(value);
-            }
-            else if (key == "certificate")
-            {
-                cert = std::get<std::string>(value);
-            }
-        }
-    }
-    catch (sdbusplus::exception::SdBusError &e)
-    {
-        std::cerr << "SDBus Error: " << e.what();
-        return IPMI_CC_UNSPECIFIED_ERROR;
-    }
-
-    cert_info->cert_len = cert.size();
-    cert_info->serial = serial;
-    // truncate subject so it fits in the 255-byte array (if necessary)
-    if (subject.size() > sizeof(cert_info->subject))
-        subject.resize(sizeof(cert_info->subject));
-    cert_info->subject_len = subject.size();
-    std::copy(subject.begin(), subject.end(), cert_info->subject);
-
-    // Status code.
-    ipmi_ret_t rc = IPMI_CC_OK;
-    // make sure to account for the *actual* size of the subject
-    *data_len = sizeof(*cert_info) - sizeof(cert_info->subject) +
-                cert_info->subject_len;
-
-    return rc;
-}
-
-#ifdef INTEL_PFR_ENABLED
-enum class FwGetRootCertDataTag : uint8_t
-{
-    activeRootKey = 1,
-    recoveryRootKey,
-    activeCSK,
-    recoveryCSK,
-};
-
-static constexpr char *bmcActivePfmMTDDev = "/dev/mtd/pfm";
-static constexpr 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;
-
 ipmi::RspType<std::array<uint8_t, certKeyLen>,
               std::optional<std::array<uint8_t, cskSignatureLen>>>
     ipmiGetFwRootCertData(uint8_t certId)
@@ -1637,7 +921,440 @@
 
     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;
+    constexpr size_t ipmbMaxBufSize = 4 * 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::ipmb), ipmbMaxBufSize},
+             {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.
+ *
+ *  @parameter : None
+ *  @returns IPMI completion code along with
+ *   - random number
+ **/
+ipmi::RspType<std::array<uint8_t, fwRandomNumLength>>
+    ipmiGetFwUpdateRandomNumber()
+{
+    phosphor::logging::log<phosphor::logging::level::INFO>(
+        "Generate FW update random number");
+    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
+ *
+ *  @parameter
+ *   -  randNum - Random number(token)
+ *  @returns IPMI completion code
+ **/
+ipmi::RspType<>
+    ipmiSetFirmwareUpdateMode(std::array<uint8_t, fwRandomNumLength> &randNum)
+{
+    phosphor::logging::log<phosphor::logging::level::INFO>(
+        "Start FW update mode");
+    /* 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()
+{
+    phosphor::logging::log<phosphor::logging::level::INFO>(
+        "Exit FW update mode");
+    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
+ *  @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 uint8_t controlReq,
+                                    const std::optional<std::string> &fileName)
+{
+    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(
+    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 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)
@@ -1650,14 +1367,14 @@
         return ipmi::responseReqDataLenInvalid();
     }
 
-    if (fw_update_status.state() != fw_update_status_cache::FW_STATE_DOWNLOAD)
+    if (fwUpdateStatus.getState() != FwUpdateStatusCache::fwStateDownload)
     {
-        phosphor::logging::log<phosphor::logging::level::DEBUG>(
+        phosphor::logging::log<phosphor::logging::level::ERR>(
             "Invalid firmware update state.");
         return ipmi::response(ccCmdNotSupportedInPresentState);
     }
 
-    std::ofstream out(FIRMWARE_BUFFER_FILE,
+    std::ofstream out(firmwareBufferFile,
                       std::ofstream::binary | std::ofstream::app);
     if (!out)
     {
@@ -1668,7 +1385,7 @@
 
     uint64_t fileDataLen = out.tellp();
 
-    if ((fileDataLen + writeDataLen) > FIRMWARE_BUFFER_MAX_SIZE)
+    if ((fileDataLen + writeDataLen) > maxFirmwareImageSize)
     {
         phosphor::logging::log<phosphor::logging::level::DEBUG>(
             "Firmware image size exceeds the limit");
@@ -1679,9 +1396,9 @@
     out.write(data, writeDataLen);
     out.close();
 
-    if (xfer_hash_check)
+    if (xferHashCheck)
     {
-        xfer_hash_check->hash(writeData);
+        xferHashCheck->hash(writeData);
     }
 
 #ifdef INTEL_PFR_ENABLED
@@ -1704,7 +1421,7 @@
     {
         struct PFRImageBlock0 block0Data = {0};
 
-        std::ifstream inFile(FIRMWARE_BUFFER_FILE,
+        std::ifstream inFile(firmwareBufferFile,
                              std::ios::binary | std::ios::in);
         inFile.read(reinterpret_cast<char *>(&block0Data), sizeof(block0Data));
         inFile.close();
@@ -1728,129 +1445,81 @@
     return ipmi::responseSuccess(writeDataLen);
 }
 
-struct intc_app_get_buffer_size_resp
-{
-    uint8_t kcs_size;
-    uint8_t ipmb_size;
-} __attribute__((packed));
-
-static constexpr int KCS_MAX_BUFFER_SIZE = 63;
-static constexpr int IPMB_MAX_BUFFER_SIZE = 128;
-static ipmi_ret_t ipmi_intel_app_get_buffer_size(
-    ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
-    ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context)
-{
-    auto msg_reply =
-        reinterpret_cast<intc_app_get_buffer_size_resp *>(response);
-    // for now this is hard coded; really this number is dependent on
-    // the BMC kcs driver as well as the host kcs driver....
-    // we can't know the latter.
-    msg_reply->kcs_size = KCS_MAX_BUFFER_SIZE / 4;
-    msg_reply->ipmb_size = IPMB_MAX_BUFFER_SIZE / 4;
-    *data_len = sizeof(*msg_reply);
-
-    return IPMI_CC_OK;
-}
-
-static constexpr ipmi_cmd_t IPMI_CMD_FW_GET_FW_VERSION_INFO = 0x20;
-static constexpr ipmi_cmd_t IPMI_CMD_FW_GET_FW_SEC_VERSION_INFO = 0x21;
-static constexpr ipmi_cmd_t IPMI_CMD_FW_GET_FW_UPD_CHAN_INFO = 0x22;
-static constexpr ipmi_cmd_t IPMI_CMD_FW_GET_BMC_EXEC_CTX = 0x23;
-static constexpr ipmi_cmd_t IPMI_CMD_FW_GET_ROOT_CERT_INFO = 0x24;
-static constexpr ipmi_cmd_t IPMI_CMD_FW_GET_FW_UPDATE_RAND_NUM = 0x26;
-static constexpr ipmi_cmd_t IPMI_CMD_FW_SET_FW_UPDATE_MODE = 0x27;
-static constexpr ipmi_cmd_t cmdFirmwareExitFirmwareUpdateMode = 0x28;
-static constexpr ipmi_cmd_t IPMI_CMD_FW_UPDATE_CONTROL = 0x29;
-static constexpr ipmi_cmd_t IPMI_CMD_FW_GET_STATUS = 0x2a;
-static constexpr ipmi_cmd_t IPMI_CMD_FW_SET_FW_UPDATE_OPTIONS = 0x2b;
-static constexpr ipmi_cmd_t IPMI_CMD_FW_GET_TIMESTAMP = 0x2d;
-static constexpr ipmi_cmd_t IPMI_CMD_FW_GET_UPDATE_ERR_MSG = 0xe0;
-static constexpr ipmi_cmd_t IPMI_CMD_FW_GET_REMOTE_FW_INFO = 0xf0;
-
-static constexpr ipmi_netfn_t NETFUN_INTC_APP = 0x30;
-static constexpr ipmi_cmd_t IPMI_CMD_INTC_GET_BUFFER_SIZE = 0x66;
-
-static void register_netfn_firmware_functions()
+static void registerFirmwareFunctions()
 {
     // guarantee that we start with an already timed out timestamp
-    fw_random_number_timestamp =
-        std::chrono::steady_clock::now() - FW_RANDOM_NUMBER_TTL;
+    fwRandomNumGenTs =
+        std::chrono::steady_clock::now() - fwRandomNumExpirySeconds;
+    fwUpdateStatus.setState(
+        static_cast<uint8_t>(FwUpdateStatusCache::fwStateInit));
 
-    unlink(FIRMWARE_BUFFER_FILE);
-
-    // <Get BT Interface Capabilities>
-    if (DEBUG)
-        std::cerr << "Registering firmware update commands\n";
+    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);
-#endif
+
     // get firmware security version information
-    ipmi_register_callback(NETFUN_FIRMWARE, IPMI_CMD_FW_GET_FW_SEC_VERSION_INFO,
-                           NULL, ipmi_firmware_get_fw_security_revision,
-                           PRIVILEGE_ADMIN);
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnFirmware,
+                          ipmi::firmware::cmdGetFwSecurityVersionInfo,
+                          ipmi::Privilege::Admin, ipmiGetFwSecurityVersionInfo);
 
-    // get channel information (max transfer sizes)
-    ipmi::registerHandler(ipmi::prioOemBase, NETFUN_FIRMWARE,
-                          IPMI_CMD_FW_GET_FW_UPD_CHAN_INFO,
-                          ipmi::Privilege::Admin, ipmiFirmwareMaxTransferSize);
-
-    // get bmc execution context
-    ipmi_register_callback(NETFUN_FIRMWARE, IPMI_CMD_FW_GET_BMC_EXEC_CTX, NULL,
-                           ipmi_firmware_get_fw_execution_context,
-                           PRIVILEGE_ADMIN);
-
-    // get root certificate information
-    ipmi_register_callback(NETFUN_FIRMWARE, IPMI_CMD_FW_GET_ROOT_CERT_INFO,
-                           NULL, ipmi_firmware_get_root_cert_info,
-                           PRIVILEGE_ADMIN);
-#ifdef INTEL_PFR_ENABLED
     // get root certificate data
     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnFirmware,
                           ipmi::firmware::cmdFwGetRootCertData,
                           ipmi::Privilege::Admin, ipmiGetFwRootCertData);
 #endif
 
-    // generate bmc fw update random number (for enter fw tranfer mode)
-    ipmi_register_callback(NETFUN_FIRMWARE, IPMI_CMD_FW_GET_FW_UPDATE_RAND_NUM,
-                           NULL, ipmi_firmware_get_fw_random_number,
-                           PRIVILEGE_ADMIN);
+    // get firmware update channel information (max transfer sizes)
+    ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnFirmware,
+                          ipmi::firmware::cmdGetFwUpdateChannelInfo,
+                          ipmi::Privilege::Admin, ipmiFirmwareMaxTransferSize);
 
-    // Set Firmware Update Mode(0x27)
-    ipmi::registerHandler(ipmi::prioOemBase, NETFUN_FIRMWARE,
-                          IPMI_CMD_FW_SET_FW_UPDATE_MODE,
+    // 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
+    // Exit Firmware Update Mode
     ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnFirmware,
-                          cmdFirmwareExitFirmwareUpdateMode,
-                          ipmi::Privilege::Admin, ipmiFirmwareExitFwUpdateMode);
+                          ipmi::firmware::cmdExitFirmwareUpdateMode,
+                          ipmi::Privilege::Admin, ipmiExitFirmwareUpdateMode);
 
-    // firmware control mechanism (set filename, usb, etc.)
-    ipmi_register_callback(NETFUN_FIRMWARE, IPMI_CMD_FW_UPDATE_CONTROL, NULL,
-                           ipmi_firmware_control, PRIVILEGE_ADMIN);
+    // 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, NETFUN_FIRMWARE,
-                          IPMI_CMD_FW_GET_STATUS, ipmi::Privilege::Admin,
-                          ipmiFrmwareGetStatus);
-    // set firmware update options (no downgrade, etc.)
-    ipmi_register_callback(NETFUN_FIRMWARE, IPMI_CMD_FW_SET_FW_UPDATE_OPTIONS,
-                           NULL, ipmi_firmware_update_options, PRIVILEGE_ADMIN);
+    // 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);
-
-    // get buffer size is used by fw update (exclusively?)
-    ipmi_register_callback(NETFUN_INTC_APP, IPMI_CMD_INTC_GET_BUFFER_SIZE, NULL,
-                           ipmi_intel_app_get_buffer_size, PRIVILEGE_USER);
     return;
 }