diff --git a/vpd-manager/bios_handler.cpp b/vpd-manager/bios_handler.cpp
deleted file mode 100644
index 7cc5aac..0000000
--- a/vpd-manager/bios_handler.cpp
+++ /dev/null
@@ -1,691 +0,0 @@
-#include "config.h"
-
-#include "bios_handler.hpp"
-
-#include "const.hpp"
-#include "ibm_vpd_utils.hpp"
-#include "manager.hpp"
-#include "types.hpp"
-
-#include <sdbusplus/bus.hpp>
-
-#include <iostream>
-#include <memory>
-#include <string>
-#include <tuple>
-#include <variant>
-
-using namespace openpower::vpd;
-using namespace openpower::vpd::constants;
-
-namespace openpower
-{
-namespace vpd
-{
-namespace manager
-{
-void BiosHandler::checkAndListenPLDMService()
-{
-    // Setup a match on NameOwnerChanged to determine when PLDM is up. In
-    // the signal handler, call restoreBIOSAttribs
-    static std::shared_ptr<sdbusplus::bus::match_t> nameOwnerMatch =
-        std::make_shared<sdbusplus::bus::match_t>(
-            *conn,
-            sdbusplus::bus::match::rules::nameOwnerChanged(
-                "xyz.openbmc_project.PLDM"),
-            [this](sdbusplus::message_t& msg) {
-                if (msg.is_method_error())
-                {
-                    std::cerr
-                        << "Error in reading name owner signal " << std::endl;
-                    return;
-                }
-                std::string name;
-                std::string newOwner;
-                std::string oldOwner;
-
-                msg.read(name, oldOwner, newOwner);
-                if (newOwner != "" && name == "xyz.openbmc_project.PLDM")
-                {
-                    this->restoreBIOSAttribs();
-                    // We don't need the match anymore
-                    nameOwnerMatch.reset();
-                }
-            });
-    // Check if PLDM is already running, if it is, we can go ahead and attempt
-    // to sync BIOS attributes (since PLDM would have initialized them by the
-    // time it acquires a bus name).
-    bool isPLDMRunning = false;
-    try
-    {
-        auto bus = sdbusplus::bus::new_default();
-        auto method =
-            bus.new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus",
-                                "org.freedesktop.DBus", "NameHasOwner");
-        method.append("xyz.openbmc_project.PLDM");
-
-        auto result = bus.call(method);
-        result.read(isPLDMRunning);
-    }
-    catch (const sdbusplus::exception::SdBusError& e)
-    {
-        std::cerr << "Failed to check if PLDM is running, assume false"
-                  << std::endl;
-        std::cerr << e.what() << std::endl;
-    }
-
-    std::cout << "Is PLDM running: " << isPLDMRunning << std::endl;
-
-    if (isPLDMRunning)
-    {
-        nameOwnerMatch.reset();
-        restoreBIOSAttribs();
-    }
-}
-
-void BiosHandler::listenBiosAttribs()
-{
-    static std::shared_ptr<sdbusplus::bus::match_t> biosMatcher =
-        std::make_shared<sdbusplus::bus::match_t>(
-            *conn,
-            sdbusplus::bus::match::rules::propertiesChanged(
-                "/xyz/openbmc_project/bios_config/manager",
-                "xyz.openbmc_project.BIOSConfig.Manager"),
-            [this](sdbusplus::message_t& msg) { biosAttribsCallback(msg); });
-}
-
-void BiosHandler::biosAttribsCallback(sdbusplus::message_t& msg)
-{
-    if (msg.is_method_error())
-    {
-        std::cerr << "Error in reading BIOS attribute signal " << std::endl;
-        return;
-    }
-    using BiosProperty = std::tuple<
-        std::string, bool, std::string, std::string, std::string,
-        std::variant<int64_t, std::string>, std::variant<int64_t, std::string>,
-        std::vector<std::tuple<std::string, std::variant<int64_t, std::string>,
-                               std::string>>>;
-
-    using BiosBaseTable =
-        std::variant<std::monostate, std::map<std::string, BiosProperty>>;
-    using BiosBaseTableType = std::map<std::string, BiosBaseTable>;
-
-    std::string object;
-    BiosBaseTableType propMap;
-    msg.read(object, propMap);
-    for (auto prop : propMap)
-    {
-        if (prop.first == "BaseBIOSTable")
-        {
-            if (auto list = std::get_if<std::map<std::string, BiosProperty>>(
-                    &(prop.second)))
-            {
-                for (const auto& item : *list)
-                {
-                    std::string attributeName = std::get<0>(item);
-                    if (attributeName == "hb_memory_mirror_mode")
-                    {
-                        auto attrValue = std::get<5>(std::get<1>(item));
-                        auto val = std::get_if<std::string>(&attrValue);
-                        if (val)
-                        {
-                            saveAMMToVPD(*val);
-                        }
-                    }
-                    else if (attributeName == "hb_field_core_override")
-                    {
-                        auto attrValue = std::get<5>(std::get<1>(item));
-                        auto val = std::get_if<int64_t>(&attrValue);
-                        if (val)
-                        {
-                            saveFCOToVPD(*val);
-                        }
-                    }
-                    else if (attributeName == "pvm_keep_and_clear")
-                    {
-                        auto attrValue = std::get<5>(std::get<1>(item));
-                        auto val = std::get_if<std::string>(&attrValue);
-                        if (val)
-                        {
-                            saveKeepAndClearToVPD(*val);
-                        }
-                    }
-                    else if (attributeName == "pvm_create_default_lpar")
-                    {
-                        auto attrValue = std::get<5>(std::get<1>(item));
-                        auto val = std::get_if<std::string>(&attrValue);
-                        if (val)
-                        {
-                            saveCreateDefaultLparToVPD(*val);
-                        }
-                    }
-                    else if (attributeName == "pvm_clear_nvram")
-                    {
-                        auto attrValue = std::get<5>(std::get<1>(item));
-                        auto val = std::get_if<std::string>(&attrValue);
-                        if (val)
-                        {
-                            saveClearNVRAMToVPD(*val);
-                        }
-                    }
-                }
-            }
-            else
-            {
-                inventory::PelAdditionalData additionalData;
-                additionalData.emplace(
-                    "DESCRIPTION",
-                    "Invalid type received for BIOS base table property");
-
-                createPEL(additionalData, PelSeverity::ERROR,
-                          errIntfForVPDDefault, nullptr);
-                std::cerr
-                    << "Invalid type received for BIOS base table property"
-                    << std::endl;
-            }
-        }
-    }
-}
-
-void BiosHandler::saveFCOToVPD(int64_t fcoVal)
-{
-    if (fcoVal == -1)
-    {
-        std::cerr << "Invalid FCO value from BIOS: " << fcoVal << std::endl;
-        return;
-    }
-
-    Binary vpdVal = {0, 0, 0, static_cast<uint8_t>(fcoVal)};
-    auto valInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "RG");
-
-    if (valInVPD.size() != 4)
-    {
-        std::cerr << "Read bad size for VSYS/RG: " << valInVPD.size()
-                  << std::endl;
-        return;
-    }
-
-    if (std::memcmp(vpdVal.data(), valInVPD.data(), 4) != 0)
-    {
-        std::cout << "Writing FCO to VPD: " << fcoVal << std::endl;
-        manager.writeKeyword(sdbusplus::message::object_path{SYSTEM_OBJECT},
-                             "VSYS", "RG", vpdVal);
-    }
-}
-
-void BiosHandler::saveAMMToVPD(const std::string& mirrorMode)
-{
-    Binary vpdVal;
-    auto valInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D0");
-
-    if (valInVPD.size() != 1)
-    {
-        std::cerr << "Read bad size for UTIL/D0: " << valInVPD.size()
-                  << std::endl;
-        return;
-    }
-
-    if (mirrorMode != "Enabled" && mirrorMode != "Disabled")
-    {
-        std::cerr << "Bad value for Mirror mode BIOS attribute: " << mirrorMode
-                  << std::endl;
-        return;
-    }
-
-    // Write to VPD only if the value is not already what we want to write.
-    if (mirrorMode == "Enabled" && valInVPD.at(0) != 2)
-    {
-        vpdVal.emplace_back(2);
-    }
-    else if (mirrorMode == "Disabled" && valInVPD.at(0) != 1)
-    {
-        vpdVal.emplace_back(1);
-    }
-
-    if (!vpdVal.empty())
-    {
-        std::cout << "Writing AMM to VPD: " << static_cast<int>(vpdVal.at(0))
-                  << std::endl;
-        manager.writeKeyword(sdbusplus::message::object_path{SYSTEM_OBJECT},
-                             "UTIL", "D0", vpdVal);
-    }
-}
-
-void BiosHandler::saveKeepAndClearToVPD(const std::string& keepAndClear)
-{
-    Binary vpdVal;
-    auto valInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
-
-    if (valInVPD.size() != 1)
-    {
-        std::cerr << "Read bad size for UTIL/D1: " << valInVPD.size()
-                  << std::endl;
-        return;
-    }
-
-    if (keepAndClear != "Enabled" && keepAndClear != "Disabled")
-    {
-        std::cerr << "Bad value for keep and clear BIOS attribute: "
-                  << keepAndClear << std::endl;
-        return;
-    }
-
-    // Write to VPD only if the value is not already what we want to write.
-    if (keepAndClear == "Enabled" && ((valInVPD.at(0) & 0x01) != 0x01))
-    {
-        vpdVal.emplace_back(valInVPD.at(0) | 0x01);
-    }
-    else if (keepAndClear == "Disabled" && ((valInVPD.at(0) & 0x01) != 0))
-    {
-        vpdVal.emplace_back(valInVPD.at(0) & ~(0x01));
-    }
-
-    if (!vpdVal.empty())
-    {
-        std::cout << "Writing Keep and Clear to VPD: "
-                  << static_cast<int>(vpdVal.at(0)) << std::endl;
-        manager.writeKeyword(sdbusplus::message::object_path{SYSTEM_OBJECT},
-                             "UTIL", "D1", vpdVal);
-    }
-}
-
-void BiosHandler::saveCreateDefaultLparToVPD(
-    const std::string& createDefaultLpar)
-{
-    Binary vpdVal;
-    auto valInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
-
-    if (valInVPD.size() != 1)
-    {
-        std::cerr << "Read bad size for UTIL/D1: " << valInVPD.size()
-                  << std::endl;
-        return;
-    }
-
-    if (createDefaultLpar != "Enabled" && createDefaultLpar != "Disabled")
-    {
-        std::cerr << "Bad value for create default lpar BIOS attribute: "
-                  << createDefaultLpar << std::endl;
-        return;
-    }
-
-    // Write to VPD only if the value is not already what we want to write.
-    if (createDefaultLpar == "Enabled" && ((valInVPD.at(0) & 0x02) != 0x02))
-    {
-        vpdVal.emplace_back(valInVPD.at(0) | 0x02);
-    }
-    else if (createDefaultLpar == "Disabled" && ((valInVPD.at(0) & 0x02) != 0))
-    {
-        vpdVal.emplace_back(valInVPD.at(0) & ~(0x02));
-    }
-
-    if (!vpdVal.empty())
-    {
-        std::cout << "Writing create default lpar to VPD: "
-                  << static_cast<int>(vpdVal.at(0)) << std::endl;
-        manager.writeKeyword(sdbusplus::message::object_path{SYSTEM_OBJECT},
-                             "UTIL", "D1", vpdVal);
-    }
-}
-
-void BiosHandler::saveClearNVRAMToVPD(const std::string& clearNVRAM)
-{
-    Binary vpdVal;
-    auto valInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
-
-    if (valInVPD.size() != 1)
-    {
-        std::cerr << "Read bad size for UTIL/D1: " << valInVPD.size()
-                  << std::endl;
-        return;
-    }
-
-    if (clearNVRAM != "Enabled" && clearNVRAM != "Disabled")
-    {
-        std::cerr << "Bad value for clear NVRAM BIOS attribute: " << clearNVRAM
-                  << std::endl;
-        return;
-    }
-
-    // Write to VPD only if the value is not already what we want to write.
-    if (clearNVRAM == "Enabled" && ((valInVPD.at(0) & 0x04) != 0x04))
-    {
-        vpdVal.emplace_back(valInVPD.at(0) | 0x04);
-    }
-    else if (clearNVRAM == "Disabled" && ((valInVPD.at(0) & 0x04) != 0))
-    {
-        vpdVal.emplace_back(valInVPD.at(0) & ~(0x04));
-    }
-
-    if (!vpdVal.empty())
-    {
-        std::cout << "Writing clear NVRAM to VPD: "
-                  << static_cast<int>(vpdVal.at(0)) << std::endl;
-        manager.writeKeyword(sdbusplus::message::object_path{SYSTEM_OBJECT},
-                             "UTIL", "D1", vpdVal);
-    }
-}
-
-int64_t BiosHandler::readBIOSFCO()
-{
-    int64_t fcoVal = -1;
-    auto val = readBIOSAttribute("hb_field_core_override");
-
-    if (auto pVal = std::get_if<int64_t>(&val))
-    {
-        fcoVal = *pVal;
-    }
-    else
-    {
-        std::cerr << "FCO is not an int" << std::endl;
-    }
-    return fcoVal;
-}
-
-std::string BiosHandler::readBIOSAMM()
-{
-    std::string ammVal{};
-    auto val = readBIOSAttribute("hb_memory_mirror_mode");
-
-    if (auto pVal = std::get_if<std::string>(&val))
-    {
-        ammVal = *pVal;
-    }
-    else
-    {
-        std::cerr << "AMM is not a string" << std::endl;
-    }
-    return ammVal;
-}
-
-std::string BiosHandler::readBIOSKeepAndClear()
-{
-    std::string keepAndClear{};
-    auto val = readBIOSAttribute("pvm_keep_and_clear");
-
-    if (auto pVal = std::get_if<std::string>(&val))
-    {
-        keepAndClear = *pVal;
-    }
-    else
-    {
-        std::cerr << "Keep and clear is not a string" << std::endl;
-    }
-    return keepAndClear;
-}
-
-std::string BiosHandler::readBIOSCreateDefaultLpar()
-{
-    std::string createDefaultLpar{};
-    auto val = readBIOSAttribute("pvm_create_default_lpar");
-
-    if (auto pVal = std::get_if<std::string>(&val))
-    {
-        createDefaultLpar = *pVal;
-    }
-    else
-    {
-        std::cerr << "Create default LPAR is not a string" << std::endl;
-    }
-    return createDefaultLpar;
-}
-
-std::string BiosHandler::readBIOSClearNVRAM()
-{
-    std::string clearNVRAM{};
-    auto val = readBIOSAttribute("pvm_clear_nvram");
-
-    if (auto pVal = std::get_if<std::string>(&val))
-    {
-        clearNVRAM = *pVal;
-    }
-    else
-    {
-        std::cerr << "Clear NVRAM is not a string" << std::endl;
-    }
-    return clearNVRAM;
-}
-
-void BiosHandler::saveFCOToBIOS(const std::string& fcoVal, int64_t fcoInBIOS)
-{
-    if (fcoVal.size() != 4)
-    {
-        std::cerr << "Bad size for FCO in VPD: " << fcoVal.size() << std::endl;
-        return;
-    }
-
-    // Need to write?
-    if (fcoInBIOS == static_cast<int64_t>(fcoVal.at(3)))
-    {
-        std::cout << "Skip FCO BIOS write, value is already: " << fcoInBIOS
-                  << std::endl;
-        return;
-    }
-
-    PendingBIOSAttrsType biosAttrs;
-    biosAttrs.push_back(
-        std::make_pair("hb_field_core_override",
-                       std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
-                                       "AttributeType.Integer",
-                                       fcoVal.at(3))));
-
-    std::cout << "Set hb_field_core_override to: "
-              << static_cast<int>(fcoVal.at(3)) << std::endl;
-
-    setBusProperty<PendingBIOSAttrsType>(
-        "xyz.openbmc_project.BIOSConfigManager",
-        "/xyz/openbmc_project/bios_config/manager",
-        "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes",
-        biosAttrs);
-}
-
-void BiosHandler::saveAMMToBIOS(const std::string& ammVal,
-                                const std::string& ammInBIOS)
-{
-    if (ammVal.size() != 1)
-    {
-        std::cerr << "Bad size for AMM in VPD: " << ammVal.size() << std::endl;
-        return;
-    }
-
-    // Make sure data in VPD is sane
-    if (ammVal.at(0) != 1 && ammVal.at(0) != 2)
-    {
-        std::cerr << "Bad value for AMM read from VPD: "
-                  << static_cast<int>(ammVal.at(0)) << std::endl;
-        return;
-    }
-
-    // Need to write?
-    std::string toWrite = (ammVal.at(0) == 2) ? "Enabled" : "Disabled";
-    if (ammInBIOS == toWrite)
-    {
-        std::cout << "Skip AMM BIOS write, value is already: " << toWrite
-                  << std::endl;
-        return;
-    }
-
-    PendingBIOSAttrsType biosAttrs;
-    biosAttrs.push_back(
-        std::make_pair("hb_memory_mirror_mode",
-                       std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
-                                       "AttributeType.Enumeration",
-                                       toWrite)));
-
-    std::cout << "Set hb_memory_mirror_mode to: " << toWrite << std::endl;
-
-    setBusProperty<PendingBIOSAttrsType>(
-        "xyz.openbmc_project.BIOSConfigManager",
-        "/xyz/openbmc_project/bios_config/manager",
-        "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes",
-        biosAttrs);
-}
-
-void BiosHandler::saveKeepAndClearToBIOS(const std::string& keepAndClear,
-                                         const std::string& keepAndClearInBIOS)
-{
-    if (keepAndClear.size() != 1)
-    {
-        std::cerr << "Bad size for Keep and Clear in VPD: "
-                  << keepAndClear.size() << std::endl;
-        return;
-    }
-
-    // Need to write?
-    std::string toWrite = (keepAndClear.at(0) & 0x01) ? "Enabled" : "Disabled";
-    if (keepAndClearInBIOS == toWrite)
-    {
-        std::cout << "Skip Keep and Clear BIOS write, value is already: "
-                  << toWrite << std::endl;
-        return;
-    }
-
-    PendingBIOSAttrsType biosAttrs;
-    biosAttrs.push_back(
-        std::make_pair("pvm_keep_and_clear",
-                       std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
-                                       "AttributeType.Enumeration",
-                                       toWrite)));
-
-    std::cout << "Set pvm_keep_and_clear to: " << toWrite << std::endl;
-
-    setBusProperty<PendingBIOSAttrsType>(
-        "xyz.openbmc_project.BIOSConfigManager",
-        "/xyz/openbmc_project/bios_config/manager",
-        "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes",
-        biosAttrs);
-}
-
-void BiosHandler::saveCreateDefaultLparToBIOS(
-    const std::string& createDefaultLpar,
-    const std::string& createDefaultLparInBIOS)
-{
-    if (createDefaultLpar.size() != 1)
-    {
-        std::cerr << "Bad size for Create default LPAR in VPD: "
-                  << createDefaultLpar.size() << std::endl;
-        return;
-    }
-
-    // Need to write?
-    std::string toWrite =
-        (createDefaultLpar.at(0) & 0x02) ? "Enabled" : "Disabled";
-    if (createDefaultLparInBIOS == toWrite)
-    {
-        std::cout << "Skip Create default LPAR BIOS write, value is already: "
-                  << toWrite << std::endl;
-        return;
-    }
-
-    PendingBIOSAttrsType biosAttrs;
-    biosAttrs.push_back(
-        std::make_pair("pvm_create_default_lpar",
-                       std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
-                                       "AttributeType.Enumeration",
-                                       toWrite)));
-
-    std::cout << "Set pvm_create_default_lpar to: " << toWrite << std::endl;
-
-    setBusProperty<PendingBIOSAttrsType>(
-        "xyz.openbmc_project.BIOSConfigManager",
-        "/xyz/openbmc_project/bios_config/manager",
-        "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes",
-        biosAttrs);
-}
-
-void BiosHandler::saveClearNVRAMToBIOS(const std::string& clearNVRAM,
-                                       const std::string& clearNVRAMInBIOS)
-{
-    if (clearNVRAM.size() != 1)
-    {
-        std::cerr << "Bad size for Clear NVRAM in VPD: " << clearNVRAM.size()
-                  << std::endl;
-        return;
-    }
-
-    // Need to write?
-    std::string toWrite = (clearNVRAM.at(0) & 0x04) ? "Enabled" : "Disabled";
-    if (clearNVRAMInBIOS == toWrite)
-    {
-        std::cout << "Skip Clear NVRAM BIOS write, value is already: "
-                  << toWrite << std::endl;
-        return;
-    }
-
-    PendingBIOSAttrsType biosAttrs;
-    biosAttrs.push_back(
-        std::make_pair("pvm_clear_nvram",
-                       std::make_tuple("xyz.openbmc_project.BIOSConfig.Manager."
-                                       "AttributeType.Enumeration",
-                                       toWrite)));
-
-    std::cout << "Set pvm_clear_nvram to: " << toWrite << std::endl;
-
-    setBusProperty<PendingBIOSAttrsType>(
-        "xyz.openbmc_project.BIOSConfigManager",
-        "/xyz/openbmc_project/bios_config/manager",
-        "xyz.openbmc_project.BIOSConfig.Manager", "PendingAttributes",
-        biosAttrs);
-}
-
-void BiosHandler::restoreBIOSAttribs()
-{
-    // TODO: We could make this slightly more scalable by defining a table of
-    // attributes and their corresponding VPD keywords. However, that needs much
-    // more thought.
-    std::cout << "Attempting BIOS attribute reset" << std::endl;
-    // Check if the VPD contains valid data for FCO, AMM, Keep and Clear,
-    // Create default LPAR and Clear NVRAM *and* that it differs from the data
-    // already in the attributes. If so, set the BIOS attributes as per the
-    // value in the VPD. If the VPD contains default data, then initialize the
-    // VPD keywords with data taken from the BIOS.
-    auto fcoInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "RG");
-    auto ammInVPD = readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D0");
-    auto keepAndClearInVPD =
-        readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
-    auto fcoInBIOS = readBIOSFCO();
-    auto ammInBIOS = readBIOSAMM();
-    auto keepAndClearInBIOS = readBIOSKeepAndClear();
-    auto createDefaultLparInBIOS = readBIOSCreateDefaultLpar();
-    auto clearNVRAMInBIOS = readBIOSClearNVRAM();
-
-    if (fcoInVPD == "    ")
-    {
-        saveFCOToVPD(fcoInBIOS);
-    }
-    else
-    {
-        saveFCOToBIOS(fcoInVPD, fcoInBIOS);
-    }
-
-    if (ammInVPD.at(0) == 0)
-    {
-        saveAMMToVPD(ammInBIOS);
-    }
-    else
-    {
-        saveAMMToBIOS(ammInVPD, ammInBIOS);
-    }
-
-    // No uninitialized handling needed for keep and clear, create default
-    // lpar and clear nvram attributes. Their defaults in VPD are 0's which is
-    // what we want.
-    saveKeepAndClearToBIOS(keepAndClearInVPD, keepAndClearInBIOS);
-    // Have to read D1 again because two attributes are stored in the same
-    // keyword.
-    auto createDefaultLparInVPD =
-        readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
-    saveCreateDefaultLparToBIOS(createDefaultLparInVPD,
-                                createDefaultLparInBIOS);
-
-    auto clearNVRAMInVPD =
-        readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.UTIL", "D1");
-    saveClearNVRAMToBIOS(clearNVRAMInVPD, clearNVRAMInBIOS);
-
-    // Start listener now that we have done the restore
-    listenBiosAttribs();
-}
-} // namespace manager
-} // namespace vpd
-} // namespace openpower
diff --git a/vpd-manager/bios_handler.hpp b/vpd-manager/bios_handler.hpp
deleted file mode 100644
index adee3c7..0000000
--- a/vpd-manager/bios_handler.hpp
+++ /dev/null
@@ -1,254 +0,0 @@
-#pragma once
-
-#include "types.hpp"
-
-#include <stdint.h>
-
-#include <sdbusplus/asio/connection.hpp>
-
-#include <string>
-
-namespace openpower
-{
-namespace vpd
-{
-namespace manager
-{
-
-class Manager;
-/**
- * @brief A class that handles changes to BIOS attributes backed by VPD.
- *
- * This class has APIs that handle updates to BIOS attributes that need to
- * be backed up to VPD. It mainly does the following:
- * 1) Checks if the VPD keywords that BIOS attributes are backed to are
- * uninitialized. If so, it initializes them.
- * 2) Listens for changes to BIOS attributes and synchronizes them to the
- * appropriate VPD keyword.
- *
- * Since on a factory reset like scenario, the BIOS attributes are initialized
- * by PLDM, this code waits until PLDM has grabbed a bus name before attempting
- * any syncs.
- */
-class BiosHandler
-{
-  public:
-    // Some default and deleted constructors and assignments.
-    BiosHandler() = delete;
-    BiosHandler(const BiosHandler&) = delete;
-    BiosHandler& operator=(const BiosHandler&) = delete;
-    BiosHandler(Manager&&) = delete;
-    BiosHandler& operator=(BiosHandler&&) = delete;
-    ~BiosHandler() = default;
-
-    BiosHandler(std::shared_ptr<sdbusplus::asio::connection>& conn,
-                Manager& manager) : conn(conn), manager(manager)
-    {
-        checkAndListenPLDMService();
-    }
-
-  private:
-    /**
-     * @brief Check if PLDM service is running and run BIOS sync
-     *
-     * This API checks if the PLDM service is running and if yes it will start
-     * an immediate sync of BIOS attributes. If the service is not running, it
-     * registers a listener to be notified when the service starts so that a
-     * restore can be performed.
-     */
-    void checkAndListenPLDMService();
-
-    /**
-     * @brief Register listener for changes to BIOS Attributes.
-     *
-     * The VPD manager needs to listen to changes to certain BIOS attributes
-     * that are backed by VPD. When the attributes we are interested in
-     * change, the VPD manager will make sure that we write them back to the
-     * VPD keywords that back them up.
-     */
-    void listenBiosAttribs();
-
-    /**
-     * @brief Callback for BIOS Attribute changes
-     *
-     * Checks if the BIOS attribute(s) changed are those backed up by VPD. If
-     * yes, it will update the VPD with the new attribute value.
-     * @param[in] msg - The callback message.
-     */
-    void biosAttribsCallback(sdbusplus::message_t& msg);
-
-    /**
-     * @brief Persistently saves the Memory mirror mode
-     *
-     * Memory mirror mode setting is saved to the UTIL/D0 keyword in the
-     * motherboard VPD. If the mirror mode in BIOS is "Disabled", set D0 to 1,
-     * if "Enabled" set D0 to 2
-     *
-     * @param[in] mirrorMode - The mirror mode BIOS attribute.
-     */
-    void saveAMMToVPD(const std::string& mirrorMode);
-
-    /**
-     * @brief Persistently saves the Field Core Override setting
-     *
-     * Saves the field core override value (FCO) into the VSYS/RG keyword in
-     * the motherboard VPD.
-     *
-     * @param[in] fcoVal - The FCO value as an integer.
-     */
-    void saveFCOToVPD(int64_t fcoVal);
-
-    /**
-     * @brief Persistently saves the Keep and Clear setting
-     *
-     * Keep and clear setting is saved to the UTIL/D1 keyword's 0th bit in the
-     * motherboard VPD. If the keep and clear in BIOS is "Disabled", set D1:0 to
-     * 0, if "Enabled" set D1:0 to 1
-     *
-     * @param[in] keepAndClear - The keep and clear BIOS attribute.
-     */
-    void saveKeepAndClearToVPD(const std::string& keepAndClear);
-
-    /**
-     * @brief Persistently saves the Create default LPAR setting
-     *
-     * Create default LPAR setting is saved to the UTIL/D1 keyword's 1st bit in
-     * the motherboard VPD. If the create default LPAR in BIOS is "Disabled",
-     * set D1:1 to 0, if "Enabled" set D1:1 to 1
-     *
-     * @param[in] createDefaultLpar - The mirror mode BIOS attribute.
-     */
-    void saveCreateDefaultLparToVPD(const std::string& createDefaultLpar);
-
-    /**
-     * @brief Persistently saves the Clear NVRAM setting
-     *
-     * Create default LPAR setting is saved to the UTIL/D1 keyword's 2nd bit in
-     * the motherboard VPD. If the clear NVRAM in BIOS is "Disabled",
-     * set D1:2 to 0, if "Enabled" set D1:2 to 1
-     *
-     * @param[in] createDefaultLpar - The mirror mode BIOS attribute.
-     */
-    void saveClearNVRAMToVPD(const std::string& clearNVRAM);
-
-    /**
-     * @brief Writes Memory mirror mode to BIOS
-     *
-     * Writes to the hb_memory_mirror_mode BIOS attribute, if the value is
-     * not already the same as we are trying to write.
-     *
-     * @param[in] ammVal - The mirror mode as read from VPD.
-     * @param[in] ammInBIOS - The mirror mode in the BIOS table.
-     */
-    void saveAMMToBIOS(const std::string& ammVal, const std::string& ammInBIOS);
-
-    /**
-     * @brief Writes Field Core Override to BIOS
-     *
-     * Writes to the hb_field_core_override BIOS attribute, if the value is not
-     * already the same as we are trying to write.
-     *
-     * @param[in] fcoVal - The FCO value as read from VPD.
-     * @param[in] fcoInBIOS - The FCO value already in the BIOS table.
-     */
-    void saveFCOToBIOS(const std::string& fcoVal, int64_t fcoInBIOS);
-
-    /**
-     * @brief Writes Keep and clear setting to BIOS
-     *
-     * Writes to the pvm_keep_and_clear BIOS attribute, if the value is
-     * not already the same as we are trying to write.
-     *
-     * @param[in] keepAndClear - The keep and clear as read from VPD.
-     * @param[in] keepAndClearInBIOS - The keep and clear in the BIOS table.
-     */
-    void saveKeepAndClearToBIOS(const std::string& keepAndClear,
-                                const std::string& keepAndClearInBIOS);
-
-    /**
-     * @brief Writes Create default LPAR setting to BIOS
-     *
-     * Writes to the pvm_create_default_lpar BIOS attribute, if the value is
-     * not already the same as we are trying to write.
-     *
-     * @param[in] createDefaultLpar - The create default LPAR as read from VPD.
-     * @param[in] createDefaultLparInBIOS - The create default LPAR in the BIOS
-     * table.
-     */
-    void
-        saveCreateDefaultLparToBIOS(const std::string& createDefaultLpar,
-                                    const std::string& createDefaultLparInBIOS);
-
-    /**
-     * @brief Writes Clear NVRAM setting to BIOS
-     *
-     * Writes to the pvm_clear_nvram BIOS attribute, if the value is
-     * not already the same as we are trying to write.
-     *
-     * @param[in] clearNVRAM - The clear NVRAM as read from VPD.
-     * @param[in] clearNVRAMInBIOS - The clear NVRAM in the BIOS table.
-     */
-    void saveClearNVRAMToBIOS(const std::string& clearNVRAM,
-                              const std::string& clearNVRAMInBIOS);
-
-    /**
-     * @brief Reads the hb_memory_mirror_mode attribute
-     *
-     * @return std::string - The AMM BIOS attribute. Empty string on failure.
-     */
-    std::string readBIOSAMM();
-
-    /**
-     * @brief Reads the hb_field_core_override attribute
-     *
-     * @return int64_t - The FCO BIOS attribute.  -1 on failure.
-     */
-    int64_t readBIOSFCO();
-
-    /**
-     * @brief Reads the pvm_keep_and_clear attribute
-     *
-     * @return std::string - The Keep and clear BIOS attribute. Empty string on
-     * failure.
-     */
-    std::string readBIOSKeepAndClear();
-
-    /**
-     * @brief Reads the pvm_create_default_lpar attribute
-     *
-     * @return std::string - The Create default LPAR BIOS attribute. Empty
-     * string on failure.
-     */
-    std::string readBIOSCreateDefaultLpar();
-
-    /**
-     * @brief Reads the pvm_clear_nvram attribute
-     *
-     * @return std::string - The Clear NVRAM BIOS attribute. Empty
-     * string on failure.
-     */
-    std::string readBIOSClearNVRAM();
-
-    /**
-     * @brief Restore BIOS attributes
-     *
-     * This function checks if we are coming out of a factory reset. If yes,
-     * it checks the VPD cache for valid backed up copy of the applicable
-     * BIOS attributes. If valid values are found in the VPD, it will apply
-     * those to the BIOS attributes.
-     */
-    void restoreBIOSAttribs();
-
-    /**
-     * @brief Reference to the connection.
-     */
-    std::shared_ptr<sdbusplus::asio::connection>& conn;
-
-    /**
-     * @brief Reference to the manager.
-     */
-    Manager& manager;
-}; // class BiosHandler
-} // namespace manager
-} // namespace vpd
-} // namespace openpower
diff --git a/vpd-manager/editor_impl.cpp b/vpd-manager/editor_impl.cpp
deleted file mode 100644
index c24cc0f..0000000
--- a/vpd-manager/editor_impl.cpp
+++ /dev/null
@@ -1,732 +0,0 @@
-#include "config.h"
-
-#include "editor_impl.hpp"
-
-#include "vpdecc/vpdecc.h"
-
-#include "common_utility.hpp"
-#include "ibm_vpd_utils.hpp"
-#include "ipz_parser.hpp"
-#include "parser_factory.hpp"
-#include "vpd_exceptions.hpp"
-
-#include <phosphor-logging/elog-errors.hpp>
-#include <xyz/openbmc_project/Common/error.hpp>
-
-using namespace openpower::vpd::parser::interface;
-using namespace openpower::vpd::constants;
-using namespace openpower::vpd::parser::factory;
-using namespace openpower::vpd::ipz::parser;
-
-namespace openpower
-{
-namespace vpd
-{
-namespace manager
-{
-namespace editor
-{
-
-void EditorImpl::checkPTForRecord(Binary::const_iterator& iterator,
-                                  Byte ptLength)
-{
-    // auto iterator = ptRecord.cbegin();
-    auto end = std::next(iterator, ptLength + 1);
-
-    // Look at each entry in the PT keyword for the record name
-    while (iterator < end)
-    {
-        auto stop = std::next(iterator, lengths::RECORD_NAME);
-        std::string record(iterator, stop);
-
-        if (record == thisRecord.recName)
-        {
-            // Skip record name and record type
-            std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType));
-
-            // Get record offset
-            thisRecord.recOffset = readUInt16LE(iterator);
-
-            // pass the record offset length to read record length
-            std::advance(iterator, lengths::RECORD_OFFSET);
-            thisRecord.recSize = readUInt16LE(iterator);
-
-            std::advance(iterator, lengths::RECORD_LENGTH);
-            thisRecord.recECCoffset = readUInt16LE(iterator);
-
-            ECCLength len;
-            std::advance(iterator, lengths::RECORD_ECC_OFFSET);
-            len = readUInt16LE(iterator);
-            thisRecord.recECCLength = len;
-
-            // once we find the record we don't need to look further
-            return;
-        }
-        else
-        {
-            // Jump the record
-            std::advance(iterator,
-                         lengths::RECORD_NAME + sizeof(RecordType) +
-                             sizeof(RecordOffset) + sizeof(RecordLength) +
-                             sizeof(ECCOffset) + sizeof(ECCLength));
-        }
-    }
-    // imples the record was not found
-    throw std::runtime_error("Record not found");
-}
-
-void EditorImpl::updateData(const Binary& kwdData)
-{
-    std::size_t lengthToUpdate = kwdData.size() <= thisRecord.kwdDataLength
-                                     ? kwdData.size()
-                                     : thisRecord.kwdDataLength;
-
-    auto iteratorToNewdata = kwdData.cbegin();
-    auto end = iteratorToNewdata;
-    std::advance(end, lengthToUpdate);
-
-    // update data in file buffer as it will be needed to update ECC
-    // avoiding extra stream operation here
-    auto iteratorToKWdData = vpdFile.begin();
-    std::advance(iteratorToKWdData, thisRecord.kwDataOffset);
-    std::copy(iteratorToNewdata, end, iteratorToKWdData);
-
-#ifdef ManagerTest
-    auto startItr = vpdFile.begin();
-    std::advance(iteratorToKWdData, thisRecord.kwDataOffset);
-    auto endItr = startItr;
-    std::advance(endItr, thisRecord.kwdDataLength);
-
-    Binary updatedData(startItr, endItr);
-    if (updatedData == kwdData)
-    {
-        throw std::runtime_error("Data updated successfully");
-    }
-#else
-
-    // update data in EEPROM as well. As we will not write complete file back
-    vpdFileStream.seekp(startOffset + thisRecord.kwDataOffset, std::ios::beg);
-
-    iteratorToNewdata = kwdData.cbegin();
-    std::copy(iteratorToNewdata, end,
-              std::ostreambuf_iterator<char>(vpdFileStream));
-
-    // get a hold to new data in case encoding is needed
-    thisRecord.kwdUpdatedData.resize(thisRecord.kwdDataLength);
-    auto itrToKWdData = vpdFile.cbegin();
-    std::advance(itrToKWdData, thisRecord.kwDataOffset);
-    auto kwdDataEnd = itrToKWdData;
-    std::advance(kwdDataEnd, thisRecord.kwdDataLength);
-    std::copy(itrToKWdData, kwdDataEnd, thisRecord.kwdUpdatedData.begin());
-#endif
-}
-
-void EditorImpl::checkRecordForKwd()
-{
-    RecordOffset recOffset = thisRecord.recOffset;
-
-    // Amount to skip for record ID, size, and the RT keyword
-    constexpr auto skipBeg = sizeof(RecordId) + sizeof(RecordSize) +
-                             lengths::KW_NAME + sizeof(KwSize);
-
-    auto iterator = vpdFile.cbegin();
-    std::advance(iterator, recOffset + skipBeg + lengths::RECORD_NAME);
-
-    auto end = iterator;
-    std::advance(end, thisRecord.recSize);
-    std::size_t dataLength = 0;
-
-    while (iterator < end)
-    {
-        // Note keyword name
-        std::string kw(iterator, iterator + lengths::KW_NAME);
-
-        // Check if the Keyword starts with '#'
-        char kwNameStart = *iterator;
-        std::advance(iterator, lengths::KW_NAME);
-
-        // if keyword starts with #
-        if (POUND_KW == kwNameStart)
-        {
-            // Note existing keyword data length
-            dataLength = readUInt16LE(iterator);
-
-            // Jump past 2Byte keyword length + data
-            std::advance(iterator, sizeof(PoundKwSize));
-        }
-        else
-        {
-            // Note existing keyword data length
-            dataLength = *iterator;
-
-            // Jump past keyword length and data
-            std::advance(iterator, sizeof(KwSize));
-        }
-
-        if (thisRecord.recKWd == kw)
-        {
-            thisRecord.kwDataOffset = std::distance(vpdFile.cbegin(), iterator);
-            thisRecord.kwdDataLength = dataLength;
-            return;
-        }
-
-        // jump the data of current kwd to point to next kwd name
-        std::advance(iterator, dataLength);
-    }
-
-    throw std::runtime_error("Keyword not found");
-}
-
-void EditorImpl::updateRecordECC()
-{
-    auto itrToRecordData = vpdFile.cbegin();
-    std::advance(itrToRecordData, thisRecord.recOffset);
-
-    auto itrToRecordECC = vpdFile.cbegin();
-    std::advance(itrToRecordECC, thisRecord.recECCoffset);
-
-    auto l_status = vpdecc_create_ecc(
-        const_cast<uint8_t*>(&itrToRecordData[0]), thisRecord.recSize,
-        const_cast<uint8_t*>(&itrToRecordECC[0]), &thisRecord.recECCLength);
-    if (l_status != VPD_ECC_OK)
-    {
-        throw std::runtime_error("Ecc update failed");
-    }
-
-    auto end = itrToRecordECC;
-    std::advance(end, thisRecord.recECCLength);
-
-#ifndef ManagerTest
-    vpdFileStream.seekp(startOffset + thisRecord.recECCoffset, std::ios::beg);
-    std::copy(itrToRecordECC, end,
-              std::ostreambuf_iterator<char>(vpdFileStream));
-#endif
-}
-
-auto EditorImpl::getValue(offsets::Offsets offset)
-{
-    auto itr = vpdFile.cbegin();
-    std::advance(itr, offset);
-    LE2ByteData lowByte = *itr;
-    LE2ByteData highByte = *(itr + 1);
-    lowByte |= (highByte << 8);
-
-    return lowByte;
-}
-
-void EditorImpl::checkRecordData()
-{
-    auto itrToRecordData = vpdFile.cbegin();
-    std::advance(itrToRecordData, thisRecord.recOffset);
-
-    auto itrToRecordECC = vpdFile.cbegin();
-    std::advance(itrToRecordECC, thisRecord.recECCoffset);
-
-    checkECC(itrToRecordData, itrToRecordECC, thisRecord.recSize,
-             thisRecord.recECCLength);
-}
-
-void EditorImpl::checkECC(Binary::const_iterator& itrToRecData,
-                          Binary::const_iterator& itrToECCData,
-                          RecordLength recLength, ECCLength eccLength)
-{
-    auto l_status =
-        vpdecc_check_data(const_cast<uint8_t*>(&itrToRecData[0]), recLength,
-                          const_cast<uint8_t*>(&itrToECCData[0]), eccLength);
-
-    if (l_status == VPD_ECC_CORRECTABLE_DATA)
-    {
-        try
-        {
-            if (vpdFileStream.is_open())
-            {
-                vpdFileStream.seekp(startOffset + thisRecord.recOffset,
-                                    std::ios::beg);
-                auto end = itrToRecData;
-                std::advance(end, recLength);
-                std::copy(itrToRecData, end,
-                          std::ostreambuf_iterator<char>(vpdFileStream));
-            }
-            else
-            {
-                throw std::runtime_error("Ecc correction failed");
-            }
-        }
-        catch (const std::fstream::failure& e)
-        {
-            std::cout << "Error while operating on file with exception";
-            throw std::runtime_error("Ecc correction failed");
-        }
-    }
-    else if (l_status != VPD_ECC_OK)
-    {
-        throw std::runtime_error("Ecc check failed");
-    }
-}
-
-void EditorImpl::readVTOC()
-{
-    // read VTOC offset
-    RecordOffset tocOffset = getValue(offsets::VTOC_PTR);
-
-    // read VTOC record length
-    RecordLength tocLength = getValue(offsets::VTOC_REC_LEN);
-
-    // read TOC ecc offset
-    ECCOffset tocECCOffset = getValue(offsets::VTOC_ECC_OFF);
-
-    // read TOC ecc length
-    ECCLength tocECCLength = getValue(offsets::VTOC_ECC_LEN);
-
-    auto itrToRecord = vpdFile.cbegin();
-    std::advance(itrToRecord, tocOffset);
-
-    auto iteratorToECC = vpdFile.cbegin();
-    std::advance(iteratorToECC, tocECCOffset);
-
-    // validate ecc for the record
-    checkECC(itrToRecord, iteratorToECC, tocLength, tocECCLength);
-
-    // to get to the record name.
-    std::advance(itrToRecord, sizeof(RecordId) + sizeof(RecordSize) +
-                                  // Skip past the RT keyword, which contains
-                                  // the record name.
-                                  lengths::KW_NAME + sizeof(KwSize));
-
-    std::string recordName(itrToRecord, itrToRecord + lengths::RECORD_NAME);
-
-    if ("VTOC" != recordName)
-    {
-        throw std::runtime_error("VTOC record not found");
-    }
-
-    // jump to length of PT kwd
-    std::advance(itrToRecord, lengths::RECORD_NAME + lengths::KW_NAME);
-
-    // Note size of PT
-    Byte ptLen = *itrToRecord;
-    std::advance(itrToRecord, 1);
-
-    checkPTForRecord(itrToRecord, ptLen);
-}
-
-template <typename T>
-void EditorImpl::makeDbusCall(
-    const std::string& object, const std::string& interface,
-    const std::string& property, const std::variant<T>& data)
-{
-    auto bus = sdbusplus::bus::new_default();
-    auto properties =
-        bus.new_method_call(INVENTORY_MANAGER_SERVICE, object.c_str(),
-                            "org.freedesktop.DBus.Properties", "Set");
-    properties.append(interface);
-    properties.append(property);
-    properties.append(data);
-
-    auto result = bus.call(properties);
-
-    if (result.is_method_error())
-    {
-        throw std::runtime_error("bus call failed");
-    }
-}
-
-void EditorImpl::processAndUpdateCI(const std::string& objectPath)
-{
-    inventory::ObjectMap objects;
-    for (auto& commonInterface : jsonFile["commonInterfaces"].items())
-    {
-        for (auto& ciPropertyList : commonInterface.value().items())
-        {
-            if (ciPropertyList.value().type() ==
-                nlohmann::json::value_t::object)
-            {
-                if ((ciPropertyList.value().value("recordName", "") ==
-                     thisRecord.recName) &&
-                    (ciPropertyList.value().value("keywordName", "") ==
-                     thisRecord.recKWd))
-                {
-                    inventory::PropertyMap prop;
-                    inventory::InterfaceMap interfaces;
-                    std::string kwdData(thisRecord.kwdUpdatedData.begin(),
-                                        thisRecord.kwdUpdatedData.end());
-
-                    prop.emplace(ciPropertyList.key(), std::move(kwdData));
-                    interfaces.emplace(commonInterface.key(), std::move(prop));
-                    objects.emplace(objectPath, std::move(interfaces));
-                }
-            }
-        }
-    }
-    // Notify PIM
-    common::utility::callPIM(std::move(objects));
-}
-
-void EditorImpl::processAndUpdateEI(const nlohmann::json& Inventory,
-                                    const inventory::Path& objPath)
-{
-    inventory::ObjectMap objects;
-    for (const auto& extraInterface : Inventory["extraInterfaces"].items())
-    {
-        if (extraInterface.value() != NULL)
-        {
-            for (const auto& eiPropertyList : extraInterface.value().items())
-            {
-                if (eiPropertyList.value().type() ==
-                    nlohmann::json::value_t::object)
-                {
-                    if ((eiPropertyList.value().value("recordName", "") ==
-                         thisRecord.recName) &&
-                        ((eiPropertyList.value().value("keywordName", "") ==
-                          thisRecord.recKWd)))
-                    {
-                        inventory::PropertyMap prop;
-                        inventory::InterfaceMap interfaces;
-                        std::string kwdData(thisRecord.kwdUpdatedData.begin(),
-                                            thisRecord.kwdUpdatedData.end());
-                        encodeKeyword(kwdData, eiPropertyList.value().value(
-                                                   "encoding", ""));
-
-                        prop.emplace(eiPropertyList.key(), std::move(kwdData));
-                        interfaces.emplace(extraInterface.key(),
-                                           std::move(prop));
-                        objects.emplace(objPath, std::move(interfaces));
-                    }
-                }
-            }
-        }
-    }
-    // Notify PIM
-    common::utility::callPIM(std::move(objects));
-}
-
-void EditorImpl::updateCache()
-{
-    const std::vector<nlohmann::json>& groupEEPROM =
-        jsonFile["frus"][vpdFilePath].get_ref<const nlohmann::json::array_t&>();
-
-    inventory::ObjectMap objects;
-    // iterate through all the inventories for this file path
-    for (const auto& singleInventory : groupEEPROM)
-    {
-        inventory::PropertyMap prop;
-        inventory::InterfaceMap interfaces;
-        // by default inherit property is true
-        bool isInherit = true;
-
-        if (singleInventory.find("inherit") != singleInventory.end())
-        {
-            isInherit = singleInventory["inherit"].get<bool>();
-        }
-
-        if (isInherit)
-        {
-            prop.emplace(getDbusNameForThisKw(thisRecord.recKWd),
-                         thisRecord.kwdUpdatedData);
-            interfaces.emplace(
-                (IPZ_INTERFACE + (std::string) "." + thisRecord.recName),
-                std::move(prop));
-            objects.emplace(
-                (singleInventory["inventoryPath"].get<std::string>()),
-                std::move(interfaces));
-
-            // process Common interface
-            processAndUpdateCI(singleInventory["inventoryPath"]
-                                   .get_ref<const nlohmann::json::string_t&>());
-        }
-
-        // process extra interfaces
-        processAndUpdateEI(singleInventory,
-                           singleInventory["inventoryPath"]
-                               .get_ref<const nlohmann::json::string_t&>());
-
-        // check if we need to copy some specific records in this case.
-        if (singleInventory.find("copyRecords") != singleInventory.end())
-        {
-            if (find(singleInventory["copyRecords"].begin(),
-                     singleInventory["copyRecords"].end(),
-                     thisRecord.recName) !=
-                singleInventory["copyRecords"].end())
-            {
-                prop.emplace(thisRecord.recKWd, thisRecord.kwdUpdatedData);
-                interfaces.emplace(
-                    (IPZ_INTERFACE + std::string{"."} + thisRecord.recName),
-                    std::move(prop));
-                objects.emplace(
-                    (singleInventory["inventoryPath"].get<std::string>()),
-                    std::move(interfaces));
-            }
-        }
-    }
-    // Notify PIM
-    common::utility::callPIM(std::move(objects));
-}
-
-void EditorImpl::expandLocationCode(const std::string& locationCodeType)
-{
-    std::string propertyFCorTM{};
-    std::string propertySE{};
-
-    if (locationCodeType == "fcs")
-    {
-        propertyFCorTM =
-            readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC");
-        propertySE =
-            readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "SE");
-    }
-    else if (locationCodeType == "mts")
-    {
-        propertyFCorTM =
-            readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "TM");
-        propertySE =
-            readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "SE");
-    }
-
-    const nlohmann::json& groupFRUS =
-        jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
-    inventory::ObjectMap objects;
-
-    for (const auto& itemFRUS : groupFRUS.items())
-    {
-        const std::vector<nlohmann::json>& groupEEPROM =
-            itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
-        for (const auto& itemEEPROM : groupEEPROM)
-        {
-            inventory::PropertyMap prop;
-            inventory::InterfaceMap interfaces;
-            const auto& objectPath = itemEEPROM["inventoryPath"];
-            sdbusplus::message::object_path object(objectPath);
-
-            // check if the given item implements location code interface
-            if (itemEEPROM["extraInterfaces"].find(IBM_LOCATION_CODE_INF) !=
-                itemEEPROM["extraInterfaces"].end())
-            {
-                const std::string& unexpandedLocationCode =
-                    itemEEPROM["extraInterfaces"][IBM_LOCATION_CODE_INF]
-                              ["LocationCode"]
-                                  .get_ref<const nlohmann::json::string_t&>();
-                std::size_t idx = unexpandedLocationCode.find(locationCodeType);
-                if (idx != std::string::npos)
-                {
-                    std::string expandedLocationCode(unexpandedLocationCode);
-
-                    if (locationCodeType == "fcs")
-                    {
-                        expandedLocationCode.replace(
-                            idx, 3,
-                            propertyFCorTM.substr(0, 4) + ".ND0." + propertySE);
-                    }
-                    else if (locationCodeType == "mts")
-                    {
-                        std::replace(propertyFCorTM.begin(),
-                                     propertyFCorTM.end(), '-', '.');
-                        expandedLocationCode.replace(
-                            idx, 3, propertyFCorTM + "." + propertySE);
-                    }
-
-                    // update the DBUS interface COM as well as XYZ path
-                    prop.emplace("LocationCode", expandedLocationCode);
-                    // TODO deprecate this com.ibm interface later
-                    interfaces.emplace(IBM_LOCATION_CODE_INF, prop);
-                    interfaces.emplace(XYZ_LOCATION_CODE_INF, std::move(prop));
-                }
-            }
-            objects.emplace(std::move(object), std::move(interfaces));
-        }
-    }
-    // Notify PIM
-    common::utility::callPIM(std::move(objects));
-}
-
-#ifndef ManagerTest
-static void enableRebootGuard()
-{
-    try
-    {
-        auto bus = sdbusplus::bus::new_default();
-        auto method = bus.new_method_call(
-            "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
-            "org.freedesktop.systemd1.Manager", "StartUnit");
-        method.append("reboot-guard-enable.service", "replace");
-        bus.call_noreply(method);
-    }
-    catch (const sdbusplus::exception_t& e)
-    {
-        std::string errMsg =
-            "Bus call to enable BMC reboot failed for reason: ";
-        errMsg += e.what();
-
-        throw std::runtime_error(errMsg);
-    }
-}
-
-static void disableRebootGuard()
-{
-    try
-    {
-        auto bus = sdbusplus::bus::new_default();
-        auto method = bus.new_method_call(
-            "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
-            "org.freedesktop.systemd1.Manager", "StartUnit");
-        method.append("reboot-guard-disable.service", "replace");
-        bus.call_noreply(method);
-    }
-    catch (const sdbusplus::exception_t& e)
-    {
-        using namespace phosphor::logging;
-        using InternalFailure =
-            sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
-
-        std::string errMsg =
-            "Bus call to disable BMC reboot failed for reason: ";
-        errMsg += e.what();
-
-        log<level::ERR>("Disable boot guard failed");
-        elog<InternalFailure>();
-
-        throw std::runtime_error(errMsg);
-    }
-}
-#endif
-
-void EditorImpl::updateKeyword(const Binary& kwdData, uint32_t offset,
-                               const bool& updCache)
-{
-    try
-    {
-        startOffset = offset;
-#ifndef ManagerTest
-        // Restrict BMC from rebooting when VPD is being written. This will
-        // prevent any data/ECC corruption in case BMC reboots while VPD update.
-        enableRebootGuard();
-
-        Binary completeVPDFile;
-        vpdFileStream.exceptions(
-            std::ifstream::badbit | std::ifstream::failbit);
-        try
-        {
-            vpdFileStream.open(vpdFilePath,
-                               std::ios::in | std::ios::out | std::ios::binary);
-
-            auto vpdFileSize =
-                std::min(std::filesystem::file_size(vpdFilePath), MAX_VPD_SIZE);
-            if (vpdFileSize == 0)
-            {
-                std::cerr << "File size is 0 for " << vpdFilePath << std::endl;
-                throw std::runtime_error("File size is 0.");
-            }
-
-            completeVPDFile.resize(vpdFileSize);
-            vpdFileStream.seekg(startOffset, std::ios_base::cur);
-            vpdFileStream.read(reinterpret_cast<char*>(&completeVPDFile[0]),
-                               vpdFileSize);
-            vpdFileStream.clear(std::ios_base::eofbit);
-        }
-        catch (const std::system_error& fail)
-        {
-            std::cerr << "Exception in file handling [" << vpdFilePath
-                      << "] error : " << fail.what();
-            std::cerr << "Stream file size = " << vpdFileStream.gcount()
-                      << std::endl;
-            throw;
-        }
-        vpdFile = completeVPDFile;
-
-        if (objPath.empty() &&
-            jsonFile["frus"].find(vpdFilePath) != jsonFile["frus"].end())
-        {
-            objPath = jsonFile["frus"][vpdFilePath][0]["inventoryPath"]
-                          .get_ref<const nlohmann::json::string_t&>();
-        }
-
-#else
-
-        Binary completeVPDFile = vpdFile;
-
-#endif
-        if (vpdFile.empty())
-        {
-            throw std::runtime_error("Invalid File");
-        }
-        auto iterator = vpdFile.cbegin();
-        std::advance(iterator, IPZ_DATA_START);
-
-        Byte vpdType = *iterator;
-        if (vpdType == KW_VAL_PAIR_START_TAG)
-        {
-            // objPath should be empty only in case of test run.
-            ParserInterface* Iparser = ParserFactory::getParser(
-                completeVPDFile, objPath, vpdFilePath, startOffset);
-            IpzVpdParser* ipzParser = dynamic_cast<IpzVpdParser*>(Iparser);
-
-            try
-            {
-                if (ipzParser == nullptr)
-                {
-                    throw std::runtime_error("Invalid cast");
-                }
-
-                ipzParser->processHeader();
-                delete ipzParser;
-                ipzParser = nullptr;
-                // ParserFactory::freeParser(Iparser);
-
-                // process VTOC for PTT rkwd
-                readVTOC();
-
-                // check record for keywrod
-                checkRecordForKwd();
-
-                // Check Data before updating
-                checkRecordData();
-
-                // update the data to the file
-                updateData(kwdData);
-
-                // update the ECC data for the record once data has been updated
-                updateRecordECC();
-
-                if (updCache)
-                {
-#ifndef ManagerTest
-                    // update the cache once data has been updated
-                    updateCache();
-#endif
-                }
-            }
-            catch (const std::exception& e)
-            {
-                if (ipzParser != nullptr)
-                {
-                    delete ipzParser;
-                }
-                throw std::runtime_error(e.what());
-            }
-
-#ifndef ManagerTest
-            // Once VPD data and Ecc update is done, disable BMC boot guard.
-            disableRebootGuard();
-#endif
-
-            return;
-        }
-        else
-        {
-            throw openpower::vpd::exceptions::VpdDataException(
-                "Could not find start tag in VPD " + vpdFilePath);
-        }
-    }
-    catch (const std::exception& e)
-    {
-#ifndef ManagerTest
-        // Disable reboot guard.
-        disableRebootGuard();
-#endif
-
-        throw std::runtime_error(e.what());
-    }
-}
-} // namespace editor
-} // namespace manager
-} // namespace vpd
-} // namespace openpower
diff --git a/vpd-manager/editor_impl.hpp b/vpd-manager/editor_impl.hpp
deleted file mode 100644
index cf0ef2b..0000000
--- a/vpd-manager/editor_impl.hpp
+++ /dev/null
@@ -1,216 +0,0 @@
-#pragma once
-
-#include "const.hpp"
-#include "types.hpp"
-
-#include <nlohmann/json.hpp>
-
-#include <cstddef>
-#include <fstream>
-#include <tuple>
-
-namespace openpower
-{
-namespace vpd
-{
-namespace manager
-{
-namespace editor
-{
-
-/** @class EditorImpl */
-class EditorImpl
-{
-  public:
-    EditorImpl() = delete;
-    EditorImpl(const EditorImpl&) = delete;
-    EditorImpl& operator=(const EditorImpl&) = delete;
-    EditorImpl(EditorImpl&&) = delete;
-    EditorImpl& operator=(EditorImpl&&) = delete;
-    ~EditorImpl() {}
-
-    /** @brief Construct EditorImpl class
-     *
-     *  @param[in] record - Record Name
-     *  @param[in] kwd - Keyword
-     *  @param[in] vpd - Vpd Vector
-     */
-    EditorImpl(const std::string& record, const std::string& kwd,
-               Binary&& vpd) :
-        startOffset(0), thisRecord(record, kwd), vpdFile(std::move(vpd))
-    {}
-
-    /** @brief Construct EditorImpl class
-     *
-     *  @param[in] path - Path to the vpd file
-     *  @param[in] json - Parsed inventory json
-     *  @param[in] record - Record name
-     *  @param[in] kwd - Keyword
-     *  @param[in] inventoryPath - Inventory path of the vpd
-     */
-    EditorImpl(const inventory::Path& path, const nlohmann::json& json,
-               const std::string& record, const std::string& kwd,
-               const sdbusplus::message::object_path& inventoryPath) :
-        vpdFilePath(path), objPath(inventoryPath), startOffset(0),
-        jsonFile(json), thisRecord(record, kwd)
-    {}
-
-    /** @brief Construct EditorImpl class
-     *
-     * @param[in] path - EEPROM path
-     * @param[in] json - Parsed inventory json object
-     * @param[in] record - Record name
-     * @param[in] kwd - Keyword name
-     */
-    EditorImpl(const inventory::Path& path, const nlohmann::json& json,
-               const std::string& record, const std::string& kwd) :
-        vpdFilePath(path), jsonFile(json), thisRecord(record, kwd)
-    {}
-
-    /**
-     * @brief Update data for keyword
-     * The method looks for the record name to update in VTOC and then
-     * looks for the keyword name in that record. when found it updates the data
-     * of keyword with the given data. It does not block keyword data update in
-     * case the length of new data is greater than or less than the current data
-     * length. If the new data length is more than the length allotted to that
-     * keyword the new data will be truncated to update only the allotted
-     * length. Similarly if the new data length is less then only that much data
-     * will be updated for the keyword and remaining bits will be left
-     * unchanged.
-     *
-     * Following is the algorithm used to update keyword:
-     * 1) Look for the record name in the given VPD file
-     * 2) Look for the keyword name for which data needs to be updated
-     *    which is the table of contents record.
-     * 3) update the data for that keyword with the new data
-     *
-     * @param[in] kwdData - data to update
-     * @param[in] offset - offset at which the VPD starts
-     * @param[in] updCache - Flag which tells whether to update Cache or not.
-     */
-    void updateKeyword(const Binary& kwdData, uint32_t offset,
-                       const bool& updCache);
-
-    /** @brief Expands location code on DBUS
-     *  @param[in] locationCodeType - "fcs" or "mts"
-     */
-    void expandLocationCode(const std::string& locationCodeType);
-
-  private:
-    /** @brief read VTOC record from the vpd file
-     */
-    void readVTOC();
-
-    /** @brief validate ecc data for the VTOC record
-     *  @param[in] itrToRecData -iterator to the record data
-     *  @param[in] itrToECCData - iterator to the ECC data
-     *  @param[in] recLength - Length of the record
-     *  @param[in] eccLength - Length of the record's ECC
-     */
-    void checkECC(Binary::const_iterator& itrToRecData,
-                  Binary::const_iterator& itrToECCData,
-                  openpower::vpd::constants::RecordLength recLength,
-                  openpower::vpd::constants::ECCLength eccLength);
-
-    /** @brief reads value at the given offset
-     *  @param[in] offset - offset value
-     *  @return  value at that offset in bigendian
-     */
-    auto getValue(openpower::vpd::constants::offsets::Offsets offset);
-
-    /** @brief Checks if required record name exist in the VPD file
-     *  @param[in] iterator - pointing to start of PT kwd
-     *  @param[in] ptLength - length of the PT kwd
-     */
-    void checkPTForRecord(Binary::const_iterator& iterator, Byte ptLength);
-
-    /** @brief Checks for required keyword in the record */
-    void checkRecordForKwd();
-
-    /** @brief update data for given keyword
-     *  @param[in] kwdData- data to be updated
-     */
-    void updateData(const Binary& kwdData);
-
-    /** @brief update record ECC */
-    void updateRecordECC();
-
-    /** @brief method to update cache once the data for keyword has been updated
-     */
-    void updateCache();
-
-    /** @brief method to process and update CI in case required
-     *  @param[in] - objectPath - path of the object to introspect
-     */
-    void processAndUpdateCI(const std::string& objectPath);
-
-    /** @brief method to process and update extra interface
-     *  @param[in] Inventory - single inventory json subpart
-     *  @param[in] objPath - path of the object to introspect
-     */
-    void processAndUpdateEI(const nlohmann::json& Inventory,
-                            const inventory::Path& objPath);
-
-    /** @brief method to make busctl call
-     *
-     *  @param[in] object - bus object path
-     *  @param[in] interface - bus interface
-     *  @param[in] property - property to update on BUS
-     *  @param[in] data - data to be updated on Bus
-     *
-     */
-    template <typename T>
-    void makeDbusCall(const std::string& object, const std::string& interface,
-                      const std::string& property, const std::variant<T>& data);
-
-    /** @brief Method to check the record's Data using ECC */
-    void checkRecordData();
-
-    // path to the VPD file to edit
-    inventory::Path vpdFilePath;
-
-    // inventory path of the vpd fru to update keyword
-    inventory::Path objPath{};
-
-    // stream to perform operation on file
-    std::fstream vpdFileStream;
-
-    // stream to operate on VPD data
-    std::fstream vpdDataFileStream;
-
-    // offset to get vpd data from EEPROM
-    uint32_t startOffset;
-
-    // file to store parsed json
-    const nlohmann::json jsonFile;
-
-    // structure to hold info about record to edit
-    struct RecInfo
-    {
-        Binary kwdUpdatedData; // need access to it in case encoding is needed
-        const std::string recName;
-        const std::string recKWd;
-        openpower::vpd::constants::RecordOffset recOffset;
-        openpower::vpd::constants::ECCOffset recECCoffset;
-        std::size_t recECCLength;
-        std::size_t kwdDataLength;
-        openpower::vpd::constants::RecordSize recSize;
-        openpower::vpd::constants::DataOffset kwDataOffset;
-        // constructor
-        RecInfo(const std::string& rec, const std::string& kwd) :
-            recName(rec), recKWd(kwd), recOffset(0), recECCoffset(0),
-            recECCLength(0), kwdDataLength(0), recSize(0), kwDataOffset(0)
-        {}
-    } thisRecord;
-
-    Binary vpdFile;
-
-    // If requested Interface is common Interface
-    bool isCI;
-}; // class EditorImpl
-
-} // namespace editor
-} // namespace manager
-} // namespace vpd
-} // namespace openpower
diff --git a/vpd-manager/gpioMonitor.cpp b/vpd-manager/gpioMonitor.cpp
deleted file mode 100644
index 3196fee..0000000
--- a/vpd-manager/gpioMonitor.cpp
+++ /dev/null
@@ -1,201 +0,0 @@
-#include "gpioMonitor.hpp"
-
-#include "common_utility.hpp"
-#include "ibm_vpd_utils.hpp"
-
-#include <boost/asio.hpp>
-#include <boost/bind/bind.hpp>
-#include <gpiod.hpp>
-
-using namespace std;
-using namespace openpower::vpd::constants;
-
-namespace openpower
-{
-namespace vpd
-{
-namespace manager
-{
-
-bool GpioEventHandler::getPresencePinValue()
-{
-    Byte gpioData = 1;
-    gpiod::line presenceLine = gpiod::find_line(presencePin);
-    if (!presenceLine)
-    {
-        cerr << "Error getPresencePinValue: couldn't find presence line:"
-             << presencePin << " on GPIO \n";
-        // return previous state as we couldn't read current state
-        return prevPresPinValue;
-    }
-
-    presenceLine.request(
-        {"Op-panel presence line", gpiod::line_request::DIRECTION_INPUT, 0});
-
-    gpioData = presenceLine.get_value();
-
-    return gpioData;
-}
-
-void GpioMonitor::initGpioInfos(
-    std::shared_ptr<boost::asio::io_context>& ioContext)
-{
-    Byte outputValue = 0;
-    Byte presenceValue = 0;
-    string presencePinName{}, outputPinName{};
-    string devNameAddr{}, driverType{}, busType{}, objectPath{};
-
-    for (const auto& eachFRU : jsonFile["frus"].items())
-    {
-        for (const auto& eachInventory : eachFRU.value())
-        {
-            objectPath = eachInventory["inventoryPath"];
-
-            if ((eachInventory.find("presence") != eachInventory.end()) &&
-                (eachInventory.find("preAction") != eachInventory.end()))
-            {
-                if (!eachInventory["presence"].value("pollingRequired", false))
-                {
-                    // Polling not required for this FRU , skip.
-                    continue;
-                }
-
-                for (const auto& presStatus : eachInventory["presence"].items())
-                {
-                    if (presStatus.key() == "pin")
-                    {
-                        presencePinName = presStatus.value();
-                    }
-                    else if (presStatus.key() == "value")
-                    {
-                        presenceValue = presStatus.value();
-                    }
-                }
-
-                // Based on presence pin value, preAction pin will be set/reset
-                // This action will be taken before vpd collection.
-                for (const auto& preAction : eachInventory["preAction"].items())
-                {
-                    if (preAction.key() == "pin")
-                    {
-                        outputPinName = preAction.value();
-                    }
-                    else if (preAction.key() == "value")
-                    {
-                        outputValue = preAction.value();
-                    }
-                }
-
-                if ((eachInventory.find("devAddress") != eachInventory.end()) &&
-                    (eachInventory.find("driverType") != eachInventory.end()) &&
-                    (eachInventory.find("busType") != eachInventory.end()))
-                {
-                    devNameAddr = eachInventory["devAddress"];
-                    driverType = eachInventory["driverType"];
-                    busType = eachInventory["busType"];
-
-                    // Init all Gpio info variables
-                    std::shared_ptr<GpioEventHandler> gpioObj =
-                        make_shared<GpioEventHandler>(
-                            presencePinName, presenceValue, outputPinName,
-                            outputValue, devNameAddr, driverType, busType,
-                            objectPath, ioContext);
-
-                    gpioObjects.push_back(gpioObj);
-                }
-            }
-        }
-    }
-}
-
-void GpioEventHandler::toggleGpio()
-{
-    bool presPinVal = getPresencePinValue();
-    bool isPresent = false;
-
-    // preserve the new value
-    prevPresPinValue = presPinVal;
-
-    if (presPinVal == presenceValue)
-    {
-        isPresent = true;
-    }
-
-    // if FRU went away set the present property to false
-    if (!isPresent)
-    {
-        inventory::ObjectMap objects;
-        inventory::InterfaceMap interfaces;
-        inventory::PropertyMap presProp;
-
-        presProp.emplace("Present", false);
-        interfaces.emplace("xyz.openbmc_project.Inventory.Item", presProp);
-        objects.emplace(objectPath, move(interfaces));
-
-        common::utility::callPIM(move(objects));
-    }
-
-    gpiod::line outputLine = gpiod::find_line(outputPin);
-    if (!outputLine)
-    {
-        cerr << "Error: toggleGpio: couldn't find output line:" << outputPin
-             << ". Skipping update\n";
-
-        return;
-    }
-
-    outputLine.request({"FRU presence: update the output GPIO pin",
-                        gpiod::line_request::DIRECTION_OUTPUT, 0},
-                       isPresent ? outputValue : (!outputValue));
-
-    string cmnd = createBindUnbindDriverCmnd(devNameAddr, busType, driverType,
-                                             isPresent ? "bind" : "unbind");
-
-    cout << cmnd << endl;
-    executeCmd(cmnd);
-}
-
-void GpioEventHandler::handleTimerExpiry(
-    const boost::system::error_code& ec,
-    std::shared_ptr<boost::asio::steady_timer>& timer)
-{
-    if (ec == boost::asio::error::operation_aborted)
-    {
-        return;
-    }
-
-    if (ec)
-    {
-        std::cerr << "Timer wait failed for gpio pin" << ec.message();
-        return;
-    }
-
-    if (hasEventOccurred())
-    {
-        toggleGpio();
-    }
-    timer->expires_at(
-        std::chrono::steady_clock::now() + std::chrono::seconds(5));
-    timer->async_wait(boost::bind(&GpioEventHandler::handleTimerExpiry, this,
-                                  boost::asio::placeholders::error, timer));
-}
-
-void GpioEventHandler::doEventAndTimerSetup(
-    std::shared_ptr<boost::asio::io_context>& ioContext)
-{
-    prevPresPinValue = getPresencePinValue();
-
-    static vector<std::shared_ptr<boost::asio::steady_timer>> timers;
-
-    auto timer = make_shared<boost::asio::steady_timer>(
-        *ioContext, std::chrono::seconds(5));
-
-    timer->async_wait(boost::bind(&GpioEventHandler::handleTimerExpiry, this,
-                                  boost::asio::placeholders::error, timer));
-
-    timers.push_back(timer);
-}
-
-} // namespace manager
-} // namespace vpd
-} // namespace openpower
diff --git a/vpd-manager/gpioMonitor.hpp b/vpd-manager/gpioMonitor.hpp
deleted file mode 100644
index 5f34336..0000000
--- a/vpd-manager/gpioMonitor.hpp
+++ /dev/null
@@ -1,143 +0,0 @@
-#pragma once
-#include "types.hpp"
-
-#include <boost/asio/steady_timer.hpp>
-#include <nlohmann/json.hpp>
-#include <sdbusplus/asio/connection.hpp>
-
-namespace openpower
-{
-namespace vpd
-{
-namespace manager
-{
-/** @class GpioEventHandler
- *  @brief Responsible for catching the event and handle it.
- *         This keeps checking for the FRU's presence.
- *         If any attachment or de-attachment found, it enables/disables that
- * fru's output gpio and bind/unbind the driver, respectively.
- */
-class GpioEventHandler
-{
-  public:
-    GpioEventHandler() = default;
-    ~GpioEventHandler() = default;
-    GpioEventHandler(const GpioEventHandler&) = default;
-    GpioEventHandler& operator=(const GpioEventHandler&) = delete;
-    GpioEventHandler(GpioEventHandler&&) = delete;
-    GpioEventHandler& operator=(GpioEventHandler&&) = delete;
-
-    GpioEventHandler(std::string& presPin, Byte& presValue, std::string& outPin,
-                     Byte& outValue, std::string& devAddr, std::string& driver,
-                     std::string& bus, std::string& objPath,
-                     std::shared_ptr<boost::asio::io_context>& ioCon) :
-        presencePin(presPin), presenceValue(presValue), outputPin(outPin),
-        outputValue(outValue), devNameAddr(devAddr), driverType(driver),
-        busType(bus), objectPath(objPath)
-    {
-        doEventAndTimerSetup(ioCon);
-    }
-
-  private:
-    /** @brief GPIO information to get parsed from vpd json*/
-
-    // gpio pin indicates presence/absence of fru
-    const std::string presencePin;
-    // value which means fru is present
-    const Byte presenceValue;
-    // gpio pin to enable If fru is present
-    const std::string outputPin;
-    // Value to set, to enable the output pin
-    const Byte outputValue;
-
-    // FRU address on bus
-    const std::string devNameAddr;
-    // Driver type
-    const std::string driverType;
-    // Bus type
-    const std::string busType;
-    // object path of FRU
-    const std::string objectPath;
-
-    /** Preserves the GPIO pin value to compare it next time. Default init by
-     *  false*/
-    bool prevPresPinValue = false;
-
-    /** @brief This is a helper function to read the
-     *        current value of Presence GPIO
-     *
-     *  @returns The GPIO value
-     */
-    bool getPresencePinValue();
-
-    /** @brief This function will toggle the output gpio as per the presence
-     *         state of fru.
-     */
-    void toggleGpio();
-
-    /** @brief This function checks for fru's presence pin and detects change of
-     *         value on that pin, (in case of fru gets attached or de-attached).
-     *
-     *  @returns true if presence pin value changed
-     *           false otherwise
-     */
-    inline bool hasEventOccurred()
-    {
-        return getPresencePinValue() != prevPresPinValue;
-    }
-
-    /** @brief This function runs a timer , which keeps checking for if an event
-     *         happened, if event occurred then takes action.
-     *
-     *  @param[in] ioContext - Pointer to io context object.
-     */
-    void doEventAndTimerSetup(
-        std::shared_ptr<boost::asio::io_context>& ioContext);
-
-    /**
-     * @brief Api to handle timer expiry.
-     *
-     * @param ec - Error code.
-     * @param timer - Pointer to timer object.
-     */
-    void handleTimerExpiry(const boost::system::error_code& ec,
-                           std::shared_ptr<boost::asio::steady_timer>& timer);
-};
-
-/** @class GpioMonitor
- *  @brief Responsible for initialising the private variables containing gpio
- *         infos. These information will be fetched from vpd json.
- */
-class GpioMonitor
-{
-  public:
-    GpioMonitor() = delete;
-    ~GpioMonitor() = default;
-    GpioMonitor(const GpioMonitor&) = delete;
-    GpioMonitor& operator=(const GpioMonitor&) = delete;
-    GpioMonitor(GpioMonitor&&) = delete;
-    GpioMonitor& operator=(GpioMonitor&&) = delete;
-
-    GpioMonitor(nlohmann::json& js,
-                std::shared_ptr<boost::asio::io_context>& ioCon) : jsonFile(js)
-    {
-        initGpioInfos(ioCon);
-    }
-
-  private:
-    // Json file to get the data
-    nlohmann::json& jsonFile;
-    // Array of event handlers for all the attachable FRUs
-    std::vector<std::shared_ptr<GpioEventHandler>> gpioObjects;
-
-    /** @brief This function will extract the gpio information from vpd json
-     * and store it in GpioEventHandler's private variables
-     *
-     * @param[in] ioContext - Pointer to io context object.
-     */
-    void initGpioInfos(std::shared_ptr<boost::asio::io_context>& ioContext);
-};
-
-} // namespace manager
-} // namespace vpd
-} // namespace openpower
diff --git a/vpd-manager/include/backup_restore.hpp b/vpd-manager/include/backup_restore.hpp
new file mode 100644
index 0000000..12ec384
--- /dev/null
+++ b/vpd-manager/include/backup_restore.hpp
@@ -0,0 +1,102 @@
+#pragma once
+
+#include "types.hpp"
+
+#include <nlohmann/json.hpp>
+
+#include <tuple>
+
+namespace vpd
+{
+
+// Backup and restore operation status.
+enum class BackupAndRestoreStatus : uint8_t
+{
+    NotStarted,
+    Invoked,
+    Completed
+};
+
+/**
+ * @brief class to implement backup and restore VPD.
+ *
+ */
+
+class BackupAndRestore
+{
+  public:
+    // delete functions
+    BackupAndRestore() = delete;
+    BackupAndRestore(const BackupAndRestore&) = delete;
+    BackupAndRestore& operator=(const BackupAndRestore&) = delete;
+    BackupAndRestore(BackupAndRestore&&) = delete;
+    BackupAndRestore& operator=(BackupAndRestore&&) = delete;
+
+    /**
+     * @brief Constructor.
+     *
+     * @param[in] i_sysCfgJsonObj - System config JSON object.
+     *
+     * @throw std::runtime_error in case constructor failure.
+     */
+    BackupAndRestore(const nlohmann::json& i_sysCfgJsonObj);
+
+    /**
+     * @brief Default destructor.
+     */
+    ~BackupAndRestore() = default;
+
+    /**
+     * @brief An API to backup and restore VPD.
+     *
+     * Note: This API works on the keywords declared in the backup and restore
+     * config JSON. Restore or backup action could be triggered for each
+     * keyword, based on the keyword's value present in the source and
+     * destination keyword.
+     *
+     * Restore source keyword's value with destination keyword's value,
+     * when source keyword has default value but
+     * destination's keyword has non default value.
+     *
+     * Backup the source keyword value to the destination's keyword's value,
+     * when source keyword has non default value but
+     * destination's keyword has default value.
+     *
+     * @return Tuple of updated source and destination VPD map variant.
+     */
+    std::tuple<types::VPDMapVariant, types::VPDMapVariant> backupAndRestore();
+
+    /**
+     * @brief An API to set backup and restore status.
+     *
+     * @param[in] i_status - Status to set.
+     */
+    static void
+        setBackupAndRestoreStatus(const BackupAndRestoreStatus& i_status);
+
+  private:
+    /**
+     * @brief An API to handle backup and restore of IPZ type VPD.
+     *
+     * @param[in,out] io_srcVpdMap - Source VPD map.
+     * @param[in,out] io_dstVpdMap - Destination VPD map.
+     * @param[in] i_srcPath - Source EEPROM file path or inventory path.
+     * @param[in] i_dstPath - Destination EEPROM file path or inventory path.
+     *
+     * @throw std::runtime_error
+     */
+    void backupAndRestoreIpzVpd(
+        types::IPZVpdMap& io_srcVpdMap, types::IPZVpdMap& io_dstVpdMap,
+        const std::string& i_srcPath, const std::string& i_dstPath);
+
+    // System JSON config JSON object.
+    nlohmann::json m_sysCfgJsonObj{};
+
+    // Backup and restore config JSON object.
+    nlohmann::json m_backupAndRestoreCfgJsonObj{};
+
+    // Backup and restore status.
+    static BackupAndRestoreStatus m_backupAndRestoreStatus;
+};
+
+} // namespace vpd
diff --git a/vpd-manager/include/bios_handler.hpp b/vpd-manager/include/bios_handler.hpp
new file mode 100644
index 0000000..916811e
--- /dev/null
+++ b/vpd-manager/include/bios_handler.hpp
@@ -0,0 +1,273 @@
+#pragma once
+#include "manager.hpp"
+#include "types.hpp"
+
+#include <sdbusplus/asio/connection.hpp>
+#include <sdbusplus/bus.hpp>
+
+namespace vpd
+{
+
+/**
+ * @brief Interface class for BIOS handling.
+ *
+ * The class layout has the virtual methods required to be implemented by any
+ * concrete class that intends to use the feature provided via BIOS handler
+ * class.
+ */
+class BiosHandlerInterface
+{
+  public:
+    /**
+     * @brief API to back up or restore BIOS attributes.
+     *
+     * Concrete class should implement the API and read the backed up data from
+     * its designated location and take a call if it should be backed up or
+     * restored.
+     */
+    virtual void backUpOrRestoreBiosAttributes() = 0;
+
+    /**
+     * @brief Callback API to be triggered on BIOS attribute change.
+     *
+     * Concrete class should implement the API to extract the attribute and its
+     * value from DBus message broadcasted on BIOS attribute change.
+     * The definition should be overridden in concrete class to deal with BIOS
+     * attributes interested in.
+     *
+     * @param[in] i_msg - The callback message.
+     */
+    virtual void biosAttributesCallback(sdbusplus::message_t& i_msg) = 0;
+};
+
+/**
+ * @brief IBM specifc BIOS handler class.
+ */
+class IbmBiosHandler : public BiosHandlerInterface
+{
+  public:
+    /**
+     * @brief Construct a new IBM BIOS Handler object
+     *
+     * This constructor constructs a new IBM BIOS Handler object
+     * @param[in] i_manager - Manager object.
+     */
+    explicit IbmBiosHandler(const std::shared_ptr<Manager>& i_manager) :
+        m_manager(i_manager)
+    {}
+
+    /**
+     * @brief API to back up or restore BIOS attributes.
+     *
+     * The API will read the backed up data from the VPD keyword and based on
+     * its value, either backs up or restores the data.
+     */
+    virtual void backUpOrRestoreBiosAttributes();
+
+    /**
+     * @brief Callback API to be triggered on BIOS attribute change.
+     *
+     * The API to extract the required attribute and its value from DBus message
+     * broadcasted on BIOS attribute change.
+     *
+     * @param[in] i_msg - The callback message.
+     */
+    virtual void biosAttributesCallback(sdbusplus::message_t& i_msg);
+
+  private:
+    /**
+     * @brief API to read given attribute from BIOS table.
+     *
+     * @param[in] attributeName - Attribute to be read.
+     * @return - Bios attribute current value.
+     */
+    types::BiosAttributeCurrentValue
+        readBiosAttribute(const std::string& attributeName);
+
+    /**
+     * @brief API to process "hb_field_core_override" attribute.
+     *
+     * The API checks value stored in VPD. If found default then the BIOS value
+     * is saved to VPD else VPD value is restored in BIOS pending attribute
+     * table.
+     */
+    void processFieldCoreOverride();
+
+    /**
+     * @brief API to save FCO data into VPD.
+     *
+     * @param[in] i_fcoInBios - FCO value.
+     */
+    void saveFcoToVpd(int64_t i_fcoInBios);
+
+    /**
+     * @brief API to save given value to "hb_field_core_override" attribute.
+     *
+     * @param[in] i_fcoVal - FCO value.
+     */
+    void saveFcoToBios(const types::BinaryVector& i_fcoVal);
+
+    /**
+     * @brief API to save AMM data into VPD.
+     *
+     * @param[in] i_memoryMirrorMode - Memory mirror mode value.
+     */
+    void saveAmmToVpd(const std::string& i_memoryMirrorMode);
+
+    /**
+     * @brief API to save given value to "hb_memory_mirror_mode" attribute.
+     *
+     * @param[in] i_ammVal - AMM value.
+     */
+    void saveAmmToBios(const std::string& i_ammVal);
+
+    /**
+     * @brief API to process "hb_memory_mirror_mode" attribute.
+     *
+     * The API checks value stored in VPD. If found default then the BIOS value
+     * is saved to VPD else VPD value is restored in BIOS pending attribute
+     * table.
+     */
+    void processActiveMemoryMirror();
+
+    /**
+     * @brief API to process "pvm_create_default_lpar" attribute.
+     *
+     * The API reads the value from VPD and restore it to the BIOS attribute
+     * in BIOS pending attribute table.
+     */
+    void processCreateDefaultLpar();
+
+    /**
+     * @brief API to save given value to "pvm_create_default_lpar" attribute.
+     *
+     * @param[in] i_createDefaultLparVal - Value to be saved;
+     */
+    void saveCreateDefaultLparToBios(const std::string& i_createDefaultLparVal);
+
+    /**
+     * @brief API to save given value to VPD.
+     *
+     * @param[in] i_createDefaultLparVal - Value to be saved.
+     *
+     */
+    void saveCreateDefaultLparToVpd(const std::string& i_createDefaultLparVal);
+
+    /**
+     * @brief API to process "pvm_clear_nvram" attribute.
+     *
+     * The API reads the value from VPD and restores it to the BIOS pending
+     * attribute table.
+     */
+    void processClearNvram();
+
+    /**
+     * @brief API to save given value to "pvm_clear_nvram" attribute.
+     *
+     * @param[in] i_clearNvramVal - Value to be saved.
+     */
+    void saveClearNvramToBios(const std::string& i_clearNvramVal);
+
+    /**
+     * @brief API to save given value to VPD.
+     *
+     * @param[in] i_clearNvramVal - Value to be saved.
+     */
+    void saveClearNvramToVpd(const std::string& i_clearNvramVal);
+
+    /**
+     * @brief API to process "pvm_keep_and_clear" attribute.
+     *
+     * The API reads the value from VPD and restore it to the BIOS pending
+     * attribute table.
+     */
+    void processKeepAndClear();
+
+    /**
+     * @brief API to save given value to "pvm_keep_and_clear" attribute.
+     *
+     * @param[in] i_KeepAndClearVal - Value to be saved.
+     */
+    void saveKeepAndClearToBios(const std::string& i_KeepAndClearVal);
+
+    /**
+     * @brief API to save given value to VPD.
+     *
+     * @param[in] i_KeepAndClearVal - Value to be saved.
+     */
+    void saveKeepAndClearToVpd(const std::string& i_KeepAndClearVal);
+
+    // const reference to shared pointer to Manager object.
+    const std::shared_ptr<Manager>& m_manager;
+};
+
+/**
+ * @brief A class to operate upon BIOS attributes.
+ *
+ * The class along with specific BIOS handler class(es), provides a feature
+ * where specific BIOS attributes identified by the concrete specific class can
+ * be listened for any change and can be backed up to a desired location or
+ * restored back to the BIOS table.
+ *
+ * To use the feature, "BiosHandlerInterface" should be implemented by a
+ * concrete class and the same should be used to instantiate BiosHandler.
+ *
+ * This class registers call back to listen to PLDM service as it is being used
+ * for reading/writing BIOS attributes.
+ *
+ * The feature can be used in a factory reset scenario where backed up values
+ * can be used to restore BIOS.
+ *
+ */
+template <typename T>
+class BiosHandler
+{
+  public:
+    // deleted APIs
+    BiosHandler() = delete;
+    BiosHandler(const BiosHandler&) = delete;
+    BiosHandler& operator=(const BiosHandler&) = delete;
+    BiosHandler& operator=(BiosHandler&&) = delete;
+    ~BiosHandler() = default;
+
+    /**
+     * @brief Constructor.
+     *
+     * @param[in] i_connection - Asio connection object.
+     * @param[in] i_manager - Manager object.
+     */
+    BiosHandler(
+        const std::shared_ptr<sdbusplus::asio::connection>& i_connection,
+        const std::shared_ptr<Manager>& i_manager) : m_asioConn(i_connection)
+    {
+        m_specificBiosHandler = std::make_shared<T>(i_manager);
+        checkAndListenPldmService();
+    }
+
+  private:
+    /**
+     * @brief API to check if PLDM service is running and run BIOS sync.
+     *
+     * This API checks if the PLDM service is running and if yes it will start
+     * an immediate sync of BIOS attributes. If the service is not running, it
+     * registers a listener to be notified when the service starts so that a
+     * restore can be performed.
+     */
+    void checkAndListenPldmService();
+
+    /**
+     * @brief Register listener for BIOS attribute property change.
+     *
+     * The VPD manager needs to listen for property change of certain BIOS
+     * attributes that are backed in VPD. When the attributes change, the new
+     * value is written back to the VPD keywords that backs them up.
+     */
+    void listenBiosAttributes();
+
+    // Reference to the connection.
+    const std::shared_ptr<sdbusplus::asio::connection>& m_asioConn;
+
+    // shared pointer to specific BIOS handler.
+    std::shared_ptr<T> m_specificBiosHandler;
+};
+} // namespace vpd
diff --git a/vpd-manager/include/constants.hpp b/vpd-manager/include/constants.hpp
new file mode 100644
index 0000000..5faf8da
--- /dev/null
+++ b/vpd-manager/include/constants.hpp
@@ -0,0 +1,196 @@
+#pragma once
+
+#include <cstdint>
+#include <iostream>
+namespace vpd
+{
+namespace constants
+{
+static constexpr auto KEYWORD_SIZE = 2;
+static constexpr auto RECORD_SIZE = 4;
+
+static constexpr uint8_t IPZ_DATA_START = 11;
+static constexpr uint8_t IPZ_DATA_START_TAG = 0x84;
+static constexpr uint8_t IPZ_RECORD_END_TAG = 0x78;
+
+static constexpr uint8_t KW_VPD_DATA_START = 0;
+static constexpr uint8_t KW_VPD_START_TAG = 0x82;
+static constexpr uint8_t KW_VPD_PAIR_START_TAG = 0x84;
+static constexpr uint8_t ALT_KW_VPD_PAIR_START_TAG = 0x90;
+static constexpr uint8_t KW_VPD_END_TAG = 0x78;
+static constexpr uint8_t KW_VAL_PAIR_END_TAG = 0x79;
+static constexpr uint8_t AMM_ENABLED_IN_VPD = 2;
+static constexpr uint8_t AMM_DISABLED_IN_VPD = 1;
+
+static constexpr auto DDIMM_11S_BARCODE_START = 416;
+static constexpr auto DDIMM_11S_BARCODE_START_TAG = "11S";
+static constexpr auto DDIMM_11S_FORMAT_LEN = 3;
+static constexpr auto DDIMM_11S_BARCODE_LEN = 26;
+static constexpr auto PART_NUM_LEN = 7;
+static constexpr auto SERIAL_NUM_LEN = 12;
+static constexpr auto CCIN_LEN = 4;
+static constexpr auto CONVERT_MB_TO_KB = 1024;
+static constexpr auto CONVERT_GB_TO_KB = 1024 * 1024;
+
+static constexpr auto SPD_BYTE_2 = 2;
+static constexpr auto SPD_BYTE_3 = 3;
+static constexpr auto SPD_BYTE_4 = 4;
+static constexpr auto SPD_BYTE_6 = 6;
+static constexpr auto SPD_BYTE_12 = 12;
+static constexpr auto SPD_BYTE_13 = 13;
+static constexpr auto SPD_BYTE_18 = 18;
+static constexpr auto SPD_BYTE_234 = 234;
+static constexpr auto SPD_BYTE_235 = 235;
+static constexpr auto SPD_BYTE_BIT_0_3_MASK = 0x0F;
+static constexpr auto SPD_BYTE_MASK = 0xFF;
+static constexpr auto SPD_MODULE_TYPE_DDIMM = 0x0A;
+static constexpr auto SPD_DRAM_TYPE_DDR5 = 0x12;
+static constexpr auto SPD_DRAM_TYPE_DDR4 = 0x0C;
+
+static constexpr auto JEDEC_SDRAM_CAP_MASK = 0x0F;
+static constexpr auto JEDEC_PRI_BUS_WIDTH_MASK = 0x07;
+static constexpr auto JEDEC_SDRAM_WIDTH_MASK = 0x07;
+static constexpr auto JEDEC_NUM_RANKS_MASK = 0x38;
+static constexpr auto JEDEC_DIE_COUNT_MASK = 0x70;
+static constexpr auto JEDEC_SINGLE_LOAD_STACK = 0x02;
+static constexpr auto JEDEC_SIGNAL_LOADING_MASK = 0x03;
+
+static constexpr auto JEDEC_SDRAMCAP_MULTIPLIER = 256;
+static constexpr auto JEDEC_PRI_BUS_WIDTH_MULTIPLIER = 8;
+static constexpr auto JEDEC_SDRAM_WIDTH_MULTIPLIER = 4;
+static constexpr auto JEDEC_SDRAMCAP_RESERVED = 7;
+static constexpr auto JEDEC_RESERVED_BITS = 3;
+static constexpr auto JEDEC_DIE_COUNT_RIGHT_SHIFT = 4;
+
+static constexpr auto LAST_KW = "PF";
+static constexpr auto POUND_KW = '#';
+static constexpr auto POUND_KW_PREFIX = "PD_";
+static constexpr auto MB_YEAR_END = 4;
+static constexpr auto MB_MONTH_END = 7;
+static constexpr auto MB_DAY_END = 10;
+static constexpr auto MB_HOUR_END = 13;
+static constexpr auto MB_MIN_END = 16;
+static constexpr auto MB_RESULT_LEN = 19;
+static constexpr auto MB_LEN_BYTES = 8;
+static constexpr auto UUID_LEN_BYTES = 16;
+static constexpr auto UUID_TIME_LOW_END = 8;
+static constexpr auto UUID_TIME_MID_END = 13;
+static constexpr auto UUID_TIME_HIGH_END = 18;
+static constexpr auto UUID_CLK_SEQ_END = 23;
+static constexpr auto MAC_ADDRESS_LEN_BYTES = 6;
+static constexpr auto ONE_BYTE = 1;
+static constexpr auto TWO_BYTES = 2;
+
+static constexpr auto VALUE_0 = 0;
+static constexpr auto VALUE_1 = 1;
+static constexpr auto VALUE_2 = 2;
+static constexpr auto VALUE_3 = 3;
+static constexpr auto VALUE_4 = 4;
+static constexpr auto VALUE_5 = 5;
+static constexpr auto VALUE_6 = 6;
+static constexpr auto VALUE_7 = 7;
+static constexpr auto VALUE_8 = 8;
+
+static constexpr auto MASK_BYTE_BITS_01 = 0x03;
+static constexpr auto MASK_BYTE_BITS_345 = 0x38;
+static constexpr auto MASK_BYTE_BITS_012 = 0x07;
+static constexpr auto MASK_BYTE_BITS_567 = 0xE0;
+static constexpr auto MASK_BYTE_BITS_01234 = 0x1F;
+
+static constexpr auto MASK_BYTE_BIT_6 = 0x40;
+static constexpr auto MASK_BYTE_BIT_7 = 0x80;
+
+static constexpr auto SHIFT_BITS_0 = 0;
+static constexpr auto SHIFT_BITS_3 = 3;
+static constexpr auto SHIFT_BITS_5 = 5;
+
+static constexpr auto ASCII_OF_SPACE = 32;
+
+// Size of 8 EQs' in CP00's PG keyword
+static constexpr auto SIZE_OF_8EQ_IN_PG = 24;
+
+// Zero based index position of first EQ in CP00's PG keyword
+static constexpr auto INDEX_OF_EQ0_IN_PG = 97;
+
+constexpr auto systemInvPath = "/xyz/openbmc_project/inventory/system";
+constexpr auto pimPath = "/xyz/openbmc_project/inventory";
+constexpr auto pimIntf = "xyz.openbmc_project.Inventory.Manager";
+constexpr auto ipzVpdInf = "com.ibm.ipzvpd.";
+constexpr auto kwdVpdInf = "com.ibm.ipzvpd.VINI";
+constexpr auto vsysInf = "com.ibm.ipzvpd.VSYS";
+constexpr auto utilInf = "com.ibm.ipzvpd.UTIL";
+constexpr auto vcenInf = "com.ibm.ipzvpd.VCEN";
+constexpr auto kwdCCIN = "CC";
+constexpr auto kwdRG = "RG";
+constexpr auto kwdAMM = "D0";
+constexpr auto kwdClearNVRAM_CreateLPAR = "D1";
+constexpr auto kwdKeepAndClear = "D1";
+constexpr auto kwdFC = "FC";
+constexpr auto kwdTM = "TM";
+constexpr auto kwdSE = "SE";
+constexpr auto recVSYS = "VSYS";
+constexpr auto recVCEN = "VCEN";
+constexpr auto locationCodeInf = "com.ibm.ipzvpd.Location";
+constexpr auto xyzLocationCodeInf =
+    "xyz.openbmc_project.Inventory.Decorator.LocationCode";
+constexpr auto operationalStatusInf =
+    "xyz.openbmc_project.State.Decorator.OperationalStatus";
+constexpr auto enableInf = "xyz.openbmc_project.Object.Enable";
+constexpr auto assetInf = "xyz.openbmc_project.Inventory.Decorator.Asset";
+constexpr auto inventoryItemInf = "xyz.openbmc_project.Inventory.Item";
+constexpr auto pldmServiceName = "xyz.openbmc_project.PLDM";
+constexpr auto pimServiceName = "xyz.openbmc_project.Inventory.Manager";
+constexpr auto biosConfigMgrObjPath =
+    "/xyz/openbmc_project/bios_config/manager";
+constexpr auto biosConfigMgrService = "xyz.openbmc_project.BIOSConfigManager";
+constexpr auto biosConfigMgrInterface =
+    "xyz.openbmc_project.BIOSConfig.Manager";
+constexpr auto objectMapperService = "xyz.openbmc_project.ObjectMapper";
+constexpr auto objectMapperPath = "/xyz/openbmc_project/object_mapper";
+constexpr auto objectMapperInf = "xyz.openbmc_project.ObjectMapper";
+constexpr auto systemVpdInvPath =
+    "/xyz/openbmc_project/inventory/system/chassis/motherboard";
+constexpr auto assetTagInf = "xyz.openbmc_project.Inventory.Decorator.AssetTag";
+constexpr auto hostObjectPath = "/xyz/openbmc_project/state/host0";
+constexpr auto hostInterface = "xyz.openbmc_project.State.Host";
+constexpr auto hostService = "xyz.openbmc_project.State.Host";
+constexpr auto hostRunningState =
+    "xyz.openbmc_project.State.Host.HostState.Running";
+static constexpr auto BD_YEAR_END = 4;
+static constexpr auto BD_MONTH_END = 7;
+static constexpr auto BD_DAY_END = 10;
+static constexpr auto BD_HOUR_END = 13;
+
+constexpr uint8_t UNEXP_LOCATION_CODE_MIN_LENGTH = 4;
+constexpr uint8_t EXP_LOCATION_CODE_MIN_LENGTH = 17;
+static constexpr auto SE_KWD_LENGTH = 7;
+static constexpr auto INVALID_NODE_NUMBER = -1;
+
+static constexpr auto CMD_BUFFER_LENGTH = 256;
+
+// To be explicitly used for string comparision.
+static constexpr auto STR_CMP_SUCCESS = 0;
+
+// Just a random value. Can be adjusted as required.
+static constexpr uint8_t MAX_THREADS = 10;
+
+static constexpr auto FAILURE = -1;
+static constexpr auto SUCCESS = 0;
+
+constexpr auto bmcStateService = "xyz.openbmc_project.State.BMC";
+constexpr auto bmcZeroStateObject = "/xyz/openbmc_project/state/bmc0";
+constexpr auto bmcStateInterface = "xyz.openbmc_project.State.BMC";
+constexpr auto currentBMCStateProperty = "CurrentBMCState";
+constexpr auto bmcReadyState = "xyz.openbmc_project.State.BMC.BMCState.Ready";
+
+static constexpr auto eventLoggingServiceName = "xyz.openbmc_project.Logging";
+static constexpr auto eventLoggingObjectPath = "/xyz/openbmc_project/logging";
+static constexpr auto eventLoggingInterface =
+    "xyz.openbmc_project.Logging.Create";
+
+static constexpr auto systemdService = "org.freedesktop.systemd1";
+static constexpr auto systemdObjectPath = "/org/freedesktop/systemd1";
+static constexpr auto systemdManagerInterface =
+    "org.freedesktop.systemd1.Manager";
+} // namespace constants
+} // namespace vpd
diff --git a/vpd-manager/include/ddimm_parser.hpp b/vpd-manager/include/ddimm_parser.hpp
new file mode 100644
index 0000000..a53ed17
--- /dev/null
+++ b/vpd-manager/include/ddimm_parser.hpp
@@ -0,0 +1,123 @@
+#pragma once
+
+#include "constants.hpp"
+#include "exceptions.hpp"
+#include "logger.hpp"
+#include "parser_interface.hpp"
+#include "types.hpp"
+
+namespace vpd
+{
+/**
+ * @brief Concrete class to implement DDIMM VPD parsing.
+ *
+ * The class inherits ParserInterface interface class and overrides the parser
+ * functionality to implement parsing logic for DDIMM VPD format.
+ */
+class DdimmVpdParser : public ParserInterface
+{
+  public:
+    // Deleted API's
+    DdimmVpdParser() = delete;
+    DdimmVpdParser(const DdimmVpdParser&) = delete;
+    DdimmVpdParser& operator=(const DdimmVpdParser&) = delete;
+    DdimmVpdParser(DdimmVpdParser&&) = delete;
+    DdimmVpdParser& operator=(DdimmVpdParser&&) = delete;
+
+    /**
+     * @brief Defaul destructor.
+     */
+    ~DdimmVpdParser() = default;
+
+    /**
+     * @brief Constructor
+     *
+     * @param[in] i_vpdVector - VPD data.
+     */
+    DdimmVpdParser(const types::BinaryVector& i_vpdVector) :
+        m_vpdVector(i_vpdVector)
+    {
+        if ((constants::DDIMM_11S_BARCODE_START +
+             constants::DDIMM_11S_BARCODE_LEN) > m_vpdVector.size())
+        {
+            throw(DataException("Malformed DDIMM VPD"));
+        }
+    }
+
+    /**
+     * @brief API to parse DDIMM VPD file.
+     *
+     * @return parsed VPD data
+     */
+    virtual types::VPDMapVariant parse() override;
+
+  private:
+    /**
+     * @brief API to read keyword data based on the type DDR4/DDR5.
+     *
+     * Updates the m_parsedVpdMap with read keyword data.
+     * @param[in] i_iterator - iterator to buffer containing VPD
+     */
+    void readKeywords(types::BinaryVector::const_iterator i_iterator);
+
+    /**
+     * @brief API to calculate DDIMM size from DDIMM VPD
+     *
+     * @param[in] i_iterator - iterator to buffer containing VPD
+     * @return calculated size or 0 in case of any error.
+     */
+    size_t getDdimmSize(types::BinaryVector::const_iterator i_iterator);
+
+    /**
+     * @brief This function calculates DDR5 based DDIMM's capacity
+     *
+     * @param[in] i_iterator - iterator to buffer containing VPD
+     * @return calculated size or 0 in case of any error.
+     */
+    size_t
+        getDdr5BasedDdimmSize(types::BinaryVector::const_iterator i_iterator);
+
+    /**
+     * @brief This function calculates DDR4 based DDIMM's capacity
+     *
+     * @param[in] i_iterator - iterator to buffer containing VPD
+     * @return calculated size or 0 in case of any error.
+     */
+    size_t
+        getDdr4BasedDdimmSize(types::BinaryVector::const_iterator i_iterator);
+
+    /**
+     * @brief This function calculates DDR5 based die per package
+     *
+     * @param[in] i_ByteValue - the bit value for calculation
+     * @return die per package value.
+     */
+    uint8_t getDdr5DiePerPackage(uint8_t i_ByteValue);
+
+    /**
+     * @brief This function calculates DDR5 based density per die
+     *
+     * @param[in] i_ByteValue - the bit value for calculation
+     * @return density per die.
+     */
+    uint8_t getDdr5DensityPerDie(uint8_t i_ByteValue);
+
+    /**
+     * @brief This function checks the validity of the bits
+     *
+     * @param[in] i_ByteValue - the byte value with relevant bits
+     * @param[in] i_shift - shifter value to selects needed bits
+     * @param[in] i_minValue - minimum value it can contain
+     * @param[in] i_maxValue - maximum value it can contain
+     * @return true if valid else false.
+     */
+    bool checkValidValue(uint8_t i_ByteValue, uint8_t i_shift,
+                         uint8_t i_minValue, uint8_t i_maxValue);
+
+    // VPD file to be parsed
+    const types::BinaryVector& m_vpdVector;
+
+    // Stores parsed VPD data.
+    types::DdimmVpdMap m_parsedVpdMap{};
+};
+} // namespace vpd
diff --git a/vpd-manager/include/event_logger.hpp b/vpd-manager/include/event_logger.hpp
new file mode 100644
index 0000000..0080be6
--- /dev/null
+++ b/vpd-manager/include/event_logger.hpp
@@ -0,0 +1,170 @@
+#pragma once
+
+#include "constants.hpp"
+#include "types.hpp"
+
+#include <iostream>
+#include <optional>
+#include <string>
+#include <unordered_map>
+
+namespace vpd
+{
+/**
+ * @brief Class for logging events.
+ *
+ * Class handles logging PEL under 'logging' service.
+ * Provide separate async API's for calling out inventory_path, device_path and
+ * i2c bus.
+ */
+class EventLogger
+{
+  public:
+    /**
+     * @brief An API to create a PEL with inventory path callout.
+     *
+     * This API calls an async method to create PEL, and also handles inventory
+     * path callout.
+     *
+     * Note: If inventory path callout info is not provided, it will create a
+     * PEL without any callout. Currently only one callout is handled in this
+     * API.
+     *
+     * @todo: Symbolic FRU and procedure callout needs to be handled in this
+     * API.
+     *
+     * @param[in] i_errorType - Enum to map with event message name.
+     * @param[in] i_severity - Severity of the event.
+     * @param[in] i_callouts - Callout information, list of tuple having
+     * inventory path and priority as input [optional].
+     * @param[in] i_fileName - File name.
+     * @param[in] i_funcName - Function name.
+     * @param[in] i_internalRc - Internal return code.
+     * @param[in] i_description - Error description.
+     * @param[in] i_userData1 - Additional user data [optional].
+     * @param[in] i_userData2 - Additional user data [optional].
+     * @param[in] i_symFru - Symblolic FRU callout data [optional].
+     * @param[in] i_procedure - Procedure callout data [optional].
+     *
+     * @throw exception in case of error.
+     */
+    static void createAsyncPelWithInventoryCallout(
+        const types::ErrorType& i_errorType,
+        const types::SeverityType& i_severity,
+        const std::vector<types::InventoryCalloutData>& i_callouts,
+        const std::string& i_fileName, const std::string& i_funcName,
+        const uint8_t i_internalRc, const std::string& i_description,
+        const std::optional<std::string> i_userData1,
+        const std::optional<std::string> i_userData2,
+        const std::optional<std::string> i_symFru,
+        const std::optional<std::string> i_procedure);
+
+    /**
+     * @brief An API to create a PEL with device path callout.
+     *
+     * @param[in] i_errorType - Enum to map with event message name.
+     * @param[in] i_severity - Severity of the event.
+     * @param[in] i_callouts - Callout information, list of tuple having device
+     * path and error number as input.
+     * @param[in] i_fileName - File name.
+     * @param[in] i_funcName - Function name.
+     * @param[in] i_internalRc - Internal return code.
+     * @param[in] i_userData1 - Additional user data [optional].
+     * @param[in] i_userData2 - Additional user data [optional].
+     */
+    static void createAsyncPelWithI2cDeviceCallout(
+        const types::ErrorType i_errorType,
+        const types::SeverityType i_severity,
+        const std::vector<types::DeviceCalloutData>& i_callouts,
+        const std::string& i_fileName, const std::string& i_funcName,
+        const uint8_t i_internalRc,
+        const std::optional<std::pair<std::string, std::string>> i_userData1,
+        const std::optional<std::pair<std::string, std::string>> i_userData2);
+
+    /**
+     * @brief An API to create a PEL with I2c bus callout.
+     *
+     * @param[in] i_errorType - Enum to map with event message name.
+     * @param[in] i_severity - Severity of the event.
+     * @param[in] i_callouts - Callout information, list of tuple having i2c
+     * bus, i2c address and error number as input.
+     * @param[in] i_fileName - File name.
+     * @param[in] i_funcName - Function name.
+     * @param[in] i_internalRc - Internal return code.
+     * @param[in] i_userData1 - Additional user data [optional].
+     * @param[in] i_userData2 - Additional user data [optional].
+     */
+    static void createAsyncPelWithI2cBusCallout(
+        const types::ErrorType i_errorType,
+        const types::SeverityType i_severity,
+        const std::vector<types::I2cBusCalloutData>& i_callouts,
+        const std::string& i_fileName, const std::string& i_funcName,
+        const uint8_t i_internalRc,
+        const std::optional<std::pair<std::string, std::string>> i_userData1,
+        const std::optional<std::pair<std::string, std::string>> i_userData2);
+
+    /**
+     * @brief An API to create a PEL.
+     *
+     * @param[in] i_errorType - Enum to map with event message name.
+     * @param[in] i_severity - Severity of the event.
+     * @param[in] i_fileName - File name.
+     * @param[in] i_funcName - Function name.
+     * @param[in] i_internalRc - Internal return code.
+     * @param[in] i_description - Error description.
+     * @param[in] i_userData1 - Additional user data [optional].
+     * @param[in] i_userData2 - Additional user data [optional].
+     * @param[in] i_symFru - Symblolic FRU callout data [optional].
+     * @param[in] i_procedure - Procedure callout data [optional].
+     *
+     * @todo: Symbolic FRU and procedure callout needs to be handled in this
+     * API.
+     */
+    static void createAsyncPel(
+        const types::ErrorType& i_errorType,
+        const types::SeverityType& i_severity, const std::string& i_fileName,
+        const std::string& i_funcName, const uint8_t i_internalRc,
+        const std::string& i_description,
+        const std::optional<std::string> i_userData1,
+        const std::optional<std::string> i_userData2,
+        const std::optional<std::string> i_symFru,
+        const std::optional<std::string> i_procedure);
+
+    /**
+     * @brief An API to create PEL.
+     *
+     * This API makes synchronous call to phosphor-logging Create method.
+     *
+     * @param[in] i_errorType - Enum to map with event message name.
+     * @param[in] i_severity - Severity of the event.
+     * @param[in] i_fileName - File name.
+     * @param[in] i_funcName - Function name.
+     * @param[in] i_internalRc - Internal return code.
+     * @param[in] i_description - Error description.
+     * @param[in] i_userData1 - Additional user data [optional].
+     * @param[in] i_userData2 - Additional user data [optional].
+     * @param[in] i_symFru - Symblolic FRU callout data [optional].s
+     * @param[in] i_procedure - Procedure callout data [optional].
+     *
+     * @todo: Symbolic FRU and procedure callout needs to be handled in this
+     * API.
+     */
+    static void createSyncPel(
+        const types::ErrorType& i_errorType,
+        const types::SeverityType& i_severity, const std::string& i_fileName,
+        const std::string& i_funcName, const uint8_t i_internalRc,
+        const std::string& i_description,
+        const std::optional<std::string> i_userData1,
+        const std::optional<std::string> i_userData2,
+        const std::optional<std::string> i_symFru,
+        const std::optional<std::string> i_procedure);
+
+  private:
+    static const std::unordered_map<types::SeverityType, std::string>
+        m_severityMap;
+    static const std::unordered_map<types::ErrorType, std::string>
+        m_errorMsgMap;
+    static const std::unordered_map<types::CalloutPriority, std::string>
+        m_priorityMap;
+};
+} // namespace vpd
diff --git a/vpd-manager/include/exceptions.hpp b/vpd-manager/include/exceptions.hpp
new file mode 100644
index 0000000..a787d08
--- /dev/null
+++ b/vpd-manager/include/exceptions.hpp
@@ -0,0 +1,157 @@
+#pragma once
+
+#include <stdexcept>
+
+namespace vpd
+{
+/** @class Exception
+ * @brief This class inherits std::runtime_error and overrrides "what" method
+ * to return the description of exception.
+ * This class also works as base class for custom exception classes for
+ * VPD repository.
+ */
+class Exception : public std::runtime_error
+{
+  public:
+    // deleted methods
+    Exception() = delete;
+    Exception(const Exception&) = delete;
+    Exception(Exception&&) = delete;
+    Exception& operator=(const Exception&) = delete;
+
+    // default destructor
+    ~Exception() = default;
+
+    /** @brief constructor
+     *
+     *  @param[in] msg - Information w.r.t exception.
+     */
+    explicit Exception(const std::string& msg) :
+        std::runtime_error(msg), m_errMsg(msg)
+    {}
+
+    /** @brief inline method to return exception string.
+     *
+     * This is overridden method of std::runtime class.
+     */
+    inline const char* what() const noexcept override
+    {
+        return m_errMsg.c_str();
+    }
+
+  private:
+    /** @brief string to hold the reason of exception */
+    std::string m_errMsg;
+
+}; // class Exception
+
+/** @class EccException
+ *
+ *  @brief This class extends Exceptions class and define type for ECC related
+ * exception in VPD.
+ */
+class EccException : public Exception
+{
+  public:
+    // deleted methods
+    EccException() = delete;
+    EccException(const EccException&) = delete;
+    EccException(EccException&&) = delete;
+    EccException& operator=(const EccException&) = delete;
+
+    // default destructor
+    ~EccException() = default;
+
+    /** @brief constructor
+     *
+     *  @param[in] msg - Information w.r.t exception.
+     */
+    explicit EccException(const std::string& msg) : Exception(msg) {}
+
+}; // class EccException
+
+/** @class DataException
+ *
+ * @brief This class extends Exceptions class and define type for data related
+ * exception in VPD
+ */
+class DataException : public Exception
+{
+  public:
+    // deleted methods
+    DataException() = delete;
+    DataException(const DataException&) = delete;
+    DataException(DataException&&) = delete;
+    DataException& operator=(const DataException&) = delete;
+
+    // default destructor
+    ~DataException() = default;
+
+    /** @brief constructor
+     *
+     *  @param[in] msg - string to define exception
+     */
+    explicit DataException(const std::string& msg) : Exception(msg) {}
+
+}; // class DataException
+
+class JsonException : public Exception
+{
+  public:
+    // deleted methods
+    JsonException() = delete;
+    JsonException(const JsonException&) = delete;
+    JsonException(JsonException&&) = delete;
+    JsonException& operator=(const JsonException&) = delete;
+
+    // default destructor
+    ~JsonException() = default;
+
+    /** @brief constructor
+     *  @param[in] msg - Information w.r.t. exception.
+     *  @param[in] path - Json path
+     */
+    JsonException(const std::string& msg, const std::string& path) :
+        Exception(msg), m_jsonPath(path)
+    {}
+
+    /** @brief Json path getter method.
+     *
+     *  @return - Json path
+     */
+    inline std::string getJsonPath() const
+    {
+        return m_jsonPath;
+    }
+
+  private:
+    /** To hold the path of Json that failed*/
+    std::string m_jsonPath;
+
+}; // class JSonException
+
+/** @class GpioException
+ *  @brief Custom handler for GPIO exception.
+ *
+ *  This class extends Exceptions class and define
+ *  type for GPIO related exception in VPD.
+ */
+class GpioException : public Exception
+{
+  public:
+    // deleted methods
+    GpioException() = delete;
+    GpioException(const GpioException&) = delete;
+    GpioException(GpioException&&) = delete;
+    GpioException& operator=(const GpioException&) = delete;
+
+    // default destructor
+    ~GpioException() = default;
+
+    /** @brief constructor
+     *  @param[in] msg - string to define exception
+     */
+    explicit GpioException(const std::string& msg) : Exception(msg) {}
+};
+
+} // namespace vpd
diff --git a/vpd-manager/include/gpio_monitor.hpp b/vpd-manager/include/gpio_monitor.hpp
new file mode 100644
index 0000000..476a31d
--- /dev/null
+++ b/vpd-manager/include/gpio_monitor.hpp
@@ -0,0 +1,142 @@
+#pragma once
+
+#include "worker.hpp"
+
+#include <boost/asio/steady_timer.hpp>
+#include <nlohmann/json.hpp>
+#include <sdbusplus/asio/connection.hpp>
+
+#include <vector>
+
+namespace vpd
+{
+/**
+ * @brief class for GPIO event handling.
+ *
+ * Responsible for detecting events and handling them. It continuously
+ * monitors the presence of the FRU. If it detects any change, performs
+ * deletion of FRU VPD if FRU is not present, otherwise performs VPD
+ * collection if FRU gets added.
+ */
+class GpioEventHandler
+{
+  public:
+    GpioEventHandler() = delete;
+    ~GpioEventHandler() = default;
+    GpioEventHandler(const GpioEventHandler&) = delete;
+    GpioEventHandler& operator=(const GpioEventHandler&) = delete;
+    GpioEventHandler(GpioEventHandler&&) = delete;
+    GpioEventHandler& operator=(GpioEventHandler&&) = delete;
+
+    /**
+     * @brief Constructor
+     *
+     * @param[in] i_fruPath - EEPROM path of the FRU.
+     * @param[in] i_worker - pointer to the worker object.
+     * @param[in] i_ioContext - pointer to the io context object
+     */
+    GpioEventHandler(
+        const std::string i_fruPath, const std::shared_ptr<Worker>& i_worker,
+        const std::shared_ptr<boost::asio::io_context>& i_ioContext) :
+        m_fruPath(i_fruPath), m_worker(i_worker)
+    {
+        setEventHandlerForGpioPresence(i_ioContext);
+    }
+
+  private:
+    /**
+     * @brief API to take action based on GPIO presence pin value.
+     *
+     * This API takes action based on the change in the presence pin value.
+     * It performs deletion of FRU VPD if FRU is not present, otherwise performs
+     * VPD collection if FRU gets added.
+     *
+     * @param[in] i_isFruPresent - Holds the present status of the FRU.
+     */
+    void handleChangeInGpioPin(const bool& i_isFruPresent);
+
+    /**
+     * @brief An API to set event handler for FRUs GPIO presence.
+     *
+     * An API to set timer to call event handler to detect GPIO presence
+     * of the FRU.
+     *
+     * @param[in] i_ioContext - pointer to io context object
+     */
+    void setEventHandlerForGpioPresence(
+        const std::shared_ptr<boost::asio::io_context>& i_ioContext);
+
+    /**
+     * @brief API to handle timer expiry.
+     *
+     * This API handles timer expiry and checks on the GPIO presence state,
+     * takes action if there is any change in the GPIO presence value.
+     *
+     * @param[in] i_errorCode - Error Code
+     * @param[in] i_timerObj - Pointer to timer Object.
+     */
+    void handleTimerExpiry(
+        const boost::system::error_code& i_errorCode,
+        const std::shared_ptr<boost::asio::steady_timer>& i_timerObj);
+
+    const std::string m_fruPath;
+
+    const std::shared_ptr<Worker>& m_worker;
+
+    // Preserves the GPIO pin value to compare. Default value is false.
+    bool m_prevPresencePinValue = false;
+};
+
+class GpioMonitor
+{
+  public:
+    GpioMonitor() = delete;
+    ~GpioMonitor() = default;
+    GpioMonitor(const GpioMonitor&) = delete;
+    GpioMonitor& operator=(const GpioMonitor&) = delete;
+    GpioMonitor(GpioMonitor&&) = delete;
+    GpioMonitor& operator=(GpioMonitor&&) = delete;
+
+    /**
+     * @brief constructor
+     *
+     * @param[in] i_sysCfgJsonObj - System config JSON Object.
+     * @param[in] i_worker - pointer to the worker object.
+     * @param[in] i_ioContext - pointer to IO context object.
+     */
+    GpioMonitor(const nlohmann::json i_sysCfgJsonObj,
+                const std::shared_ptr<Worker>& i_worker,
+                const std::shared_ptr<boost::asio::io_context>& i_ioContext) :
+        m_sysCfgJsonObj(i_sysCfgJsonObj)
+    {
+        if (!m_sysCfgJsonObj.empty())
+        {
+            initHandlerForGpio(i_ioContext, i_worker);
+        }
+        else
+        {
+            throw std::runtime_error(
+                "Gpio Monitoring can't be instantiated with empty config JSON");
+        }
+    }
+
+  private:
+    /**
+     * @brief API to instantiate GpioEventHandler for GPIO pins.
+     *
+     * This API will extract the GPIO information from system config JSON
+     * and instantiate event handler for GPIO pins.
+     *
+     * @param[in] i_ioContext - Pointer to IO context object.
+     * @param[in] i_worker - Pointer to worker class.
+     */
+    void initHandlerForGpio(
+        const std::shared_ptr<boost::asio::io_context>& i_ioContext,
+        const std::shared_ptr<Worker>& i_worker);
+
+    // Array of event handlers for all the attachable FRUs.
+    std::vector<std::shared_ptr<GpioEventHandler>> m_gpioEventHandlerObjects;
+
+    const nlohmann::json& m_sysCfgJsonObj;
+};
+} // namespace vpd
diff --git a/vpd-manager/include/ipz_parser.hpp b/vpd-manager/include/ipz_parser.hpp
new file mode 100644
index 0000000..2d50ddd
--- /dev/null
+++ b/vpd-manager/include/ipz_parser.hpp
@@ -0,0 +1,273 @@
+#pragma once
+
+#include "logger.hpp"
+#include "parser_interface.hpp"
+#include "types.hpp"
+
+#include <fstream>
+#include <string_view>
+
+namespace vpd
+{
+/**
+ * @brief Concrete class to implement IPZ VPD parsing.
+ *
+ * The class inherits ParserInterface interface class and overrides the parser
+ * functionality to implement parsing logic for IPZ VPD format.
+ */
+class IpzVpdParser : public ParserInterface
+{
+  public:
+    // Deleted APIs
+    IpzVpdParser() = delete;
+    IpzVpdParser(const IpzVpdParser&) = delete;
+    IpzVpdParser& operator=(const IpzVpdParser&) = delete;
+    IpzVpdParser(IpzVpdParser&&) = delete;
+    IpzVpdParser& operator=(IpzVpdParser&&) = delete;
+
+    /**
+     * @brief Constructor.
+     *
+     * @param[in] vpdVector - VPD data.
+     * @param[in] vpdFilePath - Path to VPD EEPROM.
+     * @param[in] vpdStartOffset - Offset from where VPD starts in the file.
+     * Defaulted to 0.
+     */
+    IpzVpdParser(const types::BinaryVector& vpdVector,
+                 const std::string& vpdFilePath, size_t vpdStartOffset = 0) :
+        m_vpdVector(vpdVector), m_vpdFilePath(vpdFilePath),
+        m_vpdStartOffset(vpdStartOffset)
+    {
+        try
+        {
+            m_vpdFileStream.exceptions(
+                std::ifstream::badbit | std::ifstream::failbit);
+            m_vpdFileStream.open(vpdFilePath, std::ios::in | std::ios::out |
+                                                  std::ios::binary);
+        }
+        catch (const std::fstream::failure& e)
+        {
+            logging::logMessage(e.what());
+        }
+    }
+
+    /**
+     * @brief Defaul destructor.
+     */
+    ~IpzVpdParser() = default;
+
+    /**
+     * @brief API to parse IPZ VPD file.
+     *
+     * Note: Caller needs to check validity of the map returned. Throws
+     * exception in certain situation, needs to be handled accordingly.
+     *
+     * @return parsed VPD data.
+     */
+    virtual types::VPDMapVariant parse() override;
+
+    /**
+     * @brief API to check validity of VPD header.
+     *
+     * Note: The API throws exception in case of any failure or malformed VDP.
+     *
+     * @param[in] itrToVPD - Iterator to the beginning of VPD file.
+     * Don't change the parameter to reference as movement of passsed iterator
+     * to an offset is not required after header check.
+     */
+    void checkHeader(types::BinaryVector::const_iterator itrToVPD);
+
+    /**
+     * @brief API to read keyword's value from hardware
+     *
+     * @param[in] i_paramsToReadData - Data required to perform read
+     *
+     * @throw
+     * sdbusplus::xyz::openbmc_project::Common::Device::Error::ReadFailure.
+     *
+     * @return On success return the value read. On failure throw exception.
+     */
+    types::DbusVariantType
+        readKeywordFromHardware(const types::ReadVpdParams i_paramsToReadData);
+
+    /**
+     * @brief API to write keyword's value on hardware.
+     *
+     * @param[in] i_paramsToWriteData - Data required to perform write.
+     *
+     * @throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument.
+     * @throw sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed.
+     * @throw DataException
+     * @throw EccException
+     *
+     *
+     * @return On success returns number of bytes written on hardware, On
+     * failure throws exception.
+     */
+    int writeKeywordOnHardware(const types::WriteVpdParams i_paramsToWriteData);
+
+  private:
+    /**
+     * @brief Check ECC of VPD header.
+     *
+     * @return true/false based on check result.
+     */
+    bool vhdrEccCheck();
+
+    /**
+     * @brief Check ECC of VTOC.
+     *
+     * @return true/false based on check result.
+     */
+    bool vtocEccCheck();
+
+    /**
+     * @brief Check ECC of a record.
+     *
+     * Note: Throws exception in case of failure. Caller need to handle as
+     * required.
+     *
+     * @param[in] iterator - Iterator to the record.
+     * @return success/failre
+     */
+    bool recordEccCheck(types::BinaryVector::const_iterator iterator);
+
+    /**
+     * @brief API to read VTOC record.
+     *
+     * The API reads VTOC record and returns the length of PT keyword.
+     *
+     * Note: Throws exception in case of any error. Caller need to handle as
+     * required.
+     *
+     * @param[in] itrToVPD - Iterator to begining of VPD data.
+     * @return Length of PT keyword.
+     */
+    auto readTOC(types::BinaryVector::const_iterator& itrToVPD);
+
+    /**
+     * @brief API to read PT record.
+     *
+     * Note: Throws exception in case ECC check fails.
+     *
+     * @param[in] itrToPT - Iterator to PT record in VPD vector.
+     * @param[in] ptLength - length of the PT record.
+     * @return List of record's offset.
+     */
+    types::RecordOffsetList readPT(types::BinaryVector::const_iterator& itrToPT,
+                                   auto ptLength);
+
+    /**
+     * @brief API to read keyword data based on its encoding type.
+     *
+     * @param[in] kwdName - Name of the keyword.
+     * @param[in] kwdDataLength - Length of keyword data.
+     * @param[in] itrToKwdData - Iterator to start of keyword data.
+     * @return keyword data, empty otherwise.
+     */
+    std::string readKwData(std::string_view kwdName, std::size_t kwdDataLength,
+                           types::BinaryVector::const_iterator itrToKwdData);
+
+    /**
+     * @brief API to read keyword and its value under a record.
+     *
+     * @param[in] iterator - pointer to the start of keywords under the record.
+     * @return keyword-value map of keywords under that record.
+     */
+    types::IPZVpdMap::mapped_type
+        readKeywords(types::BinaryVector::const_iterator& itrToKwds);
+
+    /**
+     * @brief API to process a record.
+     *
+     * @param[in] recordOffset - Offset of the record in VPD.
+     */
+    void processRecord(auto recordOffset);
+
+    /**
+     * @brief Get keyword's value from record
+     *
+     * @param[in] i_record - Record's name
+     * @param[in] i_keyword - Keyword's name
+     * @param[in] i_recordDataOffset - Record's offset value
+     *
+     * @throw std::runtime_error
+     *
+     * @return On success return bytes read, on failure throws error.
+     */
+    types::BinaryVector getKeywordValueFromRecord(
+        const types::Record& i_recordName, const types::Keyword& i_keywordName,
+        const types::RecordOffset& i_recordDataOffset);
+
+    /**
+     * @brief Get record's details from VTOC's PT keyword value
+     *
+     * This API parses through VTOC's PT keyword value and returns the given
+     * record's offset, record's length, ECC offset and ECC length.
+     *
+     * @param[in] i_record - Record's name.
+     * @param[in] i_vtocOffset - Offset to VTOC record
+     *
+     * @return On success return record's details, on failure return empty
+     * buffer.
+     */
+    types::RecordData
+        getRecordDetailsFromVTOC(const types::Record& l_recordName,
+                                 const types::RecordOffset& i_vtocOffset);
+
+    /**
+     * @brief API to update record's ECC
+     *
+     * This API is required to update the record's ECC based on the record's
+     * current data.
+     *
+     * @param[in] i_recordDataOffset - Record's data offset
+     * @param[in] i_recordDataLength - Record's data length
+     * @param[in] i_recordECCOffset - Record's ECC offset
+     * @param[in] i_recordECCLength - Record's ECC length
+     * @param[in,out] io_vpdVector - FRU VPD in vector to update record's ECC.
+     *
+     * @throw EccException
+     */
+    void updateRecordECC(const auto& i_recordDataOffset,
+                         const auto& i_recordDataLength,
+                         const auto& i_recordECCOffset,
+                         size_t i_recordECCLength,
+                         types::BinaryVector& io_vpdVector);
+
+    /**
+     * @brief API to set record's keyword's value on hardware.
+     *
+     * @param[in] i_recordName - Record name.
+     * @param[in] i_keywordName - Keyword name.
+     * @param[in] i_keywordData - Keyword data.
+     * @param[in] i_recordDataOffset - Offset to record's data.
+     * @param[in,out] io_vpdVector - FRU VPD in vector to read and write
+     * keyword's value.
+     *
+     * @throw DataException
+     *
+     * @return On success returns number of bytes set. On failure returns -1.
+     */
+    int setKeywordValueInRecord(const types::Record& i_recordName,
+                                const types::Keyword& i_keywordName,
+                                const types::BinaryVector& i_keywordData,
+                                const types::RecordOffset& i_recordDataOffset,
+                                types::BinaryVector& io_vpdVector);
+
+    // Holds VPD data.
+    const types::BinaryVector& m_vpdVector;
+
+    // stores parsed VPD data.
+    types::IPZVpdMap m_parsedVPDMap{};
+
+    // Holds the VPD file path
+    const std::string& m_vpdFilePath;
+
+    // Stream to the VPD file. Required to correct ECC
+    std::fstream m_vpdFileStream;
+
+    // VPD start offset. Required for ECC correction.
+    size_t m_vpdStartOffset = 0;
+};
+} // namespace vpd
diff --git a/vpd-manager/include/isdimm_parser.hpp b/vpd-manager/include/isdimm_parser.hpp
new file mode 100644
index 0000000..091285c
--- /dev/null
+++ b/vpd-manager/include/isdimm_parser.hpp
@@ -0,0 +1,150 @@
+#pragma once
+
+#include "parser_interface.hpp"
+#include "types.hpp"
+
+#include <string_view>
+
+namespace vpd
+{
+/**
+ * @brief Concrete class to implement JEDEC SPD parsing.
+ *
+ * The class inherits ParserInterface interface class and overrides the parser
+ * functionality to implement parsing logic for JEDEC SPD format.
+ */
+class JedecSpdParser : public ParserInterface
+{
+  public:
+    // Deleted API's
+    JedecSpdParser() = delete;
+    JedecSpdParser(const JedecSpdParser&) = delete;
+    JedecSpdParser& operator=(const JedecSpdParser&) = delete;
+    JedecSpdParser(JedecSpdParser&&) = delete;
+    JedecSpdParser& operator=(JedecSpdParser&&) = delete;
+    ~JedecSpdParser() = default;
+
+    /**
+     * @brief Constructor
+     *
+     * @param[in] i_spdVector - JEDEC SPD data.
+     */
+    explicit JedecSpdParser(const types::BinaryVector& i_spdVector) :
+        m_memSpd(i_spdVector)
+    {}
+
+    /**
+     * @brief Parse the memory SPD binary data.
+     *
+     * Collects and emplace the keyword-value pairs in map.
+     *
+     * @return map of keyword:value
+     */
+    types::VPDMapVariant parse();
+
+  private:
+    /**
+     * @brief An API to read keywords.
+     *
+     * @param[in] i_iterator - iterator to buffer containing SPD
+     * @return- map of kwd:value
+     */
+    types::JedecSpdMap
+        readKeywords(types::BinaryVector::const_iterator& i_iterator);
+
+    /**
+     * @brief This function calculates DIMM size from DDR4 SPD
+     *
+     * @param[in] i_iterator - iterator to buffer containing SPD
+     * @return calculated size or 0 in case of any error.
+     */
+    auto getDDR4DimmCapacity(types::BinaryVector::const_iterator& i_iterator);
+
+    /**
+     * @brief This function calculates part number from DDR4 SPD
+     *
+     * @param[in] i_iterator - iterator to buffer containing SPD
+     * @return calculated part number or a default value.
+     */
+    std::string_view
+        getDDR4PartNumber(types::BinaryVector::const_iterator& i_iterator);
+
+    /**
+     * @brief This function calculates serial number from DDR4 SPD
+     *
+     * @param[in] i_iterator - iterator to buffer containing SPD
+     * @return calculated serial number or a default value.
+     */
+    std::string
+        getDDR4SerialNumber(types::BinaryVector::const_iterator& i_iterator);
+
+    /**
+     * @brief This function allocates FRU number based on part number
+     *
+     * Mappings for FRU number from calculated part number is used
+     * for DDR4 ISDIMM.
+     *
+     * @param[in] i_partNumber - part number of the DIMM
+     * @param[in] i_iterator - iterator to buffer containing SPD
+     * @return allocated FRU number or a default value
+     */
+    std::string_view
+        getDDR4FruNumber(const std::string& i_partNumber,
+                         types::BinaryVector::const_iterator& i_iterator);
+
+    /**
+     * @brief This function allocates CCIN based on part number for DDR4 SPD
+     *
+     * @param[in] i_partNumber - part number of the DIMM
+     * @return allocated CCIN or a default value.
+     */
+    std::string_view getDDR4CCIN(const std::string& i_partNumber);
+
+    /**
+     * @brief This function calculates DIMM size from DDR5 SPD
+     *
+     * @param[in] i_iterator - iterator to buffer containing SPD
+     * @return calculated size or 0 in case of any error.
+     */
+    auto getDDR5DimmCapacity(types::BinaryVector::const_iterator& i_iterator);
+
+    /**
+     * @brief This function calculates part number from DDR5 SPD
+     *
+     * @param[in] i_iterator - iterator to buffer containing SPD
+     * @return calculated part number or a default value.
+     */
+    auto getDDR5PartNumber(types::BinaryVector::const_iterator& i_iterator);
+
+    /**
+     * @brief This function calculates serial number from DDR5 SPD
+     *
+     * @param[in] i_iterator - iterator to buffer containing SPD
+     * @return calculated serial number.
+     */
+    auto getDDR5SerialNumber(types::BinaryVector::const_iterator& i_iterator);
+
+    /**
+     * @brief This function allocates FRU number based on part number
+     *
+     * Mappings for FRU number from calculated part number is used
+     * for DDR5 ISDIMM.
+     *
+     * @param[in] i_partNumber - part number of the DIMM
+     * @return allocated FRU number.
+     */
+    auto getDDR5FruNumber(const std::string& i_partNumber);
+
+    /**
+     * @brief This function allocates CCIN based on part number for DDR5 SPD
+     *
+     * @param[in] i_partNumber - part number of the DIMM
+     * @return allocated CCIN.
+     */
+    auto getDDR5CCIN(const std::string& i_partNumber);
+
+    // SPD file to be parsed
+    const types::BinaryVector& m_memSpd;
+};
+
+} // namespace vpd
diff --git a/vpd-manager/include/keyword_vpd_parser.hpp b/vpd-manager/include/keyword_vpd_parser.hpp
new file mode 100644
index 0000000..ae30a34
--- /dev/null
+++ b/vpd-manager/include/keyword_vpd_parser.hpp
@@ -0,0 +1,97 @@
+#pragma once
+
+#include "parser_interface.hpp"
+#include "types.hpp"
+
+namespace vpd
+{
+
+/**
+ * @brief Concrete class to implement Keyword VPD parsing
+ *
+ * The class inherits ParserInterface class and overrides the parser
+ * functionality to implement parsing logic for Keyword VPD format.
+ */
+class KeywordVpdParser : public ParserInterface
+{
+  public:
+    KeywordVpdParser() = delete;
+    KeywordVpdParser(const KeywordVpdParser&) = delete;
+    KeywordVpdParser(KeywordVpdParser&&) = delete;
+    ~KeywordVpdParser() = default;
+
+    /**
+     * @brief Constructor
+     *
+     * @param kwVpdVector - move it to object's m_keywordVpdVector
+     */
+    KeywordVpdParser(const types::BinaryVector& kwVpdVector) :
+        m_keywordVpdVector(kwVpdVector),
+        m_vpdIterator(m_keywordVpdVector.begin())
+    {}
+
+    /**
+     * @brief A wrapper function to parse the keyword VPD binary data.
+     *
+     * It validates certain tags and checksum data, calls helper function
+     * to parse and emplace the data as keyword-value pairs in KeywordVpdMap.
+     *
+     * @throw DataException - VPD is not valid
+     * @return map of keyword:value
+     */
+    types::VPDMapVariant parse();
+
+  private:
+    /**
+     * @brief Parse the VPD data and emplace them as pair into the Map.
+     *
+     * @throw DataException - VPD data size is 0, check VPD
+     * @return map of keyword:value
+     */
+    types::KeywordVpdMap populateVpdMap();
+
+    /**
+     * @brief Validate checksum.
+     *
+     * Finding the 2's complement of sum of all the
+     * keywords,values and large resource identifier string.
+     *
+     * @param[in] i_checkSumStart - VPD iterator pointing at checksum start
+     * value
+     * @param[in] i_checkSumEnd - VPD iterator pointing at checksum end value
+     * @throw DataException - checksum invalid, check VPD
+     */
+    void validateChecksum(types::BinaryVector::const_iterator i_checkSumStart,
+                          types::BinaryVector::const_iterator i_checkSumEnd);
+
+    /**
+     * @brief It reads 2 bytes from current VPD pointer
+     *
+     * @return 2 bytes of VPD data
+     */
+    inline size_t getKwDataSize()
+    {
+        return (*(m_vpdIterator + 1) << 8 | *m_vpdIterator);
+    }
+
+    /**
+     * @brief Check for given number of bytes validity
+     *
+     * Check if number of elements from (begining of the vector) to (iterator +
+     * numberOfBytes) is lesser than or equal to the total no.of elements in
+     * the vector. This check is performed before advancement of the iterator.
+     *
+     * @param[in] numberOfBytes - no.of positions the iterator is going to be
+     * iterated
+     *
+     * @throw DataException - Truncated VPD data, check VPD.
+     */
+    void checkNextBytesValidity(uint8_t numberOfBytes);
+
+    /*Vector of keyword VPD data*/
+    const types::BinaryVector& m_keywordVpdVector;
+
+    /*Iterator to VPD data*/
+    types::BinaryVector::const_iterator m_vpdIterator;
+};
+} // namespace vpd
diff --git a/vpd-manager/include/logger.hpp b/vpd-manager/include/logger.hpp
new file mode 100644
index 0000000..a4160c1
--- /dev/null
+++ b/vpd-manager/include/logger.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <iostream>
+#include <source_location>
+#include <string_view>
+
+namespace vpd
+{
+/**
+ * @brief The namespace defines logging related methods for VPD.
+ */
+namespace logging
+{
+
+/**
+ * @brief An api to log message.
+ * This API should be called to log message. It will auto append information
+ * like file name, line and function name to the message being logged.
+ *
+ * @param[in] message - Information that we want  to log.
+ * @param[in] location - Object of source_location class.
+ */
+void logMessage(std::string_view message, const std::source_location& location =
+                                              std::source_location::current());
+} // namespace logging
+} // namespace vpd
diff --git a/vpd-manager/include/manager.hpp b/vpd-manager/include/manager.hpp
new file mode 100644
index 0000000..cb64123
--- /dev/null
+++ b/vpd-manager/include/manager.hpp
@@ -0,0 +1,300 @@
+#pragma once
+
+#include "constants.hpp"
+#include "gpio_monitor.hpp"
+#include "types.hpp"
+#include "worker.hpp"
+
+#include <sdbusplus/asio/object_server.hpp>
+
+namespace vpd
+{
+/**
+ * @brief Class to manage VPD processing.
+ *
+ * The class is responsible to implement methods to manage VPD on the system.
+ * It also implements methods to be exposed over D-Bus required to access/edit
+ * VPD data.
+ */
+class Manager
+{
+  public:
+    /**
+     * List of deleted methods.
+     */
+    Manager(const Manager&) = delete;
+    Manager& operator=(const Manager&) = delete;
+    Manager(Manager&&) = delete;
+
+    /**
+     * @brief Constructor.
+     *
+     * @param[in] ioCon - IO context.
+     * @param[in] iFace - interface to implement.
+     * @param[in] connection - Dbus Connection.
+     */
+    Manager(const std::shared_ptr<boost::asio::io_context>& ioCon,
+            const std::shared_ptr<sdbusplus::asio::dbus_interface>& iFace,
+            const std::shared_ptr<sdbusplus::asio::connection>& asioConnection);
+
+    /**
+     * @brief Destructor.
+     */
+    ~Manager() = default;
+
+    /**
+     * @brief Update keyword value.
+     *
+     * This API is used to update keyword value on the given input path and its
+     * redundant path(s) if any taken from system config JSON.
+     *
+     * To update IPZ type VPD, input parameter for writing should be in the form
+     * of (Record, Keyword, Value). Eg: ("VINI", "SN", {0x01, 0x02, 0x03}).
+     *
+     * To update Keyword type VPD, input parameter for writing should be in the
+     * form of (Keyword, Value). Eg: ("PE", {0x01, 0x02, 0x03}).
+     *
+     * @param[in] i_vpdPath - Path (inventory object path/FRU EEPROM path).
+     * @param[in] i_paramsToWriteData - Input details.
+     *
+     * @return On success returns number of bytes written, on failure returns
+     * -1.
+     */
+    int updateKeyword(const types::Path i_vpdPath,
+                      const types::WriteVpdParams i_paramsToWriteData);
+
+    /**
+     * @brief Update keyword value on hardware.
+     *
+     * This API is used to update keyword value on hardware. Updates only on the
+     * given input hardware path, does not look for corresponding redundant or
+     * primary path against the given path. To update corresponding paths, make
+     * separate call with respective path.
+     *
+     * To update IPZ type VPD, input parameter for writing should be in the form
+     * of (Record, Keyword, Value). Eg: ("VINI", "SN", {0x01, 0x02, 0x03}).
+     *
+     * To update Keyword type VPD, input parameter for writing should be in the
+     * form of (Keyword, Value). Eg: ("PE", {0x01, 0x02, 0x03}).
+     *
+     * @param[in] i_fruPath - EEPROM path of the FRU.
+     * @param[in] i_paramsToWriteData - Input details.
+     *
+     * @return On success returns number of bytes written, on failure returns
+     * -1.
+     */
+    int updateKeywordOnHardware(
+        const types::Path i_fruPath,
+        const types::WriteVpdParams i_paramsToWriteData) noexcept;
+
+    /**
+     * @brief Read keyword value.
+     *
+     * API can be used to read VPD keyword from the given input path.
+     *
+     * To read keyword of type IPZ, input parameter for reading should be in the
+     * form of (Record, Keyword). Eg: ("VINI", "SN").
+     *
+     * To read keyword from keyword type VPD, just keyword name has to be
+     * supplied in the input parameter. Eg: ("SN").
+     *
+     * @param[in] i_fruPath - EEPROM path.
+     * @param[in] i_paramsToReadData - Input details.
+     *
+     * @throw
+     * sdbusplus::xyz::openbmc_project::Common::Device::Error::ReadFailure.
+     *
+     * @return On success returns the read value in variant of array of bytes.
+     * On failure throws exception.
+     */
+    types::DbusVariantType
+        readKeyword(const types::Path i_fruPath,
+                    const types::ReadVpdParams i_paramsToReadData);
+
+    /**
+     * @brief Collect single FRU VPD
+     * API can be used to perform VPD collection for the given FRU, only if the
+     * current state of the system matches with the state at which the FRU is
+     * allowed for VPD recollection.
+     *
+     * @param[in] i_dbusObjPath - D-bus object path
+     */
+    void collectSingleFruVpd(
+        const sdbusplus::message::object_path& i_dbusObjPath);
+
+    /**
+     * @brief Delete single FRU VPD
+     * API can be used to perform VPD deletion for the given FRU.
+     *
+     * @param[in] i_dbusObjPath - D-bus object path
+     */
+    void deleteSingleFruVpd(
+        const sdbusplus::message::object_path& i_dbusObjPath);
+
+    /**
+     * @brief Get expanded location code.
+     *
+     * API to get expanded location code from the unexpanded location code.
+     *
+     * @param[in] i_unexpandedLocationCode - Unexpanded location code.
+     * @param[in] i_nodeNumber - Denotes the node in case of a multi-node
+     * configuration, defaulted to zero incase of single node system.
+     *
+     * @throw xyz.openbmc_project.Common.Error.InvalidArgument for
+     * invalid argument.
+     *
+     * @return Location code of the FRU.
+     */
+    std::string getExpandedLocationCode(
+        const std::string& i_unexpandedLocationCode,
+        [[maybe_unused]] const uint16_t i_nodeNumber = 0);
+
+    /**
+     * @brief Get D-Bus object path of FRUs from expanded location code.
+     *
+     * An API to get list of FRU D-Bus object paths for a given expanded
+     * location code.
+     *
+     * @param[in] i_expandedLocationCode - Expanded location code.
+     *
+     * @throw xyz.openbmc_project.Common.Error.InvalidArgument for
+     * invalid argument.
+     *
+     * @return List of FRUs D-Bus object paths for the given location code.
+     */
+    types::ListOfPaths getFrusByExpandedLocationCode(
+        const std::string& i_expandedLocationCode);
+
+    /**
+     * @brief Get D-Bus object path of FRUs from unexpanded location code.
+     *
+     * An API to get list of FRU D-Bus object paths for a given unexpanded
+     * location code.
+     *
+     * @param[in] i_unexpandedLocationCode - Unexpanded location code.
+     * @param[in] i_nodeNumber - Denotes the node in case of a multi-node
+     * configuration, defaulted to zero incase of single node system.
+     *
+     * @throw xyz.openbmc_project.Common.Error.InvalidArgument for
+     * invalid argument.
+     *
+     * @return List of FRUs D-Bus object paths for the given location code.
+     */
+    types::ListOfPaths getFrusByUnexpandedLocationCode(
+        const std::string& i_unexpandedLocationCode,
+        [[maybe_unused]] const uint16_t i_nodeNumber = 0);
+
+    /**
+     * @brief Get Hardware path
+     * API can be used to get EEPROM path for the given inventory path.
+     *
+     * @param[in] i_dbusObjPath - D-bus object path
+     *
+     * @return Corresponding EEPROM path.
+     */
+    std::string getHwPath(const sdbusplus::message::object_path& i_dbusObjPath);
+
+    /**
+     * @brief  Perform VPD recollection
+     * This api will trigger parser to perform VPD recollection for FRUs that
+     * can be replaced at standby.
+     */
+    void performVpdRecollection();
+
+    /**
+     * @brief Get unexpanded location code.
+     *
+     * An API to get unexpanded location code and node number from expanded
+     * location code.
+     *
+     * @param[in] i_expandedLocationCode - Expanded location code.
+     *
+     * @throw xyz.openbmc_project.Common.Error.InvalidArgument for
+     * invalid argument.
+     *
+     * @return Location code in unexpanded format and its node number.
+     */
+    std::tuple<std::string, uint16_t>
+        getUnexpandedLocationCode(const std::string& i_expandedLocationCode);
+
+  private:
+#ifdef IBM_SYSTEM
+    /**
+     * @brief API to set timer to detect system VPD over D-Bus.
+     *
+     * System VPD is required before bus name for VPD-Manager is claimed. Once
+     * system VPD is published, VPD for other FRUs should be collected. This API
+     * detects id system VPD is already published on D-Bus and based on that
+     * triggers VPD collection for rest of the FRUs.
+     *
+     * Note: Throws exception in case of any failure. Needs to be handled by the
+     * caller.
+     */
+    void SetTimerToDetectSVPDOnDbus();
+
+    /**
+     * @brief Set timer to detect and set VPD collection status for the system.
+     *
+     * Collection of FRU VPD is triggered in a separate thread. Resulting in
+     * multiple threads at  a given time. The API creates a timer which on
+     * regular interval will check if all the threads were collected back and
+     * sets the status of the VPD collection for the system accordingly.
+     *
+     * @throw std::runtime_error
+     */
+    void SetTimerToDetectVpdCollectionStatus();
+
+    /**
+     * @brief API to register callback for "AssetTag" property change.
+     */
+    void registerAssetTagChangeCallback();
+
+    /**
+     * @brief Callback API to be triggered on "AssetTag" property change.
+     *
+     * @param[in] i_msg - The callback message.
+     */
+    void processAssetTagChangeCallback(sdbusplus::message_t& i_msg);
+#endif
+
+    /**
+     * @brief An api to check validity of unexpanded location code.
+     *
+     * @param[in] i_locationCode - Unexpanded location code.
+     *
+     * @return True/False based on validity check.
+     */
+    bool isValidUnexpandedLocationCode(const std::string& i_locationCode);
+
+    /**
+     * @brief API to register callback for Host state change.
+     */
+    void registerHostStateChangeCallback();
+
+    /**
+     * @brief API to process host state change callback.
+     *
+     * @param[in] i_msg - Callback message.
+     */
+    void hostStateChangeCallBack(sdbusplus::message_t& i_msg);
+
+    // Shared pointer to asio context object.
+    const std::shared_ptr<boost::asio::io_context>& m_ioContext;
+
+    // Shared pointer to Dbus interface class.
+    const std::shared_ptr<sdbusplus::asio::dbus_interface>& m_interface;
+
+    // Shared pointer to bus connection.
+    const std::shared_ptr<sdbusplus::asio::connection>& m_asioConnection;
+
+    // Shared pointer to worker class
+    std::shared_ptr<Worker> m_worker;
+
+    // Shared pointer to GpioMonitor class
+    std::shared_ptr<GpioMonitor> m_gpioMonitor;
+
+    // Variable to hold current collection status
+    std::string m_vpdCollectionStatus = "NotStarted";
+};
+
+} // namespace vpd
diff --git a/vpd-manager/include/parser.hpp b/vpd-manager/include/parser.hpp
new file mode 100644
index 0000000..9af3088
--- /dev/null
+++ b/vpd-manager/include/parser.hpp
@@ -0,0 +1,126 @@
+#pragma once
+
+#include "parser_factory.hpp"
+#include "parser_interface.hpp"
+#include "types.hpp"
+
+#include <string.h>
+
+#include <nlohmann/json.hpp>
+
+#include <iostream>
+
+namespace vpd
+{
+/**
+ * @brief Class to implement a wrapper around concrete parser class.
+ * The class based on VPD file passed, selects the required parser and exposes
+ * API to parse the VPD and return the parsed data in required format to the
+ * caller.
+ */
+class Parser
+{
+  public:
+    /**
+     * @brief Constructor
+     *
+     * @param[in] vpdFilePath - Path to the VPD file.
+     * @param[in] parsedJson - Parsed JSON.
+     */
+    Parser(const std::string& vpdFilePath, nlohmann::json parsedJson);
+
+    /**
+     * @brief API to implement a generic parsing logic.
+     *
+     * This API is called to select parser based on the vpd data extracted from
+     * the VPD file path passed to the constructor of the class.
+     * It further parses the data based on the parser selected and returned
+     * parsed map to the caller.
+     */
+    types::VPDMapVariant parse();
+
+    /**
+     * @brief API to get parser instance based on VPD type.
+     *
+     * This API detects the VPD type based on the file path passed to the
+     * constructor of the class and returns the respective parser instance.
+     *
+     * @return Parser instance.
+     */
+    std::shared_ptr<vpd::ParserInterface> getVpdParserInstance();
+
+    /**
+     * @brief Update keyword value.
+     *
+     * This API is used to update keyword value on the EEPROM path and its
+     * redundant path(s) if any taken from system config JSON. And also updates
+     * keyword value on DBus.
+     *
+     * To update IPZ type VPD, input parameter for writing should be in the form
+     * of (Record, Keyword, Value). Eg: ("VINI", "SN", {0x01, 0x02, 0x03}).
+     *
+     * To update Keyword type VPD, input parameter for writing should be in the
+     * form of (Keyword, Value). Eg: ("PE", {0x01, 0x02, 0x03}).
+     *
+     * @param[in] i_paramsToWriteData - Input details.
+     *
+     * @return On success returns number of bytes written, on failure returns
+     * -1.
+     */
+    int updateVpdKeyword(const types::WriteVpdParams& i_paramsToWriteData);
+
+    /**
+     * @brief Update keyword value on hardware.
+     *
+     * This API is used to update keyword value on the hardware path.
+     *
+     * To update IPZ type VPD, input parameter for writing should be in the form
+     * of (Record, Keyword, Value). Eg: ("VINI", "SN", {0x01, 0x02, 0x03}).
+     *
+     * To update Keyword type VPD, input parameter for writing should be in the
+     * form of (Keyword, Value). Eg: ("PE", {0x01, 0x02, 0x03}).
+     *
+     * @param[in] i_paramsToWriteData - Input details.
+     *
+     * @return On success returns number of bytes written, on failure returns
+     * -1.
+     */
+    int updateVpdKeywordOnHardware(
+        const types::WriteVpdParams& i_paramsToWriteData);
+
+  private:
+    /**
+     * @brief Update keyword value on redundant path.
+     *
+     * This API is used to update keyword value on the given redundant path(s).
+     *
+     * To update IPZ type VPD, input parameter for writing should be in the form
+     * of (Record, Keyword, Value). Eg: ("VINI", "SN", {0x01, 0x02, 0x03}).
+     *
+     * To update Keyword type VPD, input parameter for writing should be in the
+     * form of (Keyword, Value). Eg: ("PE", {0x01, 0x02, 0x03}).
+     *
+     * @param[in] i_fruPath - Redundant EEPROM path.
+     * @param[in] i_paramsToWriteData - Input details.
+     *
+     * @return On success returns number of bytes written, on failure returns
+     * -1.
+     */
+    int updateVpdKeywordOnRedundantPath(
+        const std::string& i_fruPath,
+        const types::WriteVpdParams& i_paramsToWriteData);
+
+    // holds offfset to VPD if applicable.
+    size_t m_vpdStartOffset = 0;
+
+    // Path to the VPD file
+    const std::string& m_vpdFilePath;
+
+    // Path to configuration file, can be empty.
+    nlohmann::json m_parsedJson;
+
+    // Vector to hold VPD.
+    types::BinaryVector m_vpdVector;
+
+}; // parser
+} // namespace vpd
diff --git a/vpd-manager/include/parser_factory.hpp b/vpd-manager/include/parser_factory.hpp
new file mode 100644
index 0000000..819ec59
--- /dev/null
+++ b/vpd-manager/include/parser_factory.hpp
@@ -0,0 +1,50 @@
+#pragma once
+
+#include "logger.hpp"
+#include "parser_interface.hpp"
+#include "types.hpp"
+
+#include <memory>
+
+namespace vpd
+{
+/**
+ * @brief Factory calss to instantiate concrete parser class.
+ *
+ * This class should be used to instantiate an instance of parser class based
+ * on the type of vpd file.
+ */
+class ParserFactory
+{
+  public:
+    // Deleted APIs
+    ParserFactory() = delete;
+    ~ParserFactory() = delete;
+    ParserFactory(const ParserFactory&) = delete;
+    ParserFactory& operator=(const ParserFactory&) = delete;
+    ParserFactory(ParserFactory&&) = delete;
+    ParserFactory& operator=(ParserFactory&&) = delete;
+
+    /**
+     * @brief An API to get object of concrete parser class.
+     *
+     * The method is used to get object of respective parser class based on the
+     * type of VPD extracted from VPD vector passed to the API.
+     * To detect respective parser from VPD vector, add logic into the API
+     * vpdTypeCheck.
+     *
+     * Note: API throws DataException in case vpd type check fails for any
+     * unknown type. Caller responsibility to handle the exception.
+     *
+     * @param[in] i_vpdVector - vpd file content to check for the type.
+     * @param[in] i_vpdFilePath - FRU EEPROM path.
+     * @param[in] i_vpdStartOffset - Offset from where VPD starts in the VPD
+     * file.
+     *
+     * @return - Pointer to concrete parser class object.
+     */
+    static std::shared_ptr<ParserInterface>
+        getParser(const types::BinaryVector& i_vpdVector,
+                  const std::string& i_vpdFilePath, size_t i_vpdStartOffset);
+};
+} // namespace vpd
diff --git a/vpd-manager/include/parser_interface.hpp b/vpd-manager/include/parser_interface.hpp
new file mode 100644
index 0000000..0ff2862
--- /dev/null
+++ b/vpd-manager/include/parser_interface.hpp
@@ -0,0 +1,69 @@
+#pragma once
+
+#include "types.hpp"
+
+#include <variant>
+
+namespace vpd
+{
+/**
+ * @brief Interface class for parsers.
+ *
+ * Any concrete parser class, implementing parsing logic need to derive from
+ * this interface class and override the parse method declared in this class.
+ */
+class ParserInterface
+{
+  public:
+    /**
+     * @brief Pure virtual function for parsing VPD file.
+     *
+     * The API needs to be overridden by all the classes deriving from parser
+     * inerface class to implement respective VPD parsing logic.
+     *
+     * @return parsed format for VPD data, depending upon the
+     * parsing logic.
+     */
+    virtual types::VPDMapVariant parse() = 0;
+
+    /**
+     * @brief Read keyword's value from hardware
+     *
+     * @param[in] types::ReadVpdParams - Parameters required to perform read.
+     *
+     * @return keyword's value on successful read. Exception on failure.
+     */
+    virtual types::DbusVariantType
+        readKeywordFromHardware(const types::ReadVpdParams)
+    {
+        return types::DbusVariantType();
+    }
+
+    /**
+     * @brief API to write keyword's value on hardware.
+     *
+     * This virtual method is created to achieve runtime polymorphism for
+     * hardware writes on VPD of different types. This virtual method can be
+     * redefined at derived classess to implement write according to the type of
+     * VPD.
+     *
+     * @param[in] i_paramsToWriteData - Data required to perform write.
+     *
+     * @throw May throw exception depending on the implementation of derived
+     * methods.
+     * @return On success returns number of bytes written on hardware, On
+     * failure returns -1.
+     */
+    virtual int
+        writeKeywordOnHardware(const types::WriteVpdParams i_paramsToWriteData)
+    {
+        (void)i_paramsToWriteData;
+        return -1;
+    }
+
+    /**
+     * @brief Virtual destructor.
+     */
+    virtual ~ParserInterface() {}
+};
+} // namespace vpd
diff --git a/vpd-manager/include/types.hpp b/vpd-manager/include/types.hpp
new file mode 100644
index 0000000..314aebd
--- /dev/null
+++ b/vpd-manager/include/types.hpp
@@ -0,0 +1,192 @@
+#pragma once
+
+#include <phosphor-logging/elog-errors.hpp>
+#include <sdbusplus/asio/property.hpp>
+#include <sdbusplus/server.hpp>
+#include <xyz/openbmc_project/Common/Device/error.hpp>
+#include <xyz/openbmc_project/Common/error.hpp>
+
+#include <tuple>
+#include <unordered_map>
+#include <variant>
+
+namespace vpd
+{
+namespace types
+{
+
+using BiosProperty = std::tuple<
+    std::string, bool, std::string, std::string, std::string,
+    std::variant<int64_t, std::string>, std::variant<int64_t, std::string>,
+    std::vector<std::tuple<std::string, std::variant<int64_t, std::string>,
+                           std::string>>>;
+using BiosBaseTable =
+    std::variant<std::monostate, std::map<std::string, BiosProperty>>;
+using BiosBaseTableType = std::map<std::string, BiosBaseTable>;
+using BiosAttributeCurrentValue =
+    std::variant<std::monostate, int64_t, std::string>;
+using BiosAttributePendingValue = std::variant<int64_t, std::string>;
+using BiosGetAttrRetType = std::tuple<std::string, BiosAttributeCurrentValue,
+                                      BiosAttributePendingValue>;
+using PendingBIOSAttrItem =
+    std::pair<std::string, std::tuple<std::string, BiosAttributePendingValue>>;
+using PendingBIOSAttrs = std::vector<PendingBIOSAttrItem>;
+
+using BinaryVector = std::vector<uint8_t>;
+
+// This covers mostly all the data type supported over Dbus for a property.
+// clang-format off
+using DbusVariantType = std::variant<
+    std::vector<std::tuple<std::string, std::string, std::string>>,
+    std::vector<std::string>,
+    std::vector<double>,
+    std::string,
+    int64_t,
+    uint64_t,
+    double,
+    int32_t,
+    uint32_t,
+    int16_t,
+    uint16_t,
+    uint8_t,
+    bool,
+    BinaryVector,
+    std::vector<uint32_t>,
+    std::vector<uint16_t>,
+    sdbusplus::message::object_path,
+    std::tuple<uint64_t, std::vector<std::tuple<std::string, std::string, double, uint64_t>>>,
+    std::vector<std::tuple<std::string, std::string>>,
+    std::vector<std::tuple<uint32_t, std::vector<uint32_t>>>,
+    std::vector<std::tuple<uint32_t, size_t>>,
+    std::vector<std::tuple<sdbusplus::message::object_path, std::string,
+                           std::string, std::string>>,
+    PendingBIOSAttrs
+ >;
+
+using MapperGetObject =
+    std::vector<std::pair<std::string, std::vector<std::string>>>;
+using MapperGetSubTree = std::map<std::string, std::map<std::string, std::vector<std::string>>>;
+
+/* A type for holding the innermost map of property::value.*/
+using IPZKwdValueMap = std::unordered_map<std::string, std::string>;
+/*IPZ VPD Map of format <Record name, <keyword, value>>*/
+using IPZVpdMap = std::unordered_map<std::string, IPZKwdValueMap>;
+
+/*Value types supported by Keyword VPD*/
+using KWdVPDValueType = std::variant<BinaryVector,std::string, size_t>;
+/* This hold map of parsed data of keyword VPD type*/
+using KeywordVpdMap = std::unordered_map<std::string, KWdVPDValueType>;
+
+/**
+ * Both Keyword VPD parser and DDIMM parser stores the
+ * parsed VPD in the same format.
+ * To have better readability, two types are defined for underneath data structure.
+*/
+using DdimmVpdMap = KeywordVpdMap;
+
+/**
+ * Both Keyword VPD parser and ISDIMM parser stores the
+ * parsed SPD in the same format.
+*/
+using JedecSpdMap = KeywordVpdMap;
+
+/**
+ * Type to hold keyword::value map of a VPD.
+ * Variant can be extended to support additional type.
+*/
+using VPDKWdValueMap = std::variant<IPZKwdValueMap, KeywordVpdMap>;
+
+/* Map<Property, Value>*/
+using PropertyMap = std::map<std::string, DbusVariantType>;
+/* Map<Interface<Property, Value>>*/
+using InterfaceMap = std::map<std::string, PropertyMap>;
+using ObjectMap = std::map<sdbusplus::message::object_path, InterfaceMap>;
+
+using KwSize = uint8_t;
+using RecordId = uint8_t;
+using RecordSize = uint16_t;
+using RecordType = uint16_t;
+using RecordOffset = uint16_t;
+using RecordLength = uint16_t;
+using ECCOffset = uint16_t;
+using ECCLength = uint16_t;
+using PoundKwSize = uint16_t;
+
+using RecordOffsetList = std::vector<uint32_t>;
+
+using VPDMapVariant = std::variant<std::monostate, IPZVpdMap, KeywordVpdMap>;
+
+using HWVerList = std::vector<std::pair<std::string, std::string>>;
+/**
+ * Map of <systemIM, pair<Default version, vector<HW version, JSON suffix>>>
+*/
+using SystemTypeMap =
+    std::unordered_map<std::string, std::pair<std::string, HWVerList>>;
+
+using Path = std::string;
+using Record = std::string;
+using Keyword = std::string;
+
+using IpzData = std::tuple<Record, Keyword, BinaryVector>;
+using KwData = std::tuple<Keyword, BinaryVector>;
+using VpdData = std::variant<IpzData, KwData>;
+
+using IpzType = std::tuple<Record, Keyword>;
+using ReadVpdParams = std::variant<IpzType, Keyword>;
+using WriteVpdParams = std::variant<IpzData, KwData>;
+
+using ListOfPaths = std::vector<sdbusplus::message::object_path>;
+using RecordData = std::tuple<RecordOffset, RecordLength, ECCOffset, ECCLength>;
+
+using DbusInvalidArgument =
+    sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
+using DbusNotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
+
+using InvalidArgument = phosphor::logging::xyz::openbmc_project::Common::InvalidArgument;
+
+namespace DeviceError = sdbusplus::xyz::openbmc_project::Common::Device::Error;
+
+/* PEL Severity enum as defined in [xyz.openbmc_project.Logging.Entry.Level]log.hpp from 'phosphor-logging' repo. */
+enum SeverityType
+{
+    Notice,
+    Informational,
+    Debug,
+    Warning,
+    Critical,
+    Emergency,
+    Alert,
+    Error
+};
+
+/* PEL callout priority from 'phosphor-logging' pel_types.hpp. If any change in 'phosphor-logging', it needs update here as well. */
+enum CalloutPriority
+{
+    High,
+    Medium,
+    MediumGroupA,
+    MediumGroupB,
+    MediumGroupC,
+    Low
+};
+
+/* The Message property of the event entry for creating PEL, to introduce new message needs to be added in 'phosphor-logging' message_registry.json as well. */
+enum ErrorType
+{
+    DefaultValue,
+    InvalidVpdMessage,
+    VpdMismatch,
+    InvalidEeprom,
+    EccCheckFailed,
+    JsonFailure,
+    DbusFailure,
+    InvalidSystem,
+    EssentialFru,
+    GpioError
+};
+
+using InventoryCalloutData = std::tuple<std::string, CalloutPriority>;
+using DeviceCalloutData = std::tuple<std::string, std::string>;
+using I2cBusCalloutData = std::tuple<std::string, std::string, std::string>;
+} // namespace types
+} // namespace vpd
diff --git a/vpd-manager/include/utility/common_utility.hpp b/vpd-manager/include/utility/common_utility.hpp
new file mode 100644
index 0000000..15b33a2
--- /dev/null
+++ b/vpd-manager/include/utility/common_utility.hpp
@@ -0,0 +1,117 @@
+#pragma once
+
+#include "constants.hpp"
+#include "logger.hpp"
+
+#include <algorithm>
+#include <cstdio>
+#include <cstdlib>
+#include <vector>
+
+/**
+ * @brief Namespace to host common utility methods.
+ *
+ * A method qualifies as a common utility function if,
+ * A)It is being used by the utility namespace at the same level as well as
+ * other files directly.
+ * B) The utility should be a leaf node and should not be dependent on any other
+ * utility.
+ *                  *******************
+ *                  | Commmon Utility | - - - - - - -
+ *                  *******************              |
+ *                          /\                       |
+ *                         /  \                      |
+ *         ****************    ****************      |
+ *         | json utility |    | dbus utility |      |
+ *         ****************    ****************      |
+ *                 \                 /               |
+ *                  \               /                |
+ *               ************************            |
+ *               | Vpd specific Utility | - - - - - - -
+ *               ************************
+ */
+
+namespace vpd
+{
+
+namespace commonUtility
+{
+/** @brief Return the hex representation of the incoming byte.
+ *
+ * @param [in] i_aByte - The input byte.
+ * @returns Hex representation of the byte as a character.
+ */
+constexpr auto toHex(size_t i_aByte)
+{
+    constexpr auto l_map = "0123456789abcdef";
+    return l_map[i_aByte];
+}
+
+/**
+ * @brief API to return null at the end of variadic template args.
+ *
+ * @return empty string.
+ */
+inline std::string getCommand()
+{
+    return "";
+}
+
+/**
+ * @brief API to arrange create command.
+ *
+ * @param[in] arguments to create the command
+ * @return Command string
+ */
+template <typename T, typename... Types>
+inline std::string getCommand(T i_arg1, Types... i_args)
+{
+    std::string l_cmd = " " + i_arg1 + getCommand(i_args...);
+
+    return l_cmd;
+}
+
+/**
+ * @brief API to create shell command and execute.
+ *
+ * @throw std::runtime_error.
+ *
+ * @param[in] arguments for command
+ * @returns output of that command
+ */
+template <typename T, typename... Types>
+inline std::vector<std::string> executeCmd(T&& i_path, Types... i_args)
+{
+    std::vector<std::string> l_cmdOutput;
+    std::array<char, constants::CMD_BUFFER_LENGTH> l_buffer;
+
+    std::string l_cmd = i_path + getCommand(i_args...);
+
+    std::unique_ptr<FILE, decltype(&pclose)> l_cmdPipe(
+        popen(l_cmd.c_str(), "r"), pclose);
+
+    if (!l_cmdPipe)
+    {
+        logging::logMessage(
+            "popen failed with error " + std::string(strerror(errno)));
+        throw std::runtime_error("popen failed!");
+    }
+    while (fgets(l_buffer.data(), l_buffer.size(), l_cmdPipe.get()) != nullptr)
+    {
+        l_cmdOutput.emplace_back(l_buffer.data());
+    }
+
+    return l_cmdOutput;
+}
+
+/** @brief Converts string to lower case.
+ *
+ * @param [in] i_string - Input string.
+ */
+inline void toLower(std::string& i_string)
+{
+    std::transform(i_string.begin(), i_string.end(), i_string.begin(),
+                   [](unsigned char l_char) { return std::tolower(l_char); });
+}
+} // namespace commonUtility
+} // namespace vpd
diff --git a/vpd-manager/include/utility/dbus_utility.hpp b/vpd-manager/include/utility/dbus_utility.hpp
new file mode 100644
index 0000000..4c81815
--- /dev/null
+++ b/vpd-manager/include/utility/dbus_utility.hpp
@@ -0,0 +1,567 @@
+#pragma once
+
+#include "constants.hpp"
+#include "logger.hpp"
+#include "types.hpp"
+
+#include <chrono>
+
+namespace vpd
+{
+/**
+ * @brief The namespace defines utlity methods for generic D-Bus operations.
+ */
+namespace dbusUtility
+{
+
+/**
+ * @brief An API to get Map of service and interfaces for an object path.
+ *
+ * The API returns a Map of service name and interfaces for a given pair of
+ * object path and interface list. It can be used to determine service name
+ * which implemets a particular object path and interface.
+ *
+ * Note: It will be caller's responsibility to check for empty map returned and
+ * generate appropriate error.
+ *
+ * @param [in] objectPath - Object path under the service.
+ * @param [in] interfaces - Array of interface(s).
+ * @return - A Map of service name to object to interface(s), if success.
+ *           If failed,  empty map.
+ */
+inline types::MapperGetObject getObjectMap(const std::string& objectPath,
+                                           std::span<const char*> interfaces)
+{
+    types::MapperGetObject getObjectMap;
+
+    // interface list is optional argument, hence no check required.
+    if (objectPath.empty())
+    {
+        logging::logMessage("Path value is empty, invalid call to GetObject");
+        return getObjectMap;
+    }
+
+    try
+    {
+        auto bus = sdbusplus::bus::new_default();
+        auto method = bus.new_method_call(
+            "xyz.openbmc_project.ObjectMapper",
+            "/xyz/openbmc_project/object_mapper",
+            "xyz.openbmc_project.ObjectMapper", "GetObject");
+
+        method.append(objectPath, interfaces);
+        auto result = bus.call(method);
+        result.read(getObjectMap);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        // logging::logMessage(e.what());
+        return getObjectMap;
+    }
+
+    return getObjectMap;
+}
+
+/**
+ * @brief An API to get property map for an interface.
+ *
+ * This API returns a map of property and its value with respect to a particular
+ * interface.
+ *
+ * Note: It will be caller's responsibility to check for empty map returned and
+ * generate appropriate error.
+ *
+ * @param[in] i_service - Service name.
+ * @param[in] i_objectPath - object path.
+ * @param[in] i_interface - Interface, for the properties to be listed.
+ *
+ * @return - A map of property and value of an interface, if success.
+ *           if failed, empty map.
+ */
+inline types::PropertyMap getPropertyMap(const std::string& i_service,
+                                         const std::string& i_objectPath,
+                                         const std::string& i_interface)
+{
+    types::PropertyMap l_propertyValueMap;
+    if (i_service.empty() || i_objectPath.empty() || i_interface.empty())
+    {
+        logging::logMessage("Invalid parameters to get property map");
+        return l_propertyValueMap;
+    }
+
+    try
+    {
+        auto l_bus = sdbusplus::bus::new_default();
+        auto l_method =
+            l_bus.new_method_call(i_service.c_str(), i_objectPath.c_str(),
+                                  "org.freedesktop.DBus.Properties", "GetAll");
+        l_method.append(i_interface);
+        auto l_result = l_bus.call(l_method);
+        l_result.read(l_propertyValueMap);
+    }
+    catch (const sdbusplus::exception::SdBusError& l_ex)
+    {
+        logging::logMessage(l_ex.what());
+    }
+
+    return l_propertyValueMap;
+}
+
+/**
+ * @brief API to get object subtree from D-bus.
+ *
+ * The API returns the map of object, services and interfaces in the
+ * subtree that implement a certain interface. If no interfaces are provided
+ * then all the objects, services and interfaces under the subtree will
+ * be returned.
+ *
+ * Note: Depth can be 0 and interfaces can be null.
+ * It will be caller's responsibility to check for empty vector returned
+ * and generate appropriate error.
+ *
+ * @param[in] i_objectPath - Path to search for an interface.
+ * @param[in] i_depth - Maximum depth of the tree to search.
+ * @param[in] i_interfaces - List of interfaces to search.
+ *
+ * @return - A map of object and its related services and interfaces, if
+ *           success. If failed, empty map.
+ */
+
+inline types::MapperGetSubTree
+    getObjectSubTree(const std::string& i_objectPath, const int& i_depth,
+                     const std::vector<std::string>& i_interfaces)
+{
+    types::MapperGetSubTree l_subTreeMap;
+
+    if (i_objectPath.empty())
+    {
+        logging::logMessage("Object path is empty.");
+        return l_subTreeMap;
+    }
+
+    try
+    {
+        auto l_bus = sdbusplus::bus::new_default();
+        auto l_method = l_bus.new_method_call(
+            constants::objectMapperService, constants::objectMapperPath,
+            constants::objectMapperInf, "GetSubTree");
+        l_method.append(i_objectPath, i_depth, i_interfaces);
+        auto l_result = l_bus.call(l_method);
+        l_result.read(l_subTreeMap);
+    }
+    catch (const sdbusplus::exception::SdBusError& l_ex)
+    {
+        logging::logMessage(l_ex.what());
+    }
+
+    return l_subTreeMap;
+}
+
+/**
+ * @brief An API to read property from Dbus.
+ *
+ * The caller of the API needs to validate the validatity and correctness of the
+ * type and value of data returned. The API will just fetch and retun the data
+ * without any data validation.
+ *
+ * Note: It will be caller's responsibility to check for empty value returned
+ * and generate appropriate error if required.
+ *
+ * @param [in] serviceName - Name of the Dbus service.
+ * @param [in] objectPath - Object path under the service.
+ * @param [in] interface - Interface under which property exist.
+ * @param [in] property - Property whose value is to be read.
+ * @return - Value read from Dbus, if success.
+ *           If failed, empty variant.
+ */
+inline types::DbusVariantType readDbusProperty(
+    const std::string& serviceName, const std::string& objectPath,
+    const std::string& interface, const std::string& property)
+{
+    types::DbusVariantType propertyValue;
+
+    // Mandatory fields to make a read dbus call.
+    if (serviceName.empty() || objectPath.empty() || interface.empty() ||
+        property.empty())
+    {
+        logging::logMessage(
+            "One of the parameter to make Dbus read call is empty.");
+        return propertyValue;
+    }
+
+    try
+    {
+        auto bus = sdbusplus::bus::new_default();
+        auto method =
+            bus.new_method_call(serviceName.c_str(), objectPath.c_str(),
+                                "org.freedesktop.DBus.Properties", "Get");
+        method.append(interface, property);
+
+        auto result = bus.call(method);
+        result.read(propertyValue);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        return propertyValue;
+    }
+    return propertyValue;
+}
+
+/**
+ * @brief An API to write property on Dbus.
+ *
+ * The caller of this API needs to handle exception thrown by this method to
+ * identify any write failure. The API in no other way indicate write  failure
+ * to the caller.
+ *
+ * Note: It will be caller's responsibility ho handle the exception thrown in
+ * case of write failure and generate appropriate error.
+ *
+ * @param [in] serviceName - Name of the Dbus service.
+ * @param [in] objectPath - Object path under the service.
+ * @param [in] interface - Interface under which property exist.
+ * @param [in] property - Property whose value is to be written.
+ * @param [in] propertyValue - The value to be written.
+ */
+inline void writeDbusProperty(
+    const std::string& serviceName, const std::string& objectPath,
+    const std::string& interface, const std::string& property,
+    const types::DbusVariantType& propertyValue)
+{
+    // Mandatory fields to make a write dbus call.
+    if (serviceName.empty() || objectPath.empty() || interface.empty() ||
+        property.empty())
+    {
+        logging::logMessage(
+            "One of the parameter to make Dbus read call is empty.");
+
+        // caller need to handle the throw to ensure Dbus write success.
+        throw std::runtime_error("Dbus write failed, Parameter empty");
+    }
+
+    try
+    {
+        auto bus = sdbusplus::bus::new_default();
+        auto method =
+            bus.new_method_call(serviceName.c_str(), objectPath.c_str(),
+                                "org.freedesktop.DBus.Properties", "Set");
+        method.append(interface, property, propertyValue);
+        bus.call(method);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        logging::logMessage(e.what());
+
+        // caller needs to handle this throw to handle error in writing Dbus.
+        throw std::runtime_error("Dbus write failed");
+    }
+}
+
+/**
+ * @brief API to publish data on PIM
+ *
+ * The API calls notify on PIM object to publlish VPD.
+ *
+ * @param[in] objectMap - Object, its interface and data.
+ * @return bool - Status of call to PIM notify.
+ */
+inline bool callPIM(types::ObjectMap&& objectMap)
+{
+    try
+    {
+        for (const auto& l_objectKeyValue : objectMap)
+        {
+            auto l_nodeHandle = objectMap.extract(l_objectKeyValue.first);
+
+            if (l_nodeHandle.key().str.find(constants::pimPath, 0) !=
+                std::string::npos)
+            {
+                l_nodeHandle.key() = l_nodeHandle.key().str.replace(
+                    0, std::strlen(constants::pimPath), "");
+                objectMap.insert(std::move(l_nodeHandle));
+            }
+        }
+
+        auto bus = sdbusplus::bus::new_default();
+        auto pimMsg =
+            bus.new_method_call(constants::pimServiceName, constants::pimPath,
+                                constants::pimIntf, "Notify");
+        pimMsg.append(std::move(objectMap));
+        bus.call(pimMsg);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        return false;
+    }
+    return true;
+}
+
+/**
+ * @brief API to check if a D-Bus service is running or not.
+ *
+ * Any failure in calling the method "NameHasOwner" implies that the service is
+ * not in a running state. Hence the API returns false in case of any exception
+ * as well.
+ *
+ * @param[in] i_serviceName - D-Bus service name whose status is to be checked.
+ * @return bool - True if the service is running, false otherwise.
+ */
+inline bool isServiceRunning(const std::string& i_serviceName)
+{
+    bool l_retVal = false;
+
+    try
+    {
+        auto l_bus = sdbusplus::bus::new_default();
+        auto l_method = l_bus.new_method_call(
+            "org.freedesktop.DBus", "/org/freedesktop/DBus",
+            "org.freedesktop.DBus", "NameHasOwner");
+        l_method.append(i_serviceName);
+
+        l_bus.call(l_method).read(l_retVal);
+    }
+    catch (const sdbusplus::exception::SdBusError& l_ex)
+    {
+        logging::logMessage(
+            "Call to check service status failed with exception: " +
+            std::string(l_ex.what()));
+    }
+
+    return l_retVal;
+}
+
+/**
+ * @brief API to call "GetAttribute" method uner BIOS manager.
+ *
+ * The API reads the given attribuute from BIOS and returns a tuple of both
+ * current as well as pending value for that attribute.
+ * The API return only the current attribute value if found.
+ * API returns an empty variant of type BiosAttributeCurrentValue in case of any
+ * error.
+ *
+ * @param[in] i_attributeName - Attribute to be read.
+ * @return Tuple of PLDM attribute Type, current attribute value and pending
+ * attribute value.
+ */
+inline types::BiosAttributeCurrentValue
+    biosGetAttributeMethodCall(const std::string& i_attributeName)
+{
+    auto l_bus = sdbusplus::bus::new_default();
+    auto l_method = l_bus.new_method_call(
+        constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
+        constants::biosConfigMgrInterface, "GetAttribute");
+    l_method.append(i_attributeName);
+
+    types::BiosGetAttrRetType l_attributeVal;
+    try
+    {
+        auto l_result = l_bus.call(l_method);
+        l_result.read(std::get<0>(l_attributeVal), std::get<1>(l_attributeVal),
+                      std::get<2>(l_attributeVal));
+    }
+    catch (const sdbusplus::exception::SdBusError& l_ex)
+    {
+        logging::logMessage(
+            "Failed to read BIOS Attribute: " + i_attributeName +
+            " due to error " + std::string(l_ex.what()));
+
+        // TODO: Log an informational PEL here.
+    }
+
+    return std::get<1>(l_attributeVal);
+}
+
+/**
+ * @brief API to check if Chassis is powered on.
+ *
+ * This API queries Phosphor Chassis State Manager to know whether
+ * Chassis is powered on.
+ *
+ * @return true if chassis is powered on, false otherwise
+ */
+inline bool isChassisPowerOn()
+{
+    auto powerState = dbusUtility::readDbusProperty(
+        "xyz.openbmc_project.State.Chassis",
+        "/xyz/openbmc_project/state/chassis0",
+        "xyz.openbmc_project.State.Chassis", "CurrentPowerState");
+
+    if (auto curPowerState = std::get_if<std::string>(&powerState))
+    {
+        if ("xyz.openbmc_project.State.Chassis.PowerState.On" == *curPowerState)
+        {
+            return true;
+        }
+        return false;
+    }
+
+    /*
+        TODO: Add PEL.
+        Callout: Firmware callout
+        Type: Informational
+        Description: Chassis state can't be determined, defaulting to chassis
+        off. : e.what()
+    */
+    return false;
+}
+
+/**
+ * @brief API to check if host is in running state.
+ *
+ * This API reads the current host state from D-bus and returns true if the host
+ * is running.
+ *
+ * @return true if host is in running state. false otherwise.
+ */
+inline bool isHostRunning()
+{
+    const auto l_hostState = dbusUtility::readDbusProperty(
+        constants::hostService, constants::hostObjectPath,
+        constants::hostInterface, "CurrentHostState");
+
+    if (const auto l_currHostState = std::get_if<std::string>(&l_hostState))
+    {
+        if (*l_currHostState == constants::hostRunningState)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+/**
+ * @brief API to check if BMC is in ready state.
+ *
+ * This API reads the current state of BMC from D-bus and returns true if BMC is
+ * in ready state.
+ *
+ * @return true if BMC is ready, false otherwise.
+ */
+inline bool isBMCReady()
+{
+    const auto l_bmcState = dbusUtility::readDbusProperty(
+        constants::bmcStateService, constants::bmcZeroStateObject,
+        constants::bmcStateInterface, constants::currentBMCStateProperty);
+
+    if (const auto l_currBMCState = std::get_if<std::string>(&l_bmcState))
+    {
+        if (*l_currBMCState == constants::bmcReadyState)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+/**
+ * @brief An API to enable BMC reboot guard
+ *
+ * This API does a D-Bus method call to enable BMC reboot guard.
+ *
+ * @return On success, returns 0, otherwise returns -1.
+ */
+inline int EnableRebootGuard() noexcept
+{
+    int l_rc{constants::FAILURE};
+    try
+    {
+        auto l_bus = sdbusplus::bus::new_default();
+        auto l_method = l_bus.new_method_call(
+            constants::systemdService, constants::systemdObjectPath,
+            constants::systemdManagerInterface, "StartUnit");
+        l_method.append("reboot-guard-enable.service", "replace");
+        l_bus.call_noreply(l_method);
+        l_rc = constants::SUCCESS;
+    }
+    catch (const sdbusplus::exception::SdBusError& l_ex)
+    {
+        std::string l_errMsg =
+            "D-Bus call to enable BMC reboot guard failed for reason: ";
+        l_errMsg += l_ex.what();
+
+        logging::logMessage(l_errMsg);
+    }
+    return l_rc;
+}
+
+/**
+ * @brief An API to disable BMC reboot guard
+ *
+ * This API disables BMC reboot guard. This API has an inbuilt re-try mechanism.
+ * If Disable Reboot Guard fails, this API attempts to Disable Reboot Guard for
+ * 3 more times at an interval of 333ms.
+ *
+ * @return On success, returns 0, otherwise returns -1.
+ */
+inline int DisableRebootGuard() noexcept
+{
+    int l_rc{constants::FAILURE};
+
+    // A lambda which executes the DBus call to disable BMC reboot guard.
+    auto l_executeDisableRebootGuard = []() -> int {
+        int l_dBusCallRc{constants::FAILURE};
+        try
+        {
+            auto l_bus = sdbusplus::bus::new_default();
+            auto l_method = l_bus.new_method_call(
+                constants::systemdService, constants::systemdObjectPath,
+                constants::systemdManagerInterface, "StartUnit");
+            l_method.append("reboot-guard-disable.service", "replace");
+            l_bus.call_noreply(l_method);
+            l_dBusCallRc = constants::SUCCESS;
+        }
+        catch (const sdbusplus::exception::SdBusError& l_ex)
+        {}
+        return l_dBusCallRc;
+    };
+
+    if (constants::FAILURE == l_executeDisableRebootGuard())
+    {
+        std::function<void()> l_retryDisableRebootGuard;
+
+        // A lambda which tries to disable BMC reboot guard for 3 times at an
+        // interval of 333 ms.
+        l_retryDisableRebootGuard = [&]() {
+            constexpr int MAX_RETRIES{3};
+            static int l_numRetries{0};
+
+            if (l_numRetries < MAX_RETRIES)
+            {
+                l_numRetries++;
+                if (constants::FAILURE == l_executeDisableRebootGuard())
+                {
+                    // sleep for 333ms before next retry. This is just a random
+                    // value so that 3 re-tries * 333ms takes ~1 second in the
+                    // worst case.
+                    const std::chrono::milliseconds l_sleepTime{333};
+                    std::this_thread::sleep_for(l_sleepTime);
+                    l_retryDisableRebootGuard();
+                }
+                else
+                {
+                    l_numRetries = 0;
+                    l_rc = constants::SUCCESS;
+                }
+            }
+            else
+            {
+                // Failed to Disable Reboot Guard even after 3 retries.
+                logging::logMessage("Failed to Disable Reboot Guard after " +
+                                    std::to_string(MAX_RETRIES) + " re-tries");
+                l_numRetries = 0;
+            }
+        };
+
+        l_retryDisableRebootGuard();
+    }
+    else
+    {
+        l_rc = constants::SUCCESS;
+    }
+    return l_rc;
+}
+
+} // namespace dbusUtility
+} // namespace vpd
diff --git a/vpd-manager/include/utility/json_utility.hpp b/vpd-manager/include/utility/json_utility.hpp
new file mode 100644
index 0000000..3dab105
--- /dev/null
+++ b/vpd-manager/include/utility/json_utility.hpp
@@ -0,0 +1,1043 @@
+#pragma once
+
+#include "event_logger.hpp"
+#include "exceptions.hpp"
+#include "logger.hpp"
+#include "types.hpp"
+
+#include <gpiod.hpp>
+#include <nlohmann/json.hpp>
+#include <utility/common_utility.hpp>
+
+#include <fstream>
+#include <type_traits>
+#include <unordered_map>
+
+namespace vpd
+{
+namespace jsonUtility
+{
+
+// forward declaration of API for function map.
+bool processSystemCmdTag(const nlohmann::json& i_parsedConfigJson,
+                         const std::string& i_vpdFilePath,
+                         const std::string& i_baseAction,
+                         const std::string& i_flagToProcess);
+
+// forward declaration of API for function map.
+bool processGpioPresenceTag(
+    const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
+    const std::string& i_baseAction, const std::string& i_flagToProcess);
+
+// forward declaration of API for function map.
+bool procesSetGpioTag(const nlohmann::json& i_parsedConfigJson,
+                      const std::string& i_vpdFilePath,
+                      const std::string& i_baseAction,
+                      const std::string& i_flagToProcess);
+
+// Function pointers to process tags from config JSON.
+typedef bool (*functionPtr)(
+    const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
+    const std::string& i_baseAction, const std::string& i_flagToProcess);
+
+inline std::unordered_map<std::string, functionPtr> funcionMap{
+    {"gpioPresence", processGpioPresenceTag},
+    {"setGpio", procesSetGpioTag},
+    {"systemCmd", processSystemCmdTag}};
+
+/**
+ * @brief API to read VPD offset from JSON file.
+ *
+ * @param[in] i_sysCfgJsonObj - Parsed system config JSON object.
+ * @param[in] i_vpdFilePath - VPD file path.
+ * @return VPD offset if found in JSON, 0 otherwise.
+ */
+inline size_t getVPDOffset(const nlohmann::json& i_sysCfgJsonObj,
+                           const std::string& i_vpdFilePath)
+{
+    if (i_vpdFilePath.empty() || (i_sysCfgJsonObj.empty()) ||
+        (!i_sysCfgJsonObj.contains("frus")))
+    {
+        return 0;
+    }
+
+    if (i_sysCfgJsonObj["frus"].contains(i_vpdFilePath))
+    {
+        return i_sysCfgJsonObj["frus"][i_vpdFilePath].at(0).value("offset", 0);
+    }
+
+    const nlohmann::json& l_fruList =
+        i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+    for (const auto& l_fru : l_fruList.items())
+    {
+        const auto l_fruPath = l_fru.key();
+
+        // check if given path is redundant FRU path
+        if (i_vpdFilePath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
+                                 "redundantEeprom", ""))
+        {
+            // Return the offset of redundant EEPROM taken from JSON.
+            return i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("offset", 0);
+        }
+    }
+
+    return 0;
+}
+
+/**
+ * @brief API to parse respective JSON.
+ *
+ * Exception is thrown in case of JSON parse error.
+ *
+ * @param[in] pathToJson - Path to JSON.
+ * @return Parsed JSON.
+ */
+inline nlohmann::json getParsedJson(const std::string& pathToJson)
+{
+    if (pathToJson.empty())
+    {
+        throw std::runtime_error("Path to JSON is missing");
+    }
+
+    if (!std::filesystem::exists(pathToJson) ||
+        std::filesystem::is_empty(pathToJson))
+    {
+        throw std::runtime_error("Incorrect File Path or empty file");
+    }
+
+    std::ifstream jsonFile(pathToJson);
+    if (!jsonFile)
+    {
+        throw std::runtime_error("Failed to access Json path = " + pathToJson);
+    }
+
+    try
+    {
+        return nlohmann::json::parse(jsonFile);
+    }
+    catch (const nlohmann::json::parse_error& e)
+    {
+        throw std::runtime_error("Failed to parse JSON file");
+    }
+}
+
+/**
+ * @brief Get inventory object path from system config JSON.
+ *
+ * Given either D-bus inventory path/FRU EEPROM path/redundant EEPROM path,
+ * this API returns D-bus inventory path if present in JSON.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object
+ * @param[in] i_vpdPath - Path to where VPD is stored.
+ *
+ * @throw std::runtime_error.
+ *
+ * @return On success a valid path is returned, on failure an empty string is
+ * returned or an exception is thrown.
+ */
+inline std::string getInventoryObjPathFromJson(
+    const nlohmann::json& i_sysCfgJsonObj, const std::string& i_vpdPath)
+{
+    if (i_vpdPath.empty())
+    {
+        throw std::runtime_error("Path parameter is empty.");
+    }
+
+    if (!i_sysCfgJsonObj.contains("frus"))
+    {
+        throw std::runtime_error("Missing frus tag in system config JSON.");
+    }
+
+    // check if given path is FRU path
+    if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
+    {
+        return i_sysCfgJsonObj["frus"][i_vpdPath].at(0).value(
+            "inventoryPath", "");
+    }
+
+    const nlohmann::json& l_fruList =
+        i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+    for (const auto& l_fru : l_fruList.items())
+    {
+        const auto l_fruPath = l_fru.key();
+        const auto l_invObjPath =
+            i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("inventoryPath", "");
+
+        // check if given path is redundant FRU path or inventory path
+        if (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
+                             "redundantEeprom", "") ||
+            (i_vpdPath == l_invObjPath))
+        {
+            return l_invObjPath;
+        }
+    }
+    return std::string();
+}
+
+/**
+ * @brief Process "PostFailAction" defined in config JSON.
+ *
+ * In case there is some error in the processing of "preAction" execution and a
+ * set of procedure needs to be done as a part of post fail action. This base
+ * action can be defined in the config JSON for that FRU and it will be handled
+ * under this API.
+ *
+ * @param[in] i_parsedConfigJson - config JSON
+ * @param[in] i_vpdFilePath - EEPROM file path
+ * @param[in] i_flagToProcess - To identify which flag(s) needs to be processed
+ * under PostFailAction tag of config JSON.
+ * @return - success or failure
+ */
+inline bool executePostFailAction(const nlohmann::json& i_parsedConfigJson,
+                                  const std::string& i_vpdFilePath,
+                                  const std::string& i_flagToProcess)
+{
+    if (i_parsedConfigJson.empty() || i_vpdFilePath.empty() ||
+        i_flagToProcess.empty())
+    {
+        logging::logMessage(
+            "Invalid parameters. Abort processing for post fail action");
+
+        return false;
+    }
+
+    if (!(i_parsedConfigJson["frus"][i_vpdFilePath].at(0))["PostFailAction"]
+             .contains(i_flagToProcess))
+    {
+        logging::logMessage(
+            "Config JSON missing flag " + i_flagToProcess +
+            " to execute post fail action for path = " + i_vpdFilePath);
+
+        return false;
+    }
+
+    for (const auto& l_tags : (i_parsedConfigJson["frus"][i_vpdFilePath].at(
+             0))["PostFailAction"][i_flagToProcess]
+                                  .items())
+    {
+        auto itrToFunction = funcionMap.find(l_tags.key());
+        if (itrToFunction != funcionMap.end())
+        {
+            if (!itrToFunction->second(i_parsedConfigJson, i_vpdFilePath,
+                                       "PostFailAction", i_flagToProcess))
+            {
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+/**
+ * @brief Process "systemCmd" tag for a given FRU.
+ *
+ * The API will process "systemCmd" tag if it is defined in the config
+ * JSON for the given FRU.
+ *
+ * @param[in] i_parsedConfigJson - config JSON
+ * @param[in] i_vpdFilePath - EEPROM file path
+ * @param[in] i_baseAction - Base action for which this tag has been called.
+ * @param[in] i_flagToProcess - Flag nested under the base action for which this
+ * tag has been called.
+ * @return Execution status.
+ */
+inline bool processSystemCmdTag(
+    const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
+    const std::string& i_baseAction, const std::string& i_flagToProcess)
+{
+    if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
+        i_baseAction.empty() || i_flagToProcess.empty())
+    {
+        logging::logMessage(
+            "Invalid parameter. Abort processing of processSystemCmd.");
+        return false;
+    }
+
+    if (!((i_parsedConfigJson["frus"][i_vpdFilePath].at(
+               0)[i_baseAction][i_flagToProcess]["systemCmd"])
+              .contains("cmd")))
+    {
+        logging::logMessage(
+            "Config JSON missing required information to execute system command for EEPROM " +
+            i_vpdFilePath);
+
+        return false;
+    }
+
+    try
+    {
+        const std::string& l_systemCommand =
+            i_parsedConfigJson["frus"][i_vpdFilePath].at(
+                0)[i_baseAction][i_flagToProcess]["systemCmd"]["cmd"];
+
+        commonUtility::executeCmd(l_systemCommand);
+        return true;
+    }
+    catch (const std::exception& e)
+    {
+        std::string l_errMsg = "Process system tag failed for exception: ";
+        l_errMsg += e.what();
+
+        logging::logMessage(l_errMsg);
+        return false;
+    }
+}
+
+/**
+ * @brief Checks for presence of a given FRU using GPIO line.
+ *
+ * This API returns the presence information of the FRU corresponding to the
+ * given VPD file path by setting the presence pin.
+ *
+ * @param[in] i_parsedConfigJson - config JSON
+ * @param[in] i_vpdFilePath - EEPROM file path
+ * @param[in] i_baseAction - Base action for which this tag has been called.
+ * @param[in] i_flagToProcess - Flag nested under the base action for which this
+ * tag has been called.
+ * @return Execution status.
+ */
+inline bool processGpioPresenceTag(
+    const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
+    const std::string& i_baseAction, const std::string& i_flagToProcess)
+{
+    if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
+        i_baseAction.empty() || i_flagToProcess.empty())
+    {
+        logging::logMessage(
+            "Invalid parameter. Abort processing of processGpioPresence tag");
+        return false;
+    }
+
+    if (!(((i_parsedConfigJson["frus"][i_vpdFilePath].at(
+                0)[i_baseAction][i_flagToProcess]["gpioPresence"])
+               .contains("pin")) &&
+          ((i_parsedConfigJson["frus"][i_vpdFilePath].at(
+                0)[i_baseAction][i_flagToProcess]["gpioPresence"])
+               .contains("value"))))
+    {
+        logging::logMessage(
+            "Config JSON missing required information to detect presence for EEPROM " +
+            i_vpdFilePath);
+
+        return false;
+    }
+
+    // get the pin name
+    const std::string& l_presencePinName =
+        i_parsedConfigJson["frus"][i_vpdFilePath].at(
+            0)[i_baseAction][i_flagToProcess]["gpioPresence"]["pin"];
+
+    // get the pin value
+    uint8_t l_presencePinValue = i_parsedConfigJson["frus"][i_vpdFilePath].at(
+        0)[i_baseAction][i_flagToProcess]["gpioPresence"]["value"];
+
+    try
+    {
+        gpiod::line l_presenceLine = gpiod::find_line(l_presencePinName);
+
+        if (!l_presenceLine)
+        {
+            throw GpioException("Couldn't find the GPIO line.");
+        }
+
+        l_presenceLine.request({"Read the presence line",
+                                gpiod::line_request::DIRECTION_INPUT, 0});
+
+        return (l_presencePinValue == l_presenceLine.get_value());
+    }
+    catch (const std::exception& ex)
+    {
+        std::string l_errMsg = "Exception on GPIO line: ";
+        l_errMsg += l_presencePinName;
+        l_errMsg += " Reason: ";
+        l_errMsg += ex.what();
+        l_errMsg += " File: " + i_vpdFilePath + " Pel Logged";
+
+        // ToDo -- Update Internal Rc code.
+        EventLogger::createAsyncPelWithInventoryCallout(
+            types::ErrorType::GpioError, types::SeverityType::Informational,
+            {{getInventoryObjPathFromJson(i_parsedConfigJson, i_vpdFilePath),
+              types::CalloutPriority::High}},
+            std::source_location::current().file_name(),
+            std::source_location::current().function_name(), 0, l_errMsg,
+            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+
+        logging::logMessage(l_errMsg);
+
+        // Except when GPIO pin value is false, we go and try collecting the
+        // FRU VPD as we couldn't able to read GPIO pin value due to some
+        // error/exception. So returning true in error scenario.
+        return true;
+    }
+}
+
+/**
+ * @brief Process "setGpio" tag for a given FRU.
+ *
+ * This API enables the GPIO line.
+ *
+ * @param[in] i_parsedConfigJson - config JSON
+ * @param[in] i_vpdFilePath - EEPROM file path
+ * @param[in] i_baseAction - Base action for which this tag has been called.
+ * @param[in] i_flagToProcess - Flag nested under the base action for which this
+ * tag has been called.
+ * @return Execution status.
+ */
+inline bool procesSetGpioTag(
+    const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
+    const std::string& i_baseAction, const std::string& i_flagToProcess)
+{
+    if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
+        i_baseAction.empty() || i_flagToProcess.empty())
+    {
+        logging::logMessage(
+            "Invalid parameter. Abort processing of procesSetGpio.");
+        return false;
+    }
+
+    if (!(((i_parsedConfigJson["frus"][i_vpdFilePath].at(
+                0)[i_baseAction][i_flagToProcess]["setGpio"])
+               .contains("pin")) &&
+          ((i_parsedConfigJson["frus"][i_vpdFilePath].at(
+                0)[i_baseAction][i_flagToProcess]["setGpio"])
+               .contains("value"))))
+    {
+        logging::logMessage(
+            "Config JSON missing required information to set gpio line for EEPROM " +
+            i_vpdFilePath);
+
+        return false;
+    }
+
+    const std::string& l_pinName = i_parsedConfigJson["frus"][i_vpdFilePath].at(
+        0)[i_baseAction][i_flagToProcess]["setGpio"]["pin"];
+
+    // Get the value to set
+    uint8_t l_pinValue = i_parsedConfigJson["frus"][i_vpdFilePath].at(
+        0)[i_baseAction][i_flagToProcess]["setGpio"]["value"];
+
+    logging::logMessage(
+        "Setting GPIO: " + l_pinName + " to " + std::to_string(l_pinValue));
+    try
+    {
+        gpiod::line l_outputLine = gpiod::find_line(l_pinName);
+
+        if (!l_outputLine)
+        {
+            throw GpioException("Couldn't find GPIO line.");
+        }
+
+        l_outputLine.request(
+            {"FRU Action", ::gpiod::line_request::DIRECTION_OUTPUT, 0},
+            l_pinValue);
+        return true;
+    }
+    catch (const std::exception& ex)
+    {
+        std::string l_errMsg = "Exception on GPIO line: ";
+        l_errMsg += l_pinName;
+        l_errMsg += " Reason: ";
+        l_errMsg += ex.what();
+        l_errMsg += " File: " + i_vpdFilePath + " Pel Logged";
+
+        // ToDo -- Update Internal RC code
+        EventLogger::createAsyncPelWithInventoryCallout(
+            types::ErrorType::GpioError, types::SeverityType::Informational,
+            {{getInventoryObjPathFromJson(i_parsedConfigJson, i_vpdFilePath),
+              types::CalloutPriority::High}},
+            std::source_location::current().file_name(),
+            std::source_location::current().function_name(), 0, l_errMsg,
+            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+
+        logging::logMessage(l_errMsg);
+
+        return false;
+    }
+}
+
+/**
+ * @brief Process any action, if defined in config JSON.
+ *
+ * If any FRU(s) requires any special handling, then this base action can be
+ * defined for that FRU in the config JSON, processing of which will be handled
+ * in this API.
+ * Examples of action - preAction, PostAction etc.
+ *
+ * @param[in] i_parsedConfigJson - config JSON
+ * @param[in] i_action - Base action to be performed.
+ * @param[in] i_vpdFilePath - EEPROM file path
+ * @param[in] i_flagToProcess - To identify which flag(s) needs to be processed
+ * under PreAction tag of config JSON.
+ * @return - success or failure
+ */
+inline bool executeBaseAction(
+    const nlohmann::json& i_parsedConfigJson, const std::string& i_action,
+    const std::string& i_vpdFilePath, const std::string& i_flagToProcess)
+{
+    if (i_flagToProcess.empty() || i_action.empty() || i_vpdFilePath.empty() ||
+        !i_parsedConfigJson.contains("frus"))
+    {
+        logging::logMessage("Invalid parameter");
+        return false;
+    }
+
+    if (!i_parsedConfigJson["frus"].contains(i_vpdFilePath))
+    {
+        logging::logMessage(
+            "File path: " + i_vpdFilePath + " not found in JSON");
+        return false;
+    }
+
+    if (!i_parsedConfigJson["frus"][i_vpdFilePath].at(0).contains(i_action))
+    {
+        logging::logMessage("Action [" + i_action +
+                            "] not defined for file path:" + i_vpdFilePath);
+        return false;
+    }
+
+    if (!(i_parsedConfigJson["frus"][i_vpdFilePath].at(0))[i_action].contains(
+            i_flagToProcess))
+    {
+        logging::logMessage("Config JSON missing flag [" + i_flagToProcess +
+                            "] to execute action for path = " + i_vpdFilePath);
+
+        return false;
+    }
+
+    const nlohmann::json& l_tagsJson =
+        (i_parsedConfigJson["frus"][i_vpdFilePath].at(
+            0))[i_action][i_flagToProcess];
+
+    for (const auto& l_tag : l_tagsJson.items())
+    {
+        auto itrToFunction = funcionMap.find(l_tag.key());
+        if (itrToFunction != funcionMap.end())
+        {
+            if (!itrToFunction->second(i_parsedConfigJson, i_vpdFilePath,
+                                       i_action, i_flagToProcess))
+            {
+                // In case any of the tag fails to execute. Mark action
+                // as failed for that flag.
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+/**
+ * @brief Get redundant FRU path from system config JSON
+ *
+ * Given either D-bus inventory path/FRU path/redundant FRU path, this
+ * API returns the redundant FRU path taken from "redundantEeprom" tag from
+ * system config JSON.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ * @param[in] i_vpdPath - Path to where VPD is stored.
+ *
+ * @throw std::runtime_error.
+ * @return On success return valid path, on failure return empty string.
+ */
+inline std::string getRedundantEepromPathFromJson(
+    const nlohmann::json& i_sysCfgJsonObj, const std::string& i_vpdPath)
+{
+    if (i_vpdPath.empty())
+    {
+        throw std::runtime_error("Path parameter is empty.");
+    }
+
+    if (!i_sysCfgJsonObj.contains("frus"))
+    {
+        throw std::runtime_error("Missing frus tag in system config JSON.");
+    }
+
+    // check if given path is FRU path
+    if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
+    {
+        return i_sysCfgJsonObj["frus"][i_vpdPath].at(0).value(
+            "redundantEeprom", "");
+    }
+
+    const nlohmann::json& l_fruList =
+        i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+    for (const auto& l_fru : l_fruList.items())
+    {
+        const std::string& l_fruPath = l_fru.key();
+        const std::string& l_redundantFruPath =
+            i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("redundantEeprom",
+                                                           "");
+
+        // check if given path is inventory path or redundant FRU path
+        if ((i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("inventoryPath",
+                                                            "") == i_vpdPath) ||
+            (l_redundantFruPath == i_vpdPath))
+        {
+            return l_redundantFruPath;
+        }
+    }
+    return std::string();
+}
+
+/**
+ * @brief Get FRU EEPROM path from system config JSON
+ *
+ * Given either D-bus inventory path/FRU EEPROM path/redundant EEPROM path,
+ * this API returns FRU EEPROM path if present in JSON.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object
+ * @param[in] i_vpdPath - Path to where VPD is stored.
+ *
+ * @throw std::runtime_error.
+ *
+ * @return On success return valid path, on failure return empty string.
+ */
+inline std::string getFruPathFromJson(const nlohmann::json& i_sysCfgJsonObj,
+                                      const std::string& i_vpdPath)
+{
+    if (i_vpdPath.empty())
+    {
+        throw std::runtime_error("Path parameter is empty.");
+    }
+
+    if (!i_sysCfgJsonObj.contains("frus"))
+    {
+        throw std::runtime_error("Missing frus tag in system config JSON.");
+    }
+
+    // check if given path is FRU path
+    if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
+    {
+        return i_vpdPath;
+    }
+
+    const nlohmann::json& l_fruList =
+        i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+    for (const auto& l_fru : l_fruList.items())
+    {
+        const auto l_fruPath = l_fru.key();
+
+        // check if given path is redundant FRU path or inventory path
+        if (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
+                             "redundantEeprom", "") ||
+            (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
+                              "inventoryPath", "")))
+        {
+            return l_fruPath;
+        }
+    }
+    return std::string();
+}
+
+/**
+ * @brief An API to check backup and restore VPD is required.
+ *
+ * The API checks if there is provision for backup and restore mentioned in the
+ * system config JSON, by looking "backupRestoreConfigPath" tag.
+ * Checks if the path mentioned is a hardware path, by checking if the file path
+ * exists and size of contents in the path.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ *
+ * @return true if backup and restore is required, false otherwise.
+ */
+inline bool isBackupAndRestoreRequired(const nlohmann::json& i_sysCfgJsonObj)
+{
+    try
+    {
+        const std::string& l_backupAndRestoreCfgFilePath =
+            i_sysCfgJsonObj.value("backupRestoreConfigPath", "");
+        if (!l_backupAndRestoreCfgFilePath.empty() &&
+            std::filesystem::exists(l_backupAndRestoreCfgFilePath) &&
+            !std::filesystem::is_empty(l_backupAndRestoreCfgFilePath))
+        {
+            return true;
+        }
+    }
+    catch (std::exception& ex)
+    {
+        logging::logMessage(ex.what());
+    }
+    return false;
+}
+
+/** @brief API to check if an action is required for given EEPROM path.
+ *
+ * System config JSON can contain pre-action, post-action etc. like actions
+ * defined for an EEPROM path. The API will check if any such action is defined
+ * for the EEPROM.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ * @param[in] i_vpdFruPath - EEPROM path.
+ * @param[in] i_action - Action to be checked.
+ * @param[in] i_flowFlag - Denotes the flow w.r.t which the action should be
+ * triggered.
+ * @return - True if action is defined for the flow, false otherwise.
+ */
+inline bool isActionRequired(
+    const nlohmann::json& i_sysCfgJsonObj, const std::string& i_vpdFruPath,
+    const std::string& i_action, const std::string& i_flowFlag)
+{
+    if (i_vpdFruPath.empty() || i_action.empty() || i_flowFlag.empty())
+    {
+        logging::logMessage("Invalid parameters recieved.");
+        return false;
+    }
+
+    if (!i_sysCfgJsonObj.contains("frus"))
+    {
+        logging::logMessage("Invalid JSON object recieved.");
+        return false;
+    }
+
+    if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
+    {
+        logging::logMessage(
+            "JSON object does not contain EEPROM path " + i_vpdFruPath);
+        return false;
+    }
+
+    if ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)).contains(i_action))
+    {
+        if ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))[i_action].contains(
+                i_flowFlag))
+        {
+            return true;
+        }
+
+        logging::logMessage("Flow flag: [" + i_flowFlag +
+                            "], not found in JSON for path: " + i_vpdFruPath);
+        return false;
+    }
+    return false;
+}
+
+/**
+ * @brief An API to return list of FRUs that needs GPIO polling.
+ *
+ * An API that checks for the FRUs that requires GPIO polling and returns
+ * a list of FRUs that needs polling. Returns an empty list if there are
+ * no FRUs that requires polling.
+ *
+ * @throw std::runtime_error
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ *
+ * @return list of FRUs parameters that needs polling.
+ */
+inline std::vector<std::string>
+    getListOfGpioPollingFrus(const nlohmann::json& i_sysCfgJsonObj)
+{
+    if (i_sysCfgJsonObj.empty())
+    {
+        throw std::runtime_error("Invalid Parameters");
+    }
+
+    if (!i_sysCfgJsonObj.contains("frus"))
+    {
+        throw std::runtime_error("Missing frus section in system config JSON");
+    }
+
+    std::vector<std::string> l_gpioPollingRequiredFrusList;
+
+    for (const auto& l_fru : i_sysCfgJsonObj["frus"].items())
+    {
+        const auto l_fruPath = l_fru.key();
+
+        try
+        {
+            if (isActionRequired(i_sysCfgJsonObj, l_fruPath, "pollingRequired",
+                                 "hotPlugging"))
+            {
+                if (i_sysCfgJsonObj["frus"][l_fruPath]
+                        .at(0)["pollingRequired"]["hotPlugging"]
+                        .contains("gpioPresence"))
+                {
+                    l_gpioPollingRequiredFrusList.push_back(l_fruPath);
+                }
+            }
+        }
+        catch (const std::exception& l_ex)
+        {
+            logging::logMessage(l_ex.what());
+        }
+    }
+
+    return l_gpioPollingRequiredFrusList;
+}
+
+/**
+ * @brief Get all related path(s) to update keyword value.
+ *
+ * Given FRU EEPROM path/Inventory path needs keyword's value update, this API
+ * returns tuple of FRU EEPROM path, inventory path and redundant EEPROM path if
+ * exists in the system config JSON.
+ *
+ * Note: If the inventory object path or redundant EEPROM path(s) are not found
+ * in the system config JSON, corresponding fields will have empty value in the
+ * returning tuple.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ * @param[in,out] io_vpdPath - Inventory object path or FRU EEPROM path.
+ *
+ * @return On success returns tuple of EEPROM path, inventory path & redundant
+ * path, on failure returns tuple with given input path alone.
+ */
+inline std::tuple<std::string, std::string, std::string>
+    getAllPathsToUpdateKeyword(const nlohmann::json& i_sysCfgJsonObj,
+                               std::string io_vpdPath)
+{
+    types::Path l_inventoryObjPath;
+    types::Path l_redundantFruPath;
+    try
+    {
+        if (!i_sysCfgJsonObj.empty())
+        {
+            // Get hardware path from system config JSON.
+            const types::Path l_fruPath =
+                jsonUtility::getFruPathFromJson(i_sysCfgJsonObj, io_vpdPath);
+
+            if (!l_fruPath.empty())
+            {
+                io_vpdPath = l_fruPath;
+
+                // Get inventory object path from system config JSON
+                l_inventoryObjPath = jsonUtility::getInventoryObjPathFromJson(
+                    i_sysCfgJsonObj, l_fruPath);
+
+                // Get redundant hardware path if present in system config JSON
+                l_redundantFruPath =
+                    jsonUtility::getRedundantEepromPathFromJson(i_sysCfgJsonObj,
+                                                                l_fruPath);
+            }
+        }
+    }
+    catch (const std::exception& l_exception)
+    {
+        logging::logMessage(
+            "Failed to get all paths to update keyword value, error " +
+            std::string(l_exception.what()));
+    }
+    return std::make_tuple(io_vpdPath, l_inventoryObjPath, l_redundantFruPath);
+}
+
+/**
+ * @brief An API to get DBus service name.
+ *
+ * Given DBus inventory path, this API returns DBus service name if present in
+ * the JSON.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ * @param[in] l_inventoryPath - DBus inventory path.
+ *
+ * @return On success returns the service name present in the system config
+ * JSON, otherwise empty string.
+ *
+ * Note: Caller has to handle in case of empty string received.
+ */
+inline std::string getServiceName(const nlohmann::json& i_sysCfgJsonObj,
+                                  const std::string& l_inventoryPath)
+{
+    try
+    {
+        if (l_inventoryPath.empty())
+        {
+            throw std::runtime_error("Path parameter is empty.");
+        }
+
+        if (!i_sysCfgJsonObj.contains("frus"))
+        {
+            throw std::runtime_error("Missing frus tag in system config JSON.");
+        }
+
+        const nlohmann::json& l_listOfFrus =
+            i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+        for (const auto& l_frus : l_listOfFrus.items())
+        {
+            for (const auto& l_inventoryItem : l_frus.value())
+            {
+                if (l_inventoryPath.compare(l_inventoryItem["inventoryPath"]) ==
+                    constants::STR_CMP_SUCCESS)
+                {
+                    return l_inventoryItem["serviceName"];
+                }
+            }
+        }
+        throw std::runtime_error(
+            "Inventory path not found in the system config JSON");
+    }
+    catch (const std::exception& l_exception)
+    {
+        logging::logMessage(
+            "Error while getting DBus service name for given path " +
+            l_inventoryPath + ", error: " + std::string(l_exception.what()));
+        // TODO:log PEL
+    }
+    return std::string{};
+}
+
+/**
+ * @brief An API to check if a FRU is tagged as "powerOffOnly"
+ *
+ * Given the system config JSON and VPD FRU path, this API checks if the FRU
+ * VPD can be collected at Chassis Power Off state only.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ * @param[in] i_vpdFruPath - EEPROM path.
+ * @return - True if FRU VPD can be collected at Chassis Power Off state only.
+ *           False otherwise
+ */
+inline bool isFruPowerOffOnly(const nlohmann::json& i_sysCfgJsonObj,
+                              const std::string& i_vpdFruPath)
+{
+    if (i_vpdFruPath.empty())
+    {
+        logging::logMessage("FRU path is empty.");
+        return false;
+    }
+
+    if (!i_sysCfgJsonObj.contains("frus"))
+    {
+        logging::logMessage("Missing frus tag in system config JSON.");
+        return false;
+    }
+
+    if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
+    {
+        logging::logMessage("JSON object does not contain EEPROM path \'" +
+                            i_vpdFruPath + "\'");
+        return false;
+    }
+
+    return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
+                .contains("powerOffOnly") &&
+            (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)["powerOffOnly"]));
+}
+
+/**
+ * @brief API which tells if the FRU is replaceable at runtime
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ * @param[in] i_vpdFruPath - EEPROM path.
+ *
+ * @return true if FRU is replaceable at runtime. false otherwise.
+ */
+inline bool isFruReplaceableAtRuntime(const nlohmann::json& i_sysCfgJsonObj,
+                                      const std::string& i_vpdFruPath)
+{
+    try
+    {
+        if (i_vpdFruPath.empty())
+        {
+            throw std::runtime_error("Given FRU path is empty.");
+        }
+
+        if (i_sysCfgJsonObj.empty() || (!i_sysCfgJsonObj.contains("frus")))
+        {
+            throw std::runtime_error("Invalid system config JSON object.");
+        }
+
+        return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
+                    .contains("replaceableAtRuntime") &&
+                (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(
+                    0)["replaceableAtRuntime"]));
+    }
+    catch (const std::exception& l_error)
+    {
+        // TODO: Log PEL
+        logging::logMessage(l_error.what());
+    }
+
+    return false;
+}
+
+/**
+ * @brief API which tells if the FRU is replaceable at standby
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ * @param[in] i_vpdFruPath - EEPROM path.
+ *
+ * @return true if FRU is replaceable at standby. false otherwise.
+ */
+inline bool isFruReplaceableAtStandby(const nlohmann::json& i_sysCfgJsonObj,
+                                      const std::string& i_vpdFruPath)
+{
+    try
+    {
+        if (i_vpdFruPath.empty())
+        {
+            throw std::runtime_error("Given FRU path is empty.");
+        }
+
+        if (i_sysCfgJsonObj.empty() || (!i_sysCfgJsonObj.contains("frus")))
+        {
+            throw std::runtime_error("Invalid system config JSON object.");
+        }
+
+        return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
+                    .contains("replaceableAtStandby") &&
+                (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(
+                    0)["replaceableAtStandby"]));
+    }
+    catch (const std::exception& l_error)
+    {
+        // TODO: Log PEL
+        logging::logMessage(l_error.what());
+    }
+
+    return false;
+}
+
+/**
+ * @brief API to get list of FRUs replaceable at standby from JSON.
+ *
+ * The API will return a vector of FRUs inventory path which are replaceable at
+ * standby.
+ * The API can throw exception in case of error scenarios. Caller's
+ * responsibility to handle those exceptions.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ *
+ * @return - List of FRUs replaceable at standby.
+ */
+inline std::vector<std::string>
+    getListOfFrusReplaceableAtStandby(const nlohmann::json& i_sysCfgJsonObj)
+{
+    std::vector<std::string> l_frusReplaceableAtStandby;
+
+    if (!i_sysCfgJsonObj.contains("frus"))
+    {
+        logging::logMessage("Missing frus tag in system config JSON.");
+        return l_frusReplaceableAtStandby;
+    }
+
+    const nlohmann::json& l_fruList =
+        i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+    for (const auto& l_fru : l_fruList.items())
+    {
+        if (i_sysCfgJsonObj["frus"][l_fru.key()].at(0).value(
+                "replaceableAtStandby", false))
+        {
+            const std::string& l_inventoryObjectPath =
+                i_sysCfgJsonObj["frus"][l_fru.key()].at(0).value(
+                    "inventoryPath", "");
+
+            if (!l_inventoryObjectPath.empty())
+            {
+                l_frusReplaceableAtStandby.emplace_back(l_inventoryObjectPath);
+            }
+        }
+    }
+
+    return l_frusReplaceableAtStandby;
+}
+
+} // namespace jsonUtility
+} // namespace vpd
diff --git a/vpd-manager/include/utility/vpd_specific_utility.hpp b/vpd-manager/include/utility/vpd_specific_utility.hpp
new file mode 100644
index 0000000..d6b92fd
--- /dev/null
+++ b/vpd-manager/include/utility/vpd_specific_utility.hpp
@@ -0,0 +1,556 @@
+#pragma once
+
+#include "config.h"
+
+#include "constants.hpp"
+#include "exceptions.hpp"
+#include "logger.hpp"
+#include "types.hpp"
+
+#include <nlohmann/json.hpp>
+#include <utility/common_utility.hpp>
+#include <utility/dbus_utility.hpp>
+
+#include <filesystem>
+#include <fstream>
+#include <regex>
+
+namespace vpd
+{
+namespace vpdSpecificUtility
+{
+/**
+ * @brief API to generate file name for bad VPD.
+ *
+ * For i2c eeproms - the pattern of the vpd-name will be
+ * i2c-<bus-number>-<eeprom-address>.
+ * For spi eeproms - the pattern of the vpd-name will be spi-<spi-number>.
+ *
+ * @param[in] vpdFilePath - file path of the vpd.
+ * @return Generated file name.
+ */
+inline std::string generateBadVPDFileName(const std::string& vpdFilePath)
+{
+    std::string badVpdFileName = BAD_VPD_DIR;
+    if (vpdFilePath.find("i2c") != std::string::npos)
+    {
+        badVpdFileName += "i2c-";
+        std::regex i2cPattern("(at24/)([0-9]+-[0-9]+)\\/");
+        std::smatch match;
+        if (std::regex_search(vpdFilePath, match, i2cPattern))
+        {
+            badVpdFileName += match.str(2);
+        }
+    }
+    else if (vpdFilePath.find("spi") != std::string::npos)
+    {
+        std::regex spiPattern("((spi)[0-9]+)(.0)");
+        std::smatch match;
+        if (std::regex_search(vpdFilePath, match, spiPattern))
+        {
+            badVpdFileName += match.str(1);
+        }
+    }
+    return badVpdFileName;
+}
+
+/**
+ * @brief API which dumps the broken/bad vpd in a directory.
+ * When the vpd is bad, this API places  the bad vpd file inside
+ * "/tmp/bad-vpd" in BMC, in order to collect bad VPD data as a part of user
+ * initiated BMC dump.
+ *
+ * Note: Throws exception in case of any failure.
+ *
+ * @param[in] vpdFilePath - vpd file path
+ * @param[in] vpdVector - vpd vector
+ */
+inline void dumpBadVpd(const std::string& vpdFilePath,
+                       const types::BinaryVector& vpdVector)
+{
+    std::filesystem::create_directory(BAD_VPD_DIR);
+    auto badVpdPath = generateBadVPDFileName(vpdFilePath);
+
+    if (std::filesystem::exists(badVpdPath))
+    {
+        std::error_code ec;
+        std::filesystem::remove(badVpdPath, ec);
+        if (ec) // error code
+        {
+            std::string error = "Error removing the existing broken vpd in ";
+            error += badVpdPath;
+            error += ". Error code : ";
+            error += ec.value();
+            error += ". Error message : ";
+            error += ec.message();
+            throw std::runtime_error(error);
+        }
+    }
+
+    std::ofstream badVpdFileStream(badVpdPath, std::ofstream::binary);
+    if (badVpdFileStream.is_open())
+    {
+        throw std::runtime_error(
+            "Failed to open bad vpd file path in /tmp/bad-vpd. "
+            "Unable to dump the broken/bad vpd file.");
+    }
+
+    badVpdFileStream.write(reinterpret_cast<const char*>(vpdVector.data()),
+                           vpdVector.size());
+}
+
+/**
+ * @brief An API to read value of a keyword.
+ *
+ * Note: Throws exception. Caller needs to handle.
+ *
+ * @param[in] kwdValueMap - A map having Kwd value pair.
+ * @param[in] kwd - keyword name.
+ * @param[out] kwdValue - Value of the keyword read from map.
+ */
+inline void getKwVal(const types::IPZKwdValueMap& kwdValueMap,
+                     const std::string& kwd, std::string& kwdValue)
+{
+    if (kwd.empty())
+    {
+        logging::logMessage("Invalid parameters");
+        throw std::runtime_error("Invalid parameters");
+    }
+
+    auto itrToKwd = kwdValueMap.find(kwd);
+    if (itrToKwd != kwdValueMap.end())
+    {
+        kwdValue = itrToKwd->second;
+        return;
+    }
+
+    throw std::runtime_error("Keyword not found");
+}
+
+/**
+ * @brief An API to process encoding of a keyword.
+ *
+ * @param[in] keyword - Keyword to be processed.
+ * @param[in] encoding - Type of encoding.
+ * @return Value after being processed for encoded type.
+ */
+inline std::string encodeKeyword(const std::string& keyword,
+                                 const std::string& encoding)
+{
+    // Default value is keyword value
+    std::string result(keyword.begin(), keyword.end());
+
+    if (encoding == "MAC")
+    {
+        result.clear();
+        size_t firstByte = keyword[0];
+        result += commonUtility::toHex(firstByte >> 4);
+        result += commonUtility::toHex(firstByte & 0x0f);
+        for (size_t i = 1; i < keyword.size(); ++i)
+        {
+            result += ":";
+            result += commonUtility::toHex(keyword[i] >> 4);
+            result += commonUtility::toHex(keyword[i] & 0x0f);
+        }
+    }
+    else if (encoding == "DATE")
+    {
+        // Date, represent as
+        // <year>-<month>-<day> <hour>:<min>
+        result.clear();
+        static constexpr uint8_t skipPrefix = 3;
+
+        auto strItr = keyword.begin();
+        advance(strItr, skipPrefix);
+        for_each(strItr, keyword.end(), [&result](size_t c) { result += c; });
+
+        result.insert(constants::BD_YEAR_END, 1, '-');
+        result.insert(constants::BD_MONTH_END, 1, '-');
+        result.insert(constants::BD_DAY_END, 1, ' ');
+        result.insert(constants::BD_HOUR_END, 1, ':');
+    }
+
+    return result;
+}
+
+/**
+ * @brief Helper function to insert or merge in map.
+ *
+ * This method checks in an interface if the given interface exists. If the
+ * interface key already exists, property map is inserted corresponding to it.
+ * If the key does'nt exist then given interface and property map pair is newly
+ * created. If the property present in propertymap already exist in the
+ * InterfaceMap, then the new property value is ignored.
+ *
+ * @param[in,out] map - Interface map.
+ * @param[in] interface - Interface to be processed.
+ * @param[in] propertyMap - new property map that needs to be emplaced.
+ */
+inline void insertOrMerge(types::InterfaceMap& map,
+                          const std::string& interface,
+                          types::PropertyMap&& propertyMap)
+{
+    if (map.find(interface) != map.end())
+    {
+        try
+        {
+            auto& prop = map.at(interface);
+            std::for_each(propertyMap.begin(), propertyMap.end(),
+                          [&prop](auto l_keyValue) {
+                              prop[l_keyValue.first] = l_keyValue.second;
+                          });
+        }
+        catch (const std::exception& l_ex)
+        {
+            // ToDo:: Log PEL
+            logging::logMessage(
+                "Inserting properties into interface[" + interface +
+                "] map is failed, reason: " + std::string(l_ex.what()));
+        }
+    }
+    else
+    {
+        map.emplace(interface, propertyMap);
+    }
+}
+
+/**
+ * @brief API to expand unpanded location code.
+ *
+ * Note: The API handles all the exception internally, in case of any error
+ * unexpanded location code will be returned as it is.
+ *
+ * @param[in] unexpandedLocationCode - Unexpanded location code.
+ * @param[in] parsedVpdMap - Parsed VPD map.
+ * @return Expanded location code. In case of any error, unexpanded is returned
+ * as it is.
+ */
+inline std::string
+    getExpandedLocationCode(const std::string& unexpandedLocationCode,
+                            const types::VPDMapVariant& parsedVpdMap)
+{
+    auto expanded{unexpandedLocationCode};
+
+    try
+    {
+        // Expanded location code is formed by combining two keywords
+        // depending on type in unexpanded one. Second one is always "SE".
+        std::string kwd1, kwd2{constants::kwdSE};
+
+        // interface to search for required keywords;
+        std::string kwdInterface;
+
+        // record which holds the required keywords.
+        std::string recordName;
+
+        auto pos = unexpandedLocationCode.find("fcs");
+        if (pos != std::string::npos)
+        {
+            kwd1 = constants::kwdFC;
+            kwdInterface = constants::vcenInf;
+            recordName = constants::recVCEN;
+        }
+        else
+        {
+            pos = unexpandedLocationCode.find("mts");
+            if (pos != std::string::npos)
+            {
+                kwd1 = constants::kwdTM;
+                kwdInterface = constants::vsysInf;
+                recordName = constants::recVSYS;
+            }
+            else
+            {
+                throw std::runtime_error(
+                    "Error detecting type of unexpanded location code.");
+            }
+        }
+
+        std::string firstKwdValue, secondKwdValue;
+
+        if (auto ipzVpdMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap);
+            ipzVpdMap && (*ipzVpdMap).find(recordName) != (*ipzVpdMap).end())
+        {
+            auto itrToVCEN = (*ipzVpdMap).find(recordName);
+            // The exceptions will be cautght at end.
+            getKwVal(itrToVCEN->second, kwd1, firstKwdValue);
+            getKwVal(itrToVCEN->second, kwd2, secondKwdValue);
+        }
+        else
+        {
+            std::array<const char*, 1> interfaceList = {kwdInterface.c_str()};
+
+            types::MapperGetObject mapperRetValue = dbusUtility::getObjectMap(
+                std::string(constants::systemVpdInvPath), interfaceList);
+
+            if (mapperRetValue.empty())
+            {
+                throw std::runtime_error("Mapper failed to get service");
+            }
+
+            const std::string& serviceName = std::get<0>(mapperRetValue.at(0));
+
+            auto retVal = dbusUtility::readDbusProperty(
+                serviceName, std::string(constants::systemVpdInvPath),
+                kwdInterface, kwd1);
+
+            if (auto kwdVal = std::get_if<types::BinaryVector>(&retVal))
+            {
+                firstKwdValue.assign(
+                    reinterpret_cast<const char*>(kwdVal->data()),
+                    kwdVal->size());
+            }
+            else
+            {
+                throw std::runtime_error(
+                    "Failed to read value of " + kwd1 + " from Bus");
+            }
+
+            retVal = dbusUtility::readDbusProperty(
+                serviceName, std::string(constants::systemVpdInvPath),
+                kwdInterface, kwd2);
+
+            if (auto kwdVal = std::get_if<types::BinaryVector>(&retVal))
+            {
+                secondKwdValue.assign(
+                    reinterpret_cast<const char*>(kwdVal->data()),
+                    kwdVal->size());
+            }
+            else
+            {
+                throw std::runtime_error(
+                    "Failed to read value of " + kwd2 + " from Bus");
+            }
+        }
+
+        if (unexpandedLocationCode.find("fcs") != std::string::npos)
+        {
+            // TODO: See if ND0 can be placed in the JSON
+            expanded.replace(
+                pos, 3, firstKwdValue.substr(0, 4) + ".ND0." + secondKwdValue);
+        }
+        else
+        {
+            replace(firstKwdValue.begin(), firstKwdValue.end(), '-', '.');
+            expanded.replace(pos, 3, firstKwdValue + "." + secondKwdValue);
+        }
+    }
+    catch (const std::exception& ex)
+    {
+        logging::logMessage("Failed to expand location code with exception: " +
+                            std::string(ex.what()));
+    }
+
+    return expanded;
+}
+
+/**
+ * @brief An API to get VPD in a vector.
+ *
+ * The vector is required by the respective parser to fill the VPD map.
+ * Note: API throws exception in case of failure. Caller needs to handle.
+ *
+ * @param[in] vpdFilePath - EEPROM path of the FRU.
+ * @param[out] vpdVector - VPD in vector form.
+ * @param[in] vpdStartOffset - Offset of VPD data in EEPROM.
+ */
+inline void getVpdDataInVector(const std::string& vpdFilePath,
+                               types::BinaryVector& vpdVector,
+                               size_t& vpdStartOffset)
+{
+    try
+    {
+        std::fstream vpdFileStream;
+        vpdFileStream.exceptions(
+            std::ifstream::badbit | std::ifstream::failbit);
+        vpdFileStream.open(vpdFilePath, std::ios::in | std::ios::binary);
+        auto vpdSizeToRead = std::min(std::filesystem::file_size(vpdFilePath),
+                                      static_cast<uintmax_t>(65504));
+        vpdVector.resize(vpdSizeToRead);
+
+        vpdFileStream.seekg(vpdStartOffset, std::ios_base::beg);
+        vpdFileStream.read(reinterpret_cast<char*>(&vpdVector[0]),
+                           vpdSizeToRead);
+
+        vpdVector.resize(vpdFileStream.gcount());
+        vpdFileStream.clear(std::ios_base::eofbit);
+    }
+    catch (const std::ifstream::failure& fail)
+    {
+        std::cerr << "Exception in file handling [" << vpdFilePath
+                  << "] error : " << fail.what();
+        throw;
+    }
+}
+
+/**
+ * @brief An API to get D-bus representation of given VPD keyword.
+ *
+ * @param[in] i_keywordName - VPD keyword name.
+ *
+ * @return D-bus representation of given keyword.
+ */
+inline std::string getDbusPropNameForGivenKw(const std::string& i_keywordName)
+{
+    // Check for "#" prefixed VPD keyword.
+    if ((i_keywordName.size() == vpd::constants::TWO_BYTES) &&
+        (i_keywordName.at(0) == constants::POUND_KW))
+    {
+        // D-bus doesn't support "#". Replace "#" with "PD_" for those "#"
+        // prefixed keywords.
+        return (std::string(constants::POUND_KW_PREFIX) +
+                i_keywordName.substr(1));
+    }
+
+    // Return the keyword name back, if D-bus representation is same as the VPD
+    // keyword name.
+    return i_keywordName;
+}
+
+/**
+ * @brief API to find CCIN in parsed VPD map.
+ *
+ * Few FRUs need some special handling. To identify those FRUs CCIN are used.
+ * The API will check from parsed VPD map if the FRU is the one with desired
+ * CCIN.
+ *
+ * @throw std::runtime_error
+ * @throw DataException
+ *
+ * @param[in] i_JsonObject - Any JSON which contains CCIN tag to match.
+ * @param[in] i_parsedVpdMap - Parsed VPD map.
+ * @return True if found, false otherwise.
+ */
+inline bool findCcinInVpd(const nlohmann::json& i_JsonObject,
+                          const types::VPDMapVariant& i_parsedVpdMap)
+{
+    if (i_JsonObject.empty())
+    {
+        throw std::runtime_error("Json object is empty. Can't find CCIN");
+    }
+
+    if (auto l_ipzVPDMap = std::get_if<types::IPZVpdMap>(&i_parsedVpdMap))
+    {
+        auto l_itrToRec = (*l_ipzVPDMap).find("VINI");
+        if (l_itrToRec == (*l_ipzVPDMap).end())
+        {
+            throw DataException(
+                "VINI record not found in parsed VPD. Can't find CCIN");
+        }
+
+        std::string l_ccinFromVpd;
+        vpdSpecificUtility::getKwVal(l_itrToRec->second, "CC", l_ccinFromVpd);
+        if (l_ccinFromVpd.empty())
+        {
+            throw DataException("Empty CCIN value in VPD map. Can't find CCIN");
+        }
+
+        transform(l_ccinFromVpd.begin(), l_ccinFromVpd.end(),
+                  l_ccinFromVpd.begin(), ::toupper);
+
+        for (std::string l_ccinValue : i_JsonObject["ccin"])
+        {
+            transform(l_ccinValue.begin(), l_ccinValue.end(),
+                      l_ccinValue.begin(), ::toupper);
+
+            if (l_ccinValue.compare(l_ccinFromVpd) ==
+                constants::STR_CMP_SUCCESS)
+            {
+                // CCIN found
+                return true;
+            }
+        }
+
+        logging::logMessage("No match found for CCIN");
+        return false;
+    }
+
+    logging::logMessage("VPD type not supported. Can't find CCIN");
+    return false;
+}
+
+/**
+ * @brief API to reset data of a FRU populated under PIM.
+ *
+ * This API resets the data for particular interfaces of a FRU under PIM.
+ *
+ * @param[in] i_objectPath - DBus object path of the FRU.
+ * @param[in] io_interfaceMap - Interface and its properties map.
+ */
+inline void resetDataUnderPIM(const std::string& i_objectPath,
+                              types::InterfaceMap& io_interfaceMap)
+{
+    try
+    {
+        std::array<const char*, 0> l_interfaces;
+        const types::MapperGetObject& l_getObjectMap =
+            dbusUtility::getObjectMap(i_objectPath, l_interfaces);
+
+        const std::vector<std::string>& l_vpdRelatedInterfaces{
+            constants::operationalStatusInf, constants::inventoryItemInf,
+            constants::assetInf};
+
+        for (const auto& [l_service, l_interfaceList] : l_getObjectMap)
+        {
+            if (l_service.compare(constants::pimServiceName) !=
+                constants::STR_CMP_SUCCESS)
+            {
+                continue;
+            }
+
+            for (const auto& l_interface : l_interfaceList)
+            {
+                if ((l_interface.find(constants::ipzVpdInf) !=
+                     std::string::npos) ||
+                    ((std::find(l_vpdRelatedInterfaces.begin(),
+                                l_vpdRelatedInterfaces.end(), l_interface)) !=
+                     l_vpdRelatedInterfaces.end()))
+                {
+                    const types::PropertyMap& l_propertyValueMap =
+                        dbusUtility::getPropertyMap(l_service, i_objectPath,
+                                                    l_interface);
+
+                    types::PropertyMap l_propertyMap;
+
+                    for (const auto& l_aProperty : l_propertyValueMap)
+                    {
+                        const std::string& l_propertyName = l_aProperty.first;
+                        const auto& l_propertyValue = l_aProperty.second;
+
+                        if (std::holds_alternative<types::BinaryVector>(
+                                l_propertyValue))
+                        {
+                            l_propertyMap.emplace(l_propertyName,
+                                                  types::BinaryVector{});
+                        }
+                        else if (std::holds_alternative<std::string>(
+                                     l_propertyValue))
+                        {
+                            l_propertyMap.emplace(l_propertyName,
+                                                  std::string{});
+                        }
+                        else if (std::holds_alternative<bool>(l_propertyValue))
+                        {
+                            // ToDo -- Update the functional status property
+                            // to true.
+                            if (l_propertyName.compare("Present") ==
+                                constants::STR_CMP_SUCCESS)
+                            {
+                                l_propertyMap.emplace(l_propertyName, false);
+                            }
+                        }
+                    }
+                    io_interfaceMap.emplace(l_interface,
+                                            std::move(l_propertyMap));
+                }
+            }
+        }
+    }
+    catch (const std::exception& l_ex)
+    {
+        logging::logMessage("Failed to remove VPD for FRU: " + i_objectPath +
+                            " with error: " + std::string(l_ex.what()));
+    }
+}
+} // namespace vpdSpecificUtility
+} // namespace vpd
diff --git a/vpd-manager/include/worker.hpp b/vpd-manager/include/worker.hpp
new file mode 100644
index 0000000..85a1818
--- /dev/null
+++ b/vpd-manager/include/worker.hpp
@@ -0,0 +1,529 @@
+#pragma once
+
+#include "constants.hpp"
+#include "types.hpp"
+
+#include <nlohmann/json.hpp>
+
+#include <mutex>
+#include <optional>
+#include <semaphore>
+#include <tuple>
+
+namespace vpd
+{
+/**
+ * @brief A class to process and publish VPD data.
+ *
+ * The class works on VPD and is mainly responsible for following tasks:
+ * 1) Select appropriate device tree and JSON. Reboot if required.
+ * 2) Get desired parser using parser factory.
+ * 3) Calling respective parser class to get parsed VPD.
+ * 4) Arranging VPD data under required interfaces.
+ * 5) Calling PIM to publish VPD.
+ *
+ * The class may also implement helper functions required for VPD handling.
+ */
+class Worker
+{
+  public:
+    /**
+     * List of deleted functions.
+     */
+    Worker(const Worker&);
+    Worker& operator=(const Worker&);
+    Worker(Worker&&) = delete;
+
+    /**
+     * @brief Constructor.
+     *
+     * In case the processing is not JSON based, no argument needs to be passed.
+     * Constructor will also, based on symlink pick the correct JSON and
+     * initialize the parsed JSON variable.
+     *
+     * @param[in] pathToConfigJSON - Path to the config JSON, if applicable.
+     *
+     * Note: Throws std::exception in case of construction failure. Caller needs
+     * to handle to detect successful object creation.
+     */
+    Worker(std::string pathToConfigJson = std::string());
+
+    /**
+     * @brief Destructor
+     */
+    ~Worker() = default;
+
+#ifdef IBM_SYSTEM
+    /**
+     * @brief API to perform initial setup before manager claims Bus name.
+     *
+     * Before BUS name for VPD-Manager is claimed, fitconfig whould be set for
+     * corret device tree, inventory JSON w.r.t system should be linked and
+     * system VPD should be on DBus.
+     */
+    void performInitialSetup();
+#endif
+
+    /**
+     * @brief An API to check if system VPD is already published.
+     *
+     * @return Status, true if system is already collected else false.
+     */
+    bool isSystemVPDOnDBus() const;
+
+    /**
+     * @brief API to process all FRUs presnt in config JSON file.
+     *
+     * This API based on config JSON passed/selected for the system, will
+     * trigger parser for all the FRUs and publish it on DBus.
+     *
+     * Note: Config JSON file path should be passed to worker class constructor
+     * to make use of this API.
+     *
+     */
+    void collectFrusFromJson();
+
+    /**
+     * @brief API to parse VPD data
+     *
+     * @param[in] i_vpdFilePath - Path to the VPD file.
+     */
+    types::VPDMapVariant parseVpdFile(const std::string& i_vpdFilePath);
+
+    /**
+     * @brief An API to populate DBus interfaces for a FRU.
+     *
+     * Note: Call this API to populate D-Bus. Also caller should handle empty
+     * objectInterfaceMap.
+     *
+     * @param[in] parsedVpdMap - Parsed VPD as a map.
+     * @param[out] objectInterfaceMap - Object and its interfaces map.
+     * @param[in] vpdFilePath - EEPROM path of FRU.
+     */
+    void populateDbus(const types::VPDMapVariant& parsedVpdMap,
+                      types::ObjectMap& objectInterfaceMap,
+                      const std::string& vpdFilePath);
+
+    /**
+     * @brief An API to delete FRU VPD over DBus.
+     *
+     * @param[in] i_dbusObjPath - Dbus object path of the FRU.
+     *
+     * @throw std::runtime_error if given input path is empty.
+     */
+    void deleteFruVpd(const std::string& i_dbusObjPath);
+
+    /**
+     * @brief API to get status of VPD collection process.
+     *
+     * @return - True when done, false otherwise.
+     */
+    inline bool isAllFruCollectionDone() const
+    {
+        return m_isAllFruCollected;
+    }
+
+    /**
+     * @brief API to get system config JSON object
+     *
+     * @return System config JSON object.
+     */
+    inline nlohmann::json getSysCfgJsonObj() const
+    {
+        return m_parsedJson;
+    }
+
+    /**
+     * @brief API to get active thread count.
+     *
+     * Each FRU is collected in a separate thread. This API gives the active
+     * thread collecting FRU's VPD at any given time.
+     *
+     * @return Count of active threads.
+     */
+    size_t getActiveThreadCount() const
+    {
+        return m_activeCollectionThreadCount;
+    }
+
+  private:
+    /**
+     * @brief An API to parse and publish a FRU VPD over D-Bus.
+     *
+     * Note: This API will handle all the exceptions internally and will only
+     * return status of parsing and publishing of VPD over D-Bus.
+     *
+     * @param[in] i_vpdFilePath - Path of file containing VPD.
+     * @return Tuple of status and file path. Status, true if successfull else
+     * false.
+     */
+    std::tuple<bool, std::string>
+        parseAndPublishVPD(const std::string& i_vpdFilePath);
+
+    /**
+     * @brief An API to set appropriate device tree and JSON.
+     *
+     * This API based on system chooses corresponding device tree and JSON.
+     * If device tree change is required, it updates the "fitconfig" and reboots
+     * the system. Else it is NOOP.
+     *
+     * @throw std::runtime_error
+     */
+    void setDeviceTreeAndJson();
+
+    /**
+     * @brief API to select system specific JSON.
+     *
+     * The API based on the IM value of VPD, will select appropriate JSON for
+     * the system. In case no system is found corresponding to the extracted IM
+     * value, error will be logged.
+     *
+     * @param[out] systemJson - System JSON name.
+     * @param[in] parsedVpdMap - Parsed VPD map.
+     */
+    void getSystemJson(std::string& systemJson,
+                       const types::VPDMapVariant& parsedVpdMap);
+
+    /**
+     * @brief An API to read IM value from VPD.
+     *
+     * Note: Throws exception in case of error. Caller need to handle.
+     *
+     * @param[in] parsedVpd - Parsed VPD.
+     */
+    std::string getIMValue(const types::IPZVpdMap& parsedVpd) const;
+
+    /**
+     * @brief An API to read HW version from VPD.
+     *
+     * Note: Throws exception in case of error. Caller need to handle.
+     *
+     * @param[in] parsedVpd - Parsed VPD.
+     */
+    std::string getHWVersion(const types::IPZVpdMap& parsedVpd) const;
+
+    /**
+     * @brief An API to parse given VPD file path.
+     *
+     * @param[in] vpdFilePath - EEPROM file path.
+     * @param[out] parsedVpd - Parsed VPD as a map.
+     */
+    void fillVPDMap(const std::string& vpdFilePath,
+                    types::VPDMapVariant& parsedVpd);
+
+    /**
+     * @brief An API to parse and publish system VPD on D-Bus.
+     *
+     * Note: Throws exception in case of invalid VPD format.
+     *
+     * @param[in] parsedVpdMap - Parsed VPD as a map.
+     */
+    void publishSystemVPD(const types::VPDMapVariant& parsedVpdMap);
+
+    /**
+     * @brief An API to process extrainterfaces w.r.t a FRU.
+     *
+     * @param[in] singleFru - JSON block for a single FRU.
+     * @param[out] interfaces - Map to hold interface along with its properties.
+     * @param[in] parsedVpdMap - Parsed VPD as a map.
+     */
+    void processExtraInterfaces(const nlohmann::json& singleFru,
+                                types::InterfaceMap& interfaces,
+                                const types::VPDMapVariant& parsedVpdMap);
+
+    /**
+     * @brief An API to process embedded and synthesized FRUs.
+     *
+     * @param[in] singleFru - FRU to be processed.
+     * @param[out] interfaces - Map to hold interface along with its properties.
+     */
+    void processEmbeddedAndSynthesizedFrus(const nlohmann::json& singleFru,
+                                           types::InterfaceMap& interfaces);
+
+    /**
+     * @brief An API to read process FRU based in CCIN.
+     *
+     * For some FRUs VPD can be processed only if the FRU has some specific
+     * value for CCIN. In case the value is not from that set, VPD for those
+     * FRUs can't be processed.
+     *
+     * @param[in] singleFru - Fru whose CCIN value needs to be matched.
+     * @param[in] parsedVpdMap - Parsed VPD map.
+     */
+    bool processFruWithCCIN(const nlohmann::json& singleFru,
+                            const types::VPDMapVariant& parsedVpdMap);
+
+    /**
+     * @brief API to process json's inherit flag.
+     *
+     * Inherit flag denotes that some property in the child FRU needs to be
+     * inherited from parent FRU.
+     *
+     * @param[in] parsedVpdMap - Parsed VPD as a map.
+     * @param[out] interfaces - Map to hold interface along with its properties.
+     */
+    void processInheritFlag(const types::VPDMapVariant& parsedVpdMap,
+                            types::InterfaceMap& interfaces);
+
+    /**
+     * @brief API to process json's "copyRecord" flag.
+     *
+     * copyRecord flag denotes if some record data needs to be copies in the
+     * given FRU.
+     *
+     * @param[in] singleFru - FRU being processed.
+     * @param[in] parsedVpdMap - Parsed VPD as a map.
+     * @param[out] interfaces - Map to hold interface along with its properties.
+     */
+    void processCopyRecordFlag(const nlohmann::json& singleFru,
+                               const types::VPDMapVariant& parsedVpdMap,
+                               types::InterfaceMap& interfaces);
+
+    /**
+     * @brief An API to populate IPZ VPD property map.
+     *
+     * @param[out] interfacePropMap - Map of interface and properties under it.
+     * @param[in] keyordValueMap - Keyword value map of IPZ VPD.
+     * @param[in] interfaceName - Name of the interface.
+     */
+    void populateIPZVPDpropertyMap(types::InterfaceMap& interfacePropMap,
+                                   const types::IPZKwdValueMap& keyordValueMap,
+                                   const std::string& interfaceName);
+
+    /**
+     * @brief An API to populate Kwd VPD property map.
+     *
+     * @param[in] keyordValueMap - Keyword value map of Kwd VPD.
+     * @param[out] interfaceMap - interface and property,value under it.
+     */
+    void populateKwdVPDpropertyMap(const types::KeywordVpdMap& keyordVPDMap,
+                                   types::InterfaceMap& interfaceMap);
+
+    /**
+     * @brief API to populate all required interface for a FRU.
+     *
+     * @param[in] interfaceJson - JSON containing interfaces to be populated.
+     * @param[out] interfaceMap - Map to hold populated interfaces.
+     * @param[in] parsedVpdMap - Parsed VPD as a map.
+     */
+    void populateInterfaces(const nlohmann::json& interfaceJson,
+                            types::InterfaceMap& interfaceMap,
+                            const types::VPDMapVariant& parsedVpdMap);
+
+    /**
+     * @brief Helper function to insert or merge in map.
+     *
+     * This method checks in the given inventory::InterfaceMap if the given
+     * interface key is existing or not. If the interface key already exists,
+     * given property map is inserted into it. If the key does'nt exist then
+     * given interface and property map pair is newly created. If the property
+     * present in propertymap already exist in the InterfaceMap, then the new
+     * property value is ignored.
+     *
+     * @param[in,out] interfaceMap - map object of type inventory::InterfaceMap
+     * only.
+     * @param[in] interface - Interface name.
+     * @param[in] property - new property map that needs to be emplaced.
+     */
+    void insertOrMerge(types::InterfaceMap& interfaceMap,
+                       const std::string& interface,
+                       types::PropertyMap&& property);
+
+    /**
+     * @brief Check if the given CPU is an IO only chip.
+     *
+     * The CPU is termed as IO, whose all of the cores are bad and can never be
+     * used. Those CPU chips can be used for IO purpose like connecting PCIe
+     * devices etc., The CPU whose every cores are bad, can be identified from
+     * the CP00 record's PG keyword, only if all of the 8 EQs' value equals
+     * 0xE7F9FF. (1EQ has 4 cores grouped together by sharing its cache memory.)
+     *
+     * @param [in] pgKeyword - PG Keyword of CPU.
+     * @return true if the given cpu is an IO, false otherwise.
+     */
+    bool isCPUIOGoodOnly(const std::string& pgKeyword);
+
+    /**
+     * @brief API to prime inventory Objects.
+     *
+     * @param[in] i_vpdFilePath - EEPROM file path.
+     * @return true if the prime inventory is success, false otherwise.
+     */
+    bool primeInventory(const std::string& i_vpdFilePath);
+
+    /**
+     * @brief API to process preAction(base_action) defined in config JSON.
+     *
+     * @note sequence of tags under any given flag of preAction is EXTREMELY
+     * important to ensure proper processing. The API will process all the
+     * nested items under the base action sequentially. Also if any of the tag
+     * processing fails, the code will not process remaining tags under the
+     * flag.
+     * ******** sample format **************
+     * fru EEPROM path: {
+     *     base_action: {
+     *         flag1: {
+     *           tag1: {
+     *            },
+     *           tag2: {
+     *            }
+     *         }
+     *         flag2: {
+     *           tags: {
+     *            }
+     *         }
+     *     }
+     * }
+     * *************************************
+     *
+     * @param[in] i_vpdFilePath - Path to the EEPROM file.
+     * @param[in] i_flagToProcess - To identify which flag(s) needs to be
+     * processed under PreAction tag of config JSON.
+     * @return Execution status.
+     */
+    bool processPreAction(const std::string& i_vpdFilePath,
+                          const std::string& i_flagToProcess);
+
+    /**
+     * @brief API to process postAction(base_action) defined in config JSON.
+     *
+     * @note Sequence of tags under any given flag of postAction is EXTREMELY
+     * important to ensure proper processing. The API will process all the
+     * nested items under the base action sequentially. Also if any of the tag
+     * processing fails, the code will not process remaining tags under the
+     * flag.
+     * ******** sample format **************
+     * fru EEPROM path: {
+     *     base_action: {
+     *         flag1: {
+     *           tag1: {
+     *            },
+     *           tag2: {
+     *            }
+     *         }
+     *         flag2: {
+     *           tags: {
+     *            }
+     *         }
+     *     }
+     * }
+     * *************************************
+     * Also, if post action is required to be processed only for FRUs with
+     * certain CCIN then CCIN list can be provided under flag.
+     *
+     * @param[in] i_vpdFruPath - Path to the EEPROM file.
+     * @param[in] i_flagToProcess - To identify which flag(s) needs to be
+     * processed under postAction tag of config JSON.
+     * @param[in] i_parsedVpd - Optional Parsed VPD map. If CCIN match is
+     * required.
+     * @return Execution status.
+     */
+    bool processPostAction(
+        const std::string& i_vpdFruPath, const std::string& i_flagToProcess,
+        const std::optional<types::VPDMapVariant> i_parsedVpd = std::nullopt);
+
+    /**
+     * @brief Function to enable and bring MUX out of idle state.
+     *
+     * This finds all the MUX defined in the system json and enables them by
+     * setting the holdidle parameter to 0.
+     *
+     * @throw std::runtime_error
+     */
+    void enableMuxChips();
+
+    /**
+     * @brief An API to perform backup or restore of VPD.
+     *
+     * @param[in,out] io_srcVpdMap - Source VPD map.
+     */
+    void performBackupAndRestore(types::VPDMapVariant& io_srcVpdMap);
+
+    /**
+     * @brief API to update "Functional" property.
+     *
+     * The API sets the default value for "Functional" property once if the
+     * property is not yet populated over DBus. As the property value is not
+     * controlled by the VPD-Collection process, if it is found already
+     * populated, the functions skips re-populating the property so that already
+     * existing value can be retained.
+     *
+     * @param[in] i_inventoryObjPath - Inventory path as read from config JSON.
+     * @param[in] io_interfaces - Map to hold all the interfaces for the FRU.
+     */
+    void processFunctionalProperty(const std::string& i_inventoryObjPath,
+                                   types::InterfaceMap& io_interfaces);
+
+    /**
+     * @brief API to update "enabled" property.
+     *
+     * The API sets the default value for "enabled" property once if the
+     * property is not yet populated over DBus. As the property value is not
+     * controlled by the VPD-Collection process, if it is found already
+     * populated, the functions skips re-populating the property so that already
+     * existing value can be retained.
+     *
+     * @param[in] i_inventoryObjPath - Inventory path as read from config JSON.
+     * @param[in] io_interfaces - Map to hold all the interfaces for the FRU.
+     */
+    void processEnabledProperty(const std::string& i_inventoryObjPath,
+                                types::InterfaceMap& io_interfaces);
+
+    /**
+     * @brief API to form asset tag string for the system.
+     *
+     * @param[in] i_parsedVpdMap - Parsed VPD map.
+     *
+     * @throw std::runtime_error
+     *
+     * @return - Formed asset tag string.
+     */
+    std::string
+        createAssetTagString(const types::VPDMapVariant& i_parsedVpdMap);
+
+    /**
+     * @brief API to prime system blueprint.
+     *
+     * The API will traverse the system config JSON and will prime all the FRU
+     * paths which qualifies for priming.
+     */
+    void primeSystemBlueprint();
+
+    /**
+     * @brief API to set symbolic link for system config JSON.
+     *
+     * Once correct device tree is set, symbolic link to the correct sytsem
+     * config JSON is set to be used in subsequent BMC boot.
+     *
+     * @param[in] i_systemJson - system config JSON.
+     */
+    void setJsonSymbolicLink(const std::string& i_systemJson);
+
+    // Parsed JSON file.
+    nlohmann::json m_parsedJson{};
+
+    // Hold if symlink is present or not.
+    bool m_isSymlinkPresent = false;
+
+    // Path to config JSON if applicable.
+    std::string& m_configJsonPath;
+
+    // Keeps track of active thread(s) doing VPD collection.
+    size_t m_activeCollectionThreadCount = 0;
+
+    // Holds status, if VPD collection has been done or not.
+    // Note: This variable does not give information about successfull or failed
+    // collection. It just states, if the VPD collection process is over or not.
+    bool m_isAllFruCollected = false;
+
+    // To distinguish the factory reset path.
+    bool m_isFactoryResetDone = false;
+
+    // Mutex to guard critical resource m_activeCollectionThreadCount.
+    std::mutex m_mutex;
+
+    // Counting semaphore to limit the number of threads.
+    std::counting_semaphore<constants::MAX_THREADS> m_semaphore{
+        constants::MAX_THREADS};
+};
+} // namespace vpd
diff --git a/vpd-manager/manager.cpp b/vpd-manager/manager.cpp
deleted file mode 100644
index 8913474..0000000
--- a/vpd-manager/manager.cpp
+++ /dev/null
@@ -1,918 +0,0 @@
-#include "config.h"
-
-#include "manager.hpp"
-
-#include "common_utility.hpp"
-#include "editor_impl.hpp"
-#include "ibm_vpd_utils.hpp"
-#include "ipz_parser.hpp"
-#include "parser_factory.hpp"
-#include "reader_impl.hpp"
-#include "vpd_exceptions.hpp"
-
-#include <unistd.h>
-
-#include <phosphor-logging/elog-errors.hpp>
-#include <xyz/openbmc_project/Common/error.hpp>
-
-#include <filesystem>
-
-using namespace openpower::vpd::constants;
-using namespace openpower::vpd::inventory;
-using namespace openpower::vpd::manager::editor;
-using namespace openpower::vpd::manager::reader;
-using namespace std;
-using namespace openpower::vpd::parser;
-using namespace openpower::vpd::parser::factory;
-using namespace openpower::vpd::ipz::parser;
-using namespace openpower::vpd::exceptions;
-using namespace phosphor::logging;
-
-namespace openpower
-{
-namespace vpd
-{
-namespace manager
-{
-
-Manager::Manager(std::shared_ptr<boost::asio::io_context>& ioCon,
-                 std::shared_ptr<sdbusplus::asio::dbus_interface>& iFace,
-                 std::shared_ptr<sdbusplus::asio::connection>& conn) :
-    ioContext(ioCon), interface(iFace), conn(conn)
-{
-    interface->register_method(
-        "WriteKeyword",
-        [this](const sdbusplus::message::object_path& path,
-               const std::string& recordName, const std::string& keyword,
-               const Binary& value) {
-            this->writeKeyword(path, recordName, keyword, value);
-        });
-
-    interface->register_method(
-        "GetFRUsByUnexpandedLocationCode",
-        [this](const std::string& locationCode,
-               const uint16_t nodeNumber) -> inventory::ListOfPaths {
-            return this->getFRUsByUnexpandedLocationCode(locationCode,
-                                                         nodeNumber);
-        });
-
-    interface->register_method(
-        "GetFRUsByExpandedLocationCode",
-        [this](const std::string& locationCode) -> inventory::ListOfPaths {
-            return this->getFRUsByExpandedLocationCode(locationCode);
-        });
-
-    interface->register_method(
-        "GetExpandedLocationCode",
-        [this](const std::string& locationCode,
-               const uint16_t nodeNumber) -> std::string {
-            return this->getExpandedLocationCode(locationCode, nodeNumber);
-        });
-
-    interface->register_method("PerformVPDRecollection", [this]() {
-        this->performVPDRecollection();
-    });
-
-    interface->register_method(
-        "deleteFRUVPD", [this](const sdbusplus::message::object_path& path) {
-            this->deleteFRUVPD(path);
-        });
-
-    interface->register_method(
-        "CollectFRUVPD", [this](const sdbusplus::message::object_path& path) {
-            this->collectFRUVPD(path);
-        });
-
-    sd_bus_default(&sdBus);
-    initManager();
-}
-
-void Manager::initManager()
-{
-    try
-    {
-        processJSON();
-        restoreSystemVpd();
-        listenHostState();
-        listenAssetTag();
-
-        // Create an instance of the BIOS handler
-        biosHandler = std::make_shared<BiosHandler>(conn, *this);
-
-        // instantiate gpioMonitor class
-        gpioMon = std::make_shared<GpioMonitor>(jsonFile, ioContext);
-    }
-    catch (const std::exception& e)
-    {
-        std::cerr << e.what() << "\n";
-    }
-}
-
-/**
- * @brief An api to get list of blank system VPD properties.
- * @param[in] vpdMap - IPZ vpd map.
- * @param[in] objectPath - Object path for the FRU.
- * @param[out] blankPropertyList - Properties which are blank in System VPD and
- * needs to be updated as standby.
- */
-static void
-    getListOfBlankSystemVpd(Parsed& vpdMap, const string& objectPath,
-                            std::vector<RestoredEeproms>& blankPropertyList)
-{
-    for (const auto& systemRecKwdPair : svpdKwdMap)
-    {
-        auto it = vpdMap.find(systemRecKwdPair.first);
-
-        // check if record is found in map we got by parser
-        if (it != vpdMap.end())
-        {
-            const auto& kwdListForRecord = systemRecKwdPair.second;
-            for (const auto& keywordInfo : kwdListForRecord)
-            {
-                const auto& keyword = get<0>(keywordInfo);
-
-                DbusPropertyMap& kwdValMap = it->second;
-                auto iterator = kwdValMap.find(keyword);
-
-                if (iterator != kwdValMap.end())
-                {
-                    string& kwdValue = iterator->second;
-
-                    // check bus data
-                    const string& recordName = systemRecKwdPair.first;
-                    const string& busValue = readBusProperty(
-                        objectPath, ipzVpdInf + recordName, keyword);
-
-                    const auto& defaultValue = get<1>(keywordInfo);
-
-                    if (Binary(busValue.begin(), busValue.end()) !=
-                        defaultValue)
-                    {
-                        if (Binary(kwdValue.begin(), kwdValue.end()) ==
-                            defaultValue)
-                        {
-                            // implies data is blank on EEPROM but not on cache.
-                            // So EEPROM vpd update is required.
-                            Binary busData(busValue.begin(), busValue.end());
-
-                            blankPropertyList.push_back(std::make_tuple(
-                                objectPath, recordName, keyword, busData));
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
-void Manager::restoreSystemVpd()
-{
-    std::cout << "Attempting system VPD restore" << std::endl;
-    ParserInterface* parser = nullptr;
-    try
-    {
-        auto vpdVector = getVpdDataInVector(jsonFile, systemVpdFilePath);
-        uint32_t vpdStartOffset = 0;
-        const auto& inventoryPath =
-            jsonFile["frus"][systemVpdFilePath][0]["inventoryPath"]
-                .get_ref<const nlohmann::json::string_t&>();
-
-        parser = ParserFactory::getParser(vpdVector, (pimPath + inventoryPath),
-                                          systemVpdFilePath, vpdStartOffset);
-        auto parseResult = parser->parse();
-
-        if (auto pVal = std::get_if<Store>(&parseResult))
-        {
-            // map to hold all the keywords whose value is blank and
-            // needs to be updated at standby.
-            std::vector<RestoredEeproms> blankSystemVpdProperties{};
-            getListOfBlankSystemVpd(pVal->getVpdMap(), SYSTEM_OBJECT,
-                                    blankSystemVpdProperties);
-
-            // if system VPD restore is required, update the
-            // EEPROM
-            for (const auto& item : blankSystemVpdProperties)
-            {
-                std::cout << "Restoring keyword: " << std::get<2>(item)
-                          << std::endl;
-                writeKeyword(std::get<0>(item), std::get<1>(item),
-                             std::get<2>(item), std::get<3>(item));
-            }
-        }
-        else
-        {
-            std::cerr << "Not a valid format to restore system VPD"
-                      << std::endl;
-        }
-    }
-    catch (const std::exception& e)
-    {
-        std::cerr << "Failed to restore system VPD due to exception: "
-                  << e.what() << std::endl;
-    }
-    // release the parser object
-    ParserFactory::freeParser(parser);
-}
-
-void Manager::listenHostState()
-{
-    static std::shared_ptr<sdbusplus::bus::match_t> hostState =
-        std::make_shared<sdbusplus::bus::match_t>(
-            *conn,
-            sdbusplus::bus::match::rules::propertiesChanged(
-                "/xyz/openbmc_project/state/host0",
-                "xyz.openbmc_project.State.Host"),
-            [this](sdbusplus::message_t& msg) { hostStateCallBack(msg); });
-}
-
-void Manager::checkEssentialFrus()
-{
-    for (const auto& invPath : essentialFrus)
-    {
-        const auto res = readBusProperty(invPath, invItemIntf, "Present");
-
-        // implies the essential FRU is missing. Log PEL.
-        if (res == "false")
-        {
-            auto rc = sd_bus_call_method_async(
-                sdBus, NULL, loggerService, loggerObjectPath,
-                loggerCreateInterface, "Create", NULL, NULL, "ssa{ss}",
-                errIntfForEssentialFru,
-                "xyz.openbmc_project.Logging.Entry.Level.Warning", 2,
-                "DESCRIPTION", "Essential fru missing from the system.",
-                "CALLOUT_INVENTORY_PATH", (pimPath + invPath).c_str());
-
-            if (rc < 0)
-            {
-                log<level::ERR>("Error calling sd_bus_call_method_async",
-                                entry("RC=%d", rc),
-                                entry("MSG=%s", strerror(-rc)));
-            }
-        }
-    }
-}
-
-void Manager::hostStateCallBack(sdbusplus::message_t& msg)
-{
-    if (msg.is_method_error())
-    {
-        std::cerr << "Error in reading signal " << std::endl;
-    }
-
-    Path object;
-    PropertyMap propMap;
-    msg.read(object, propMap);
-    const auto itr = propMap.find("CurrentHostState");
-    if (itr != propMap.end())
-    {
-        if (auto hostState = std::get_if<std::string>(&(itr->second)))
-        {
-            // implies system is moving from standby to power on state
-            if (*hostState == "xyz.openbmc_project.State.Host.HostState."
-                              "TransitioningToRunning")
-            {
-                // detect if essential frus are present in the system.
-                checkEssentialFrus();
-
-                // check and perform recollection for FRUs replaceable at
-                // standby.
-                performVPDRecollection();
-                return;
-            }
-        }
-    }
-}
-
-void Manager::listenAssetTag()
-{
-    static std::shared_ptr<sdbusplus::bus::match_t> assetMatcher =
-        std::make_shared<sdbusplus::bus::match_t>(
-            *conn,
-            sdbusplus::bus::match::rules::propertiesChanged(
-                "/xyz/openbmc_project/inventory/system",
-                "xyz.openbmc_project.Inventory.Decorator.AssetTag"),
-            [this](sdbusplus::message_t& msg) { assetTagCallback(msg); });
-}
-
-void Manager::assetTagCallback(sdbusplus::message_t& msg)
-{
-    if (msg.is_method_error())
-    {
-        std::cerr << "Error in reading signal " << std::endl;
-    }
-
-    Path object;
-    PropertyMap propMap;
-    msg.read(object, propMap);
-    const auto itr = propMap.find("AssetTag");
-    if (itr != propMap.end())
-    {
-        if (auto assetTag = std::get_if<std::string>(&(itr->second)))
-        {
-            // Call Notify to persist the AssetTag
-            inventory::ObjectMap objectMap = {
-                {std::string{"/system"},
-                 {{"xyz.openbmc_project.Inventory.Decorator.AssetTag",
-                   {{"AssetTag", *assetTag}}}}}};
-
-            common::utility::callPIM(std::move(objectMap));
-        }
-        else
-        {
-            std::cerr << "Failed to read asset tag" << std::endl;
-        }
-    }
-}
-
-void Manager::processJSON()
-{
-    std::ifstream json(INVENTORY_JSON_SYM_LINK, std::ios::binary);
-
-    if (!json)
-    {
-        throw std::runtime_error("json file not found");
-    }
-
-    jsonFile = nlohmann::json::parse(json);
-    if (jsonFile.find("frus") == jsonFile.end())
-    {
-        throw std::runtime_error("frus group not found in json");
-    }
-
-    const nlohmann::json& groupFRUS =
-        jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
-    for (const auto& itemFRUS : groupFRUS.items())
-    {
-        const std::vector<nlohmann::json>& groupEEPROM =
-            itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
-        for (const auto& itemEEPROM : groupEEPROM)
-        {
-            bool isMotherboard = false;
-            std::string redundantPath;
-
-            if (itemEEPROM["extraInterfaces"].find(
-                    "xyz.openbmc_project.Inventory.Item.Board.Motherboard") !=
-                itemEEPROM["extraInterfaces"].end())
-            {
-                isMotherboard = true;
-            }
-            if (itemEEPROM.find("redundantEeprom") != itemEEPROM.end())
-            {
-                redundantPath = itemEEPROM["redundantEeprom"]
-                                    .get_ref<const nlohmann::json::string_t&>();
-            }
-            frus.emplace(
-                itemEEPROM["inventoryPath"]
-                    .get_ref<const nlohmann::json::string_t&>(),
-                std::make_tuple(itemFRUS.key(), redundantPath, isMotherboard));
-
-            if (itemEEPROM["extraInterfaces"].find(IBM_LOCATION_CODE_INF) !=
-                itemEEPROM["extraInterfaces"].end())
-            {
-                fruLocationCode.emplace(
-                    itemEEPROM["extraInterfaces"][IBM_LOCATION_CODE_INF]
-                              ["LocationCode"]
-                                  .get_ref<const nlohmann::json::string_t&>(),
-                    itemEEPROM["inventoryPath"]
-                        .get_ref<const nlohmann::json::string_t&>());
-            }
-
-            if (itemEEPROM.value("replaceableAtStandby", false))
-            {
-                replaceableFrus.emplace_back(itemFRUS.key());
-            }
-
-            if (itemEEPROM.value("essentialFru", false))
-            {
-                essentialFrus.emplace_back(itemEEPROM["inventoryPath"]);
-            }
-        }
-    }
-}
-
-void Manager::updateSystemVPDBackUpFRU(const std::string& recordName,
-                                       const std::string& keyword,
-                                       const Binary& value)
-{
-    const std::string& systemVpdBackupPath =
-        jsonFile["frus"][systemVpdFilePath].at(0).value("systemVpdBackupPath",
-                                                        "");
-
-    if (!systemVpdBackupPath.empty() &&
-        jsonFile["frus"][systemVpdBackupPath].at(0).contains("inventoryPath"))
-    {
-        std::string systemVpdBackupInvPath =
-            jsonFile["frus"][systemVpdBackupPath][0]["inventoryPath"]
-                .get_ref<const nlohmann::json::string_t&>();
-
-        const auto& itr = svpdKwdMap.find(recordName);
-        if (itr != svpdKwdMap.end())
-        {
-            auto systemKwdInfoList = itr->second;
-            const auto& itrToKwd =
-                find_if(systemKwdInfoList.begin(), systemKwdInfoList.end(),
-                        [&keyword](const auto& kwdInfo) {
-                            return (keyword == std::get<0>(kwdInfo));
-                        });
-
-            if (itrToKwd != systemKwdInfoList.end())
-            {
-                EditorImpl edit(systemVpdBackupPath, jsonFile,
-                                std::get<4>(*itrToKwd), std::get<5>(*itrToKwd),
-                                systemVpdBackupInvPath);
-
-                // Setup offset, if any
-                uint32_t offset = 0;
-                if (jsonFile["frus"][systemVpdBackupPath].at(0).contains(
-                        "offset"))
-                {
-                    offset =
-                        jsonFile["frus"][systemVpdBackupPath].at(0).contains(
-                            "offset");
-                }
-
-                edit.updateKeyword(value, offset, true);
-            }
-        }
-    }
-    else
-    {
-        if (systemVpdBackupPath.empty())
-        {
-            throw std::runtime_error(
-                "Invalid entry for systemVpdBackupPath in JSON");
-        }
-        else
-        {
-            throw std::runtime_error(
-                "Inventory path missing for systemVpdBackupPath");
-        }
-    }
-}
-
-void Manager::writeKeyword(const sdbusplus::message::object_path& path,
-                           const std::string& recordName,
-                           const std::string& keyword, const Binary& value)
-{
-    try
-    {
-        std::string objPath{path};
-        // Strip any inventory prefix in path
-        if (objPath.find(INVENTORY_PATH) == 0)
-        {
-            objPath = objPath.substr(sizeof(INVENTORY_PATH) - 1);
-        }
-
-        if (frus.find(objPath) == frus.end())
-        {
-            throw std::runtime_error("Inventory path not found");
-        }
-
-        inventory::Path vpdFilePath = std::get<0>(frus.find(objPath)->second);
-
-        // instantiate editor class to update the data
-        EditorImpl edit(vpdFilePath, jsonFile, recordName, keyword, objPath);
-
-        uint32_t offset = 0;
-        // Setup offset, if any
-        for (const auto& item : jsonFile["frus"][vpdFilePath])
-        {
-            if (item.find("offset") != item.end())
-            {
-                offset = item["offset"];
-                break;
-            }
-        }
-
-        edit.updateKeyword(value, offset, true);
-
-        // If system VPD is being updated and system VPD is marked for back up
-        // on another FRU, update data on back up as well.
-        if (objPath == sdbusplus::message::object_path{SYSTEM_OBJECT} &&
-            jsonFile["frus"][systemVpdFilePath].at(0).contains(
-                "systemVpdBackupPath"))
-        {
-            updateSystemVPDBackUpFRU(recordName, keyword, value);
-        }
-
-        // If we have a redundant EEPROM to update, then update just the EEPROM,
-        // not the cache since that is already done when we updated the primary
-        if (!std::get<1>(frus.find(objPath)->second).empty())
-        {
-            EditorImpl edit(std::get<1>(frus.find(objPath)->second), jsonFile,
-                            recordName, keyword, objPath);
-            edit.updateKeyword(value, offset, false);
-        }
-
-        // if it is a motehrboard FRU need to check for location expansion
-        if (std::get<2>(frus.find(objPath)->second))
-        {
-            if (recordName == "VCEN" && (keyword == "FC" || keyword == "SE"))
-            {
-                edit.expandLocationCode("fcs");
-            }
-            else if (recordName == "VSYS" &&
-                     (keyword == "TM" || keyword == "SE"))
-            {
-                edit.expandLocationCode("mts");
-            }
-        }
-
-        return;
-    }
-    catch (const std::exception& e)
-    {
-        std::cerr << e.what() << std::endl;
-    }
-}
-
-ListOfPaths Manager::getFRUsByUnexpandedLocationCode(
-    const LocationCode& locationCode, const NodeNumber nodeNumber)
-{
-    ReaderImpl read;
-    return read.getFrusAtLocation(locationCode, nodeNumber, fruLocationCode);
-}
-
-ListOfPaths
-    Manager::getFRUsByExpandedLocationCode(const LocationCode& locationCode)
-{
-    ReaderImpl read;
-    return read.getFRUsByExpandedLocationCode(locationCode, fruLocationCode);
-}
-
-LocationCode Manager::getExpandedLocationCode(const LocationCode& locationCode,
-                                              const NodeNumber nodeNumber)
-{
-    ReaderImpl read;
-    return read.getExpandedLocationCode(locationCode, nodeNumber,
-                                        fruLocationCode);
-}
-
-void Manager::performVPDRecollection()
-{
-    // get list of FRUs replaceable at standby
-    for (const auto& item : replaceableFrus)
-    {
-        const vector<nlohmann::json>& groupEEPROM = jsonFile["frus"][item];
-        const nlohmann::json& singleFru = groupEEPROM[0];
-
-        const string& inventoryPath =
-            singleFru["inventoryPath"]
-                .get_ref<const nlohmann::json::string_t&>();
-
-        bool prePostActionRequired = false;
-
-        if ((jsonFile["frus"][item].at(0)).find("preAction") !=
-            jsonFile["frus"][item].at(0).end())
-        {
-            try
-            {
-                if (!executePreAction(jsonFile, item))
-                {
-                    // if the FRU has preAction defined then its execution
-                    // should pass to ensure bind/unbind of data.
-                    // preAction execution failed. should not call
-                    // bind/unbind.
-                    log<level::ERR>(
-                        "Pre-Action execution failed for the FRU",
-                        entry("ERROR=%s",
-                              ("Inventory path: " + inventoryPath).c_str()));
-
-                    // As recollection failed delete FRU data.
-                    deleteFRUVPD(inventoryPath);
-                    continue;
-                }
-            }
-            catch (const GpioException& e)
-            {
-                log<level::ERR>(e.what());
-                PelAdditionalData additionalData{};
-                additionalData.emplace("DESCRIPTION", e.what());
-                createPEL(additionalData, PelSeverity::WARNING,
-                          errIntfForGpioError, sdBus);
-
-                // As recollection failed delete FRU data.
-                deleteFRUVPD(inventoryPath);
-
-                continue;
-            }
-            prePostActionRequired = true;
-        }
-
-        // unbind, bind the driver to trigger parser.
-        triggerVpdCollection(singleFru, inventoryPath);
-
-        // this check is added to avoid file system expensive call in case not
-        // required.
-        if (prePostActionRequired)
-        {
-            // The sleep of 1sec is sliced up in 10 retries of 10 milliseconds
-            // each.
-            for (auto retryCounter = VALUE_0; retryCounter <= VALUE_10;
-                 retryCounter++)
-            {
-                // sleep for 10 millisecond
-                if (usleep(VALUE_100000) != VALUE_0)
-                {
-                    std::cout << "Sleep failed before accessing the file"
-                              << std::endl;
-                }
-
-                // Check if file showed up
-                if (!filesystem::exists(item))
-                {
-                    // Do we need to retry?
-                    if (retryCounter < VALUE_10)
-                    {
-                        continue;
-                    }
-
-                    try
-                    {
-                        // If not, then take failure postAction
-                        executePostFailAction(jsonFile, item);
-
-                        // As recollection failed delete FRU data.
-                        deleteFRUVPD(inventoryPath);
-                    }
-                    catch (const GpioException& e)
-                    {
-                        PelAdditionalData additionalData{};
-                        additionalData.emplace("DESCRIPTION", e.what());
-                        createPEL(additionalData, PelSeverity::WARNING,
-                                  errIntfForGpioError, sdBus);
-
-                        // As recollection failed delete FRU data.
-                        deleteFRUVPD(inventoryPath);
-                    }
-                }
-                else
-                {
-                    // bind the LED driver
-                    string chipAddr = singleFru.value("pcaChipAddress", "");
-                    cout
-                        << "performVPDRecollection: Executing driver binding for "
-                           "chip "
-                           "address - "
-                        << chipAddr << endl;
-
-                    executeCmd(createBindUnbindDriverCmnd(
-                        chipAddr, "i2c", "leds-pca955x", "/bind"));
-
-                    // File has been found, kill the retry loop.
-                    break;
-                }
-            }
-        }
-    }
-}
-
-void Manager::collectFRUVPD(const sdbusplus::message::object_path& path)
-{
-    std::cout << "Manager called to collect vpd for fru: " << std::string{path}
-              << std::endl;
-
-    using InvalidArgument =
-        sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
-    using Argument = xyz::openbmc_project::Common::InvalidArgument;
-
-    std::string objPath{path};
-
-    // Strip any inventory prefix in path
-    if (objPath.find(INVENTORY_PATH) == 0)
-    {
-        objPath = objPath.substr(sizeof(INVENTORY_PATH) - 1);
-    }
-
-    // if path not found in Json.
-    if (frus.find(objPath) == frus.end())
-    {
-        elog<InvalidArgument>(Argument::ARGUMENT_NAME("Object Path"),
-                              Argument::ARGUMENT_VALUE(objPath.c_str()));
-    }
-
-    inventory::Path vpdFilePath = std::get<0>(frus.find(objPath)->second);
-
-    const std::vector<nlohmann::json>& groupEEPROM =
-        jsonFile["frus"][vpdFilePath].get_ref<const nlohmann::json::array_t&>();
-
-    nlohmann::json singleFru{};
-    for (const auto& item : groupEEPROM)
-    {
-        if (item["inventoryPath"] == objPath)
-        {
-            // this is the inventory we are looking for
-            singleFru = item;
-            break;
-        }
-    }
-
-    // check if the device qualifies for CM.
-    if (singleFru.value("concurrentlyMaintainable", false))
-    {
-        bool prePostActionRequired = false;
-
-        if ((jsonFile["frus"][vpdFilePath].at(0)).find("preAction") !=
-            jsonFile["frus"][vpdFilePath].at(0).end())
-        {
-            if (!executePreAction(jsonFile, vpdFilePath))
-            {
-                // if the FRU has preAction defined then its execution should
-                // pass to ensure bind/unbind of data.
-                // preAction execution failed. should not call bind/unbind.
-                log<level::ERR>("Pre-Action execution failed for the FRU");
-                return;
-            }
-
-            prePostActionRequired = true;
-        }
-
-        // unbind, bind the driver to trigger parser.
-        triggerVpdCollection(singleFru, objPath);
-
-        // this check is added to avoid file system expensive call in case not
-        // required.
-        if (prePostActionRequired)
-        {
-            // Check if device showed up (test for file)
-            if (!filesystem::exists(vpdFilePath))
-            {
-                try
-                {
-                    // If not, then take failure postAction
-                    executePostFailAction(jsonFile, vpdFilePath);
-                }
-                catch (const GpioException& e)
-                {
-                    PelAdditionalData additionalData{};
-                    additionalData.emplace("DESCRIPTION", e.what());
-                    createPEL(additionalData, PelSeverity::WARNING,
-                              errIntfForGpioError, sdBus);
-                }
-            }
-            else
-            {
-                // bind the LED driver
-                string chipAddr = jsonFile["frus"][vpdFilePath].at(0).value(
-                    "pcaChipAddress", "");
-                cout << "Executing driver binding for chip address - "
-                     << chipAddr << endl;
-
-                executeCmd(createBindUnbindDriverCmnd(chipAddr, "i2c",
-                                                      "leds-pca955x", "/bind"));
-            }
-        }
-        return;
-    }
-    else
-    {
-        elog<InvalidArgument>(Argument::ARGUMENT_NAME("Object Path"),
-                              Argument::ARGUMENT_VALUE(objPath.c_str()));
-    }
-}
-
-void Manager::triggerVpdCollection(const nlohmann::json& singleFru,
-                                   const std::string& path)
-{
-    if ((singleFru.find("devAddress") == singleFru.end()) ||
-        (singleFru.find("driverType") == singleFru.end()) ||
-        (singleFru.find("busType") == singleFru.end()))
-    {
-        // The FRUs is marked for collection but missing mandatory
-        // fields for collection. Log error and return.
-        log<level::ERR>(
-            "Collection Failed as mandatory field missing in Json",
-            entry("ERROR=%s", ("Recollection failed for " + (path)).c_str()));
-
-        return;
-    }
-
-    string deviceAddress = singleFru["devAddress"];
-    const string& driverType = singleFru["driverType"];
-    const string& busType = singleFru["busType"];
-
-    // devTreeStatus flag is present in json as false to mention
-    // that the EEPROM is not mentioned in device tree. If this flag
-    // is absent consider the value to be true, i.e EEPROM is
-    // mentioned in device tree
-    if (!singleFru.value("devTreeStatus", true))
-    {
-        auto pos = deviceAddress.find('-');
-        if (pos != string::npos)
-        {
-            string busNum = deviceAddress.substr(0, pos);
-            deviceAddress = "0x" + deviceAddress.substr(pos + 1, string::npos);
-
-            string deleteDevice =
-                "echo" + deviceAddress + " > /sys/bus/" + busType +
-                "/devices/" + busType + "-" + busNum + "/delete_device";
-            executeCmd(deleteDevice);
-
-            string addDevice =
-                "echo" + driverType + " " + deviceAddress + " > /sys/bus/" +
-                busType + "/devices/" + busType + "-" + busNum + "/new_device";
-            executeCmd(addDevice);
-        }
-        else
-        {
-            const string& inventoryPath =
-                singleFru["inventoryPath"]
-                    .get_ref<const nlohmann::json::string_t&>();
-
-            log<level::ERR>(
-                "Wrong format of device address in Json",
-                entry("ERROR=%s",
-                      ("Recollection failed for " + inventoryPath).c_str()));
-        }
-    }
-    else
-    {
-        executeCmd(createBindUnbindDriverCmnd(deviceAddress, busType,
-                                              driverType, "/unbind"));
-        executeCmd(createBindUnbindDriverCmnd(deviceAddress, busType,
-                                              driverType, "/bind"));
-    }
-}
-
-void Manager::deleteFRUVPD(const sdbusplus::message::object_path& path)
-{
-    std::cout << "Manager called to delete vpd for fru: " << std::string{path}
-              << std::endl;
-
-    using InvalidArgument =
-        sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
-    using Argument = xyz::openbmc_project::Common::InvalidArgument;
-
-    std::string objPath{path};
-
-    // Strip any inventory prefix in path
-    if (objPath.find(INVENTORY_PATH) == 0)
-    {
-        objPath = objPath.substr(sizeof(INVENTORY_PATH) - 1);
-    }
-
-    // if path not found in Json.
-    if (frus.find(objPath) == frus.end())
-    {
-        elog<InvalidArgument>(Argument::ARGUMENT_NAME("Object Path"),
-                              Argument::ARGUMENT_VALUE(objPath.c_str()));
-    }
-
-    inventory::Path& vpdFilePath = std::get<0>(frus.find(objPath)->second);
-
-    string chipAddress =
-        jsonFile["frus"][vpdFilePath].at(0).value("pcaChipAddress", "");
-
-    // if the FRU is present, then unbind the LED driver if any
-    if (readBusProperty(objPath, "xyz.openbmc_project.Inventory.Item",
-                        "Present") == "true")
-    {
-        // check if we have cxp-port populated for the given object path.
-        std::vector<std::string> interfaceList{
-            "xyz.openbmc_project.State.Decorator.OperationalStatus"};
-        MapperResponse subTree = getObjectSubtreeForInterfaces(
-            INVENTORY_PATH + objPath, 0, interfaceList);
-
-        if (subTree.size() != 0)
-        {
-            for (auto [objectPath, serviceInterfaceMap] : subTree)
-            {
-                std::string subTreeObjPath{objectPath};
-
-                // Strip any inventory prefix in path
-                if (subTreeObjPath.find(INVENTORY_PATH) == 0)
-                {
-                    subTreeObjPath =
-                        subTreeObjPath.substr(sizeof(INVENTORY_PATH) - 1);
-                }
-
-                inventory::ObjectMap objectMap{
-                    {subTreeObjPath,
-                     {{"xyz.openbmc_project.State.Decorator.OperationalStatus",
-                       {{"Functional", true}}},
-                      {"xyz.openbmc_project.Inventory.Item",
-                       {{"Present", false}}}}}};
-
-                // objectMap.emplace(objectPath, move(interfaceMap));
-                common::utility::callPIM(move(objectMap));
-            }
-        }
-
-        // Unbind the LED driver for this FRU
-        cout << "Unbinding device- " << chipAddress << endl;
-        executeCmd(createBindUnbindDriverCmnd(chipAddress, "i2c",
-                                              "leds-pca955x", "/unbind"));
-
-        inventory::InterfaceMap interfacesPropMap;
-        clearVpdOnRemoval(INVENTORY_PATH + objPath, interfacesPropMap);
-
-        inventory::ObjectMap objectMap;
-        objectMap.emplace(objPath, move(interfacesPropMap));
-
-        common::utility::callPIM(move(objectMap));
-    }
-}
-
-} // namespace manager
-} // namespace vpd
-} // namespace openpower
diff --git a/vpd-manager/manager.hpp b/vpd-manager/manager.hpp
deleted file mode 100644
index ae278ac..0000000
--- a/vpd-manager/manager.hpp
+++ /dev/null
@@ -1,232 +0,0 @@
-#pragma once
-
-#include "bios_handler.hpp"
-#include "editor_impl.hpp"
-#include "gpioMonitor.hpp"
-
-#include <sdbusplus/asio/object_server.hpp>
-
-#include <map>
-
-namespace openpower
-{
-namespace vpd
-{
-namespace manager
-{
-
-/** @class Manager
- *  @brief OpenBMC VPD Manager implementation.
- *
- *  Implements methods under interface com.ibm.vpd.Manager.
- */
-class Manager
-{
-  public:
-    /* Define all of the basic class operations:
-     * Not allowed:
-     * - Default constructor to avoid nullptrs.
-     * - Copy operations due to internal unique_ptr.
-     * - Move operations due to 'this' being registered as the
-     *  'context' with sdbus.
-     * Allowed:
-     * - Destructor.
-     */
-    Manager() = delete;
-    Manager(const Manager&) = delete;
-    Manager& operator=(const Manager&) = delete;
-    Manager(Manager&&) = delete;
-    ~Manager()
-    {
-        sd_bus_unref(sdBus);
-    }
-
-    /** @brief Constructor.
-     *  @param[in] ioCon - IO context.
-     *  @param[in] iFace - interface to implement.
-     *  @param[in] connection - Dbus Connection.
-     */
-    Manager(std::shared_ptr<boost::asio::io_context>& ioCon,
-            std::shared_ptr<sdbusplus::asio::dbus_interface>& iFace,
-            std::shared_ptr<sdbusplus::asio::connection>& conn);
-
-    /** @brief Implementation for WriteKeyword
-     *  Api to update the keyword value for a given inventory.
-     *
-     *  @param[in] path - Path to the D-Bus object that represents the FRU.
-     *  @param[in] recordName - name of the record for which the keyword value
-     *  has to be modified
-     *  @param[in] keyword - keyword whose value needs to be updated
-     *  @param[in] value - value that needs to be updated
-     */
-    void writeKeyword(const sdbusplus::message::object_path& path,
-                      const std::string& recordName, const std::string& keyword,
-                      const Binary& value);
-
-    /** @brief Implementation for GetFRUsByUnexpandedLocationCode
-     *  A method to get list of FRU D-BUS object paths for a given unexpanded
-     *  location code. Returns empty vector if no FRU found for that location
-     *  code.
-     *
-     *  @param[in] locationCode - An un-expanded Location code.
-     *  @param[in] nodeNumber - Denotes the node in case of a multi-node
-     *  configuration, ignored on a single node system.
-     *
-     *  @return inventoryList[std::vector<sdbusplus::message::object_path>] -
-     *  List of all the FRUs D-Bus object paths for the given location code.
-     */
-    inventory::ListOfPaths getFRUsByUnexpandedLocationCode(
-        const std::string& locationCode, const uint16_t nodeNumber);
-
-    /** @brief Implementation for GetFRUsByExpandedLocationCode
-     *  A method to get list of FRU D-BUS object paths for a given expanded
-     *  location code. Returns empty vector if no FRU found for that location
-     *  code.
-     *
-     *  @param[in] locationCode - Location code in expanded format.
-     *
-     *  @return inventoryList[std::vector<sdbusplus::message::object_path>] -
-     *  List of all the FRUs D-Bus object path for the given location code.
-     */
-    inventory::ListOfPaths
-        getFRUsByExpandedLocationCode(const std::string& locationCode);
-
-    /** @brief Implementation for GetExpandedLocationCode
-     *  An API to get expanded location code corresponding to a given
-     *  un-expanded location code.
-     *
-     *  @param[in] locationCode - Location code in un-expaned format.
-     *  @param[in] nodeNumber - Denotes the node in case of multi-node
-     *  configuration. Ignored in case of single node configuration.
-     *
-     *  @return locationCode[std::string] - Location code in expanded format.
-     */
-    std::string getExpandedLocationCode(const std::string& locationCode,
-                                        const uint16_t nodeNumber);
-
-    /** @brief Api to perform VPD recollection.
-     * This api will trigger parser to perform VPD recollection for FRUs that
-     * can be replaced at standby.
-     */
-    void performVPDRecollection();
-
-    /** @brief Api to delete FRU VPD.
-     * This api will set the present property of given FRU to false. If already
-     * set to false, It will log an error.
-     * @param[in] path - Object path of FRU.
-     */
-    void deleteFRUVPD(const sdbusplus::message::object_path& path);
-
-    /** @brief Api to perform VPD collection for a single fru.
-     *  @param[in] path - Dbus object path of that fru.
-     */
-    void collectFRUVPD(const sdbusplus::message::object_path& path);
-
-  private:
-    /**
-     * @brief An api to process some initial requirements.
-     */
-    void initManager();
-
-    /** @brief process the given JSON file
-     */
-    void processJSON();
-
-    /** @brief Api to register host state callback.
-     * This api will register callback to listen for host state property change.
-     */
-    void listenHostState();
-
-    /** @brief Callback to listen for Host state change
-     *  @param[in] msg - callback message.
-     */
-    void hostStateCallBack(sdbusplus::message_t& msg);
-
-    /** @brief Api to register AssetTag property change.
-     * This api will register callback to listen for asset tag property change.
-     */
-    void listenAssetTag();
-
-    /** @brief Callback to listen for Asset tag change
-     *  @param[in] msg - callback message.
-     */
-    void assetTagCallback(sdbusplus::message_t& msg);
-
-    /**
-     * @brief Restores and defaulted VPD on the system VPD EEPROM.
-     *
-     * This function will read the system VPD EEPROM and check if any of the
-     * keywords that need to be preserved across FRU replacements are defaulted
-     * in the EEPROM. If they are, this function will restore them from the
-     * value that is in the D-Bus cache.
-     */
-    void restoreSystemVpd();
-
-    /**
-     * @brief An api to trigger vpd collection for a fru by bind/unbind of
-     * driver.
-     * @param[in] singleFru - Json of a single fru inder a given EEPROM path.
-     * @param[in] path - Inventory path.
-     */
-    void triggerVpdCollection(const nlohmann::json& singleFru,
-                              const std::string& path);
-
-    /** @brief Update FRU that back up system VPD.
-     *
-     * The API checks if the FRU being updated is system FRU and the record
-     * keyword pair being updated is the one that needs to be backed up and
-     * updates the back up FRU accordingly.
-     *
-     *  @param[in] recordName - name of the record.
-     *  @param[in] keyword - keyword whose value needs to be updated.
-     *  @param[in] value - value that needs to be updated.
-     */
-    void updateSystemVPDBackUpFRU(const std::string& recordName,
-                                  const std::string& keyword,
-                                  const Binary& value);
-
-    /**
-     * @brief Check for essential fru in the system.
-     * The api check for the presence of FRUs marked as essential and logs PEL
-     * in case they are missing.
-     */
-    void checkEssentialFrus();
-
-    // Shared pointer to asio context object.
-    std::shared_ptr<boost::asio::io_context>& ioContext;
-
-    // Shared pointer to Dbus interface class.
-    std::shared_ptr<sdbusplus::asio::dbus_interface>& interface;
-
-    // Shared pointer to bus connection.
-    std::shared_ptr<sdbusplus::asio::connection>& conn;
-
-    // file to store parsed json
-    nlohmann::json jsonFile;
-
-    // map to hold mapping to inventory path to vpd file path
-    // we need as map here as it is in reverse order to that of json
-    inventory::FrusMap frus;
-
-    // map to hold the mapping of location code and inventory path
-    inventory::LocationCodeMap fruLocationCode;
-
-    // map to hold FRUs which can be replaced at standby
-    inventory::ReplaceableFrus replaceableFrus;
-
-    // Shared pointer to gpio monitor object.
-    std::shared_ptr<GpioMonitor> gpioMon;
-
-    // Shared pointer to instance of the BIOS handler.
-    std::shared_ptr<BiosHandler> biosHandler;
-
-    // List of FRUs marked as essential in the system.
-    inventory::EssentialFrus essentialFrus;
-
-    // sd-bus
-    sd_bus* sdBus = nullptr;
-};
-
-} // namespace manager
-} // namespace vpd
-} // namespace openpower
diff --git a/vpd-manager/manager_main.cpp b/vpd-manager/manager_main.cpp
deleted file mode 100644
index bf8c0d9..0000000
--- a/vpd-manager/manager_main.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#include "config.h"
-
-#include "manager.hpp"
-
-#include <sdbusplus/asio/connection.hpp>
-
-int main(int /*argc*/, char** /*argv*/)
-{
-    try
-    {
-        auto io_con = std::make_shared<boost::asio::io_context>();
-        auto connection =
-            std::make_shared<sdbusplus::asio::connection>(*io_con);
-        connection->request_name(BUSNAME);
-
-        auto server = sdbusplus::asio::object_server(connection);
-
-        std::shared_ptr<sdbusplus::asio::dbus_interface> interface =
-            server.add_interface(OBJPATH, IFACE);
-
-        auto vpdManager = std::make_shared<openpower::vpd::manager::Manager>(
-            io_con, interface, connection);
-        interface->initialize();
-
-        // Start event loop.
-        io_con->run();
-
-        exit(EXIT_SUCCESS);
-    }
-    catch (const std::exception& e)
-    {
-        std::cerr << e.what() << "\n";
-    }
-    exit(EXIT_FAILURE);
-}
diff --git a/vpd-manager/meson.build b/vpd-manager/meson.build
index 22ac81a..4e9c10b 100644
--- a/vpd-manager/meson.build
+++ b/vpd-manager/meson.build
@@ -1,42 +1,47 @@
-systemd = dependency('libsystemd', version: '>= 221')
-sdeventplus = dependency('sdeventplus')
+common_SOURCES = ['src/logger.cpp',
+                  'src/parser_factory.cpp',
+                  'src/ipz_parser.cpp',
+                  'src/keyword_vpd_parser.cpp',
+                  'src/ddimm_parser.cpp',
+                  'src/isdimm_parser.cpp',
+                  'src/parser.cpp',
+                  'src/worker.cpp',
+                  'src/backup_restore.cpp',
+                  'src/gpio_monitor.cpp',
+                  'src/event_logger.cpp']
 
-configuration_inc = include_directories('.', '../', '../vpd-parser/')
+vpd_manager_SOURCES = ['src/manager_main.cpp',
+                    'src/manager.cpp',
+                    'src/bios_handler.cpp',
+                    ] + common_SOURCES
 
-vpd_manager_SOURCES = [
-    'manager_main.cpp',
-    'manager.cpp',
-    'editor_impl.cpp',
-    'reader_impl.cpp',
-    'gpioMonitor.cpp',
-    'bios_handler.cpp',
-    '../impl.cpp',
-    '../vpd-parser/ipz_parser.cpp',
-    '../ibm_vpd_utils.cpp',
-    '../common_utility.cpp',
-    '../vpd-parser//keyword_vpd_parser.cpp',
-    '../vpd-parser/memory_vpd_parser.cpp',
-    '../vpd-parser/isdimm_vpd_parser.cpp',
-    '../vpd-parser/parser_factory.cpp'
-]
+parser_dependencies = [sdbusplus, libgpiodcxx, phosphor_logging, phosphor_dbus_interfaces]
 
-vpd_manager_dependencies = [
-    CLI11_dep,
-    libgpiodcxx,
-    phosphor_logging,
-    sdeventplus,
-    systemd,
-    nlohmann_json_dep,
-]
+parser_build_arguments = []
+if get_option('ibm_system').enabled()
+    parser_build_arguments += ['-DIBM_SYSTEM']
+endif
 
 vpd_manager_exe = executable(
-                 'vpd-manager',
-                 vpd_manager_SOURCES,
-                 include_directories : configuration_inc,
-                 dependencies : [
-                                vpd_manager_dependencies,
+                'vpd-manager',
+                vpd_manager_SOURCES,
+                include_directories : ['../', 'include/', '../configuration/'],
+                link_with : libvpdecc,
+                dependencies : [
+                                parser_dependencies,
                                 ],
-                 link_with : libvpdecc,
-                 install : true,
-                 cpp_args : '-DIPZ_PARSER'
+                install : true,
+                cpp_args : parser_build_arguments,
                 )
+
+vpd_parser_SOURCES = ['src/vpd_parser_main.cpp',
+                     ]+ common_SOURCES
+
+vpd_parser_exe = executable(
+                'vpd-parser',
+                vpd_parser_SOURCES,
+                include_directories : ['../', 'include/', '../configuration/'],
+                link_with : libvpdecc,
+                dependencies : parser_dependencies,
+                install : true,
+                )
\ No newline at end of file
diff --git a/vpd-manager/meson.options b/vpd-manager/meson.options
deleted file mode 100644
index 92afa55..0000000
--- a/vpd-manager/meson.options
+++ /dev/null
@@ -1,5 +0,0 @@
-option('BUSNAME', type : 'string', value : 'com.ibm.VPD.Manager', description : 'BUS NAME FOR THE SERVICE')
-option('OBJPATH', type : 'string', value : '/com/ibm/VPD/Manager', description : 'OBJECT PATH FOR THE SERVICE')
-option('IFACE', type : 'string', value : 'com.ibm.VPD.Manager', description : 'INTERFACE NAME')
-option('oe-sdk', type : 'feature', value : 'disabled', description : 'ENABLE OE SDK FOR VPD KEYWORD EDITOR')
-option('INVENTORY_JSON', type : 'string', value : '/var/lib/vpd/vpd_inventory.json', description : 'PATH TO INVENTORY JSON FILE')
diff --git a/vpd-manager/reader_impl.cpp b/vpd-manager/reader_impl.cpp
deleted file mode 100644
index e4f2d8b..0000000
--- a/vpd-manager/reader_impl.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-#include "config.h"
-
-#include "reader_impl.hpp"
-
-#include "ibm_vpd_utils.hpp"
-
-#include <com/ibm/VPD/error.hpp>
-#include <phosphor-logging/elog-errors.hpp>
-#include <xyz/openbmc_project/Common/error.hpp>
-
-#include <algorithm>
-#include <map>
-#include <vector>
-
-#ifdef ManagerTest
-#include "reader_test.hpp"
-#endif
-
-namespace openpower
-{
-namespace vpd
-{
-namespace manager
-{
-namespace reader
-{
-
-using namespace phosphor::logging;
-using namespace openpower::vpd::inventory;
-using namespace openpower::vpd::constants;
-using namespace openpower::vpd::utils::interface;
-
-using InvalidArgument =
-    sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
-using Argument = xyz::openbmc_project::Common::InvalidArgument;
-using LocationNotFound = sdbusplus::com::ibm::VPD::Error::LocationNotFound;
-
-bool ReaderImpl::isValidLocationCode(const LocationCode& locationCode) const
-{
-    if ((locationCode.length() < UNEXP_LOCATION_CODE_MIN_LENGTH) ||
-        (locationCode[0] != 'U') ||
-        ((locationCode.find("fcs", 1, 3) == std::string::npos) &&
-         (locationCode.find("mts", 1, 3) == std::string::npos)))
-    {
-        return false;
-    }
-
-    return true;
-}
-
-LocationCode ReaderImpl::getExpandedLocationCode(
-    const LocationCode& locationCode, const NodeNumber& nodeNumber,
-    const LocationCodeMap& frusLocationCode) const
-{
-    // unused at this moment. Hence to avoid warnings
-    (void)nodeNumber;
-    if (!isValidLocationCode(locationCode))
-    {
-        // argument is not valid
-        elog<InvalidArgument>(Argument::ARGUMENT_NAME("LOCATIONCODE"),
-                              Argument::ARGUMENT_VALUE(locationCode.c_str()));
-    }
-    auto iterator = frusLocationCode.find(locationCode);
-    if (iterator == frusLocationCode.end())
-    {
-        // TODO: Implementation of error logic till then throwing invalid
-        // argument
-        // the location code was not found in the system
-        // elog<LocationNotFound>();
-        elog<InvalidArgument>(Argument::ARGUMENT_NAME("LOCATIONCODE"),
-                              Argument::ARGUMENT_VALUE(locationCode.c_str()));
-    }
-
-    std::string expandedLocationCode{};
-#ifndef ManagerTest
-    utility utilObj;
-#endif
-    expandedLocationCode = utilObj.readBusProperty(
-        iterator->second, IBM_LOCATION_CODE_INF, "LocationCode");
-    return expandedLocationCode;
-}
-
-ListOfPaths ReaderImpl::getFrusAtLocation(
-    const LocationCode& locationCode, const NodeNumber& nodeNumber,
-    const LocationCodeMap& frusLocationCode) const
-{
-    // unused at this moment, to avoid compilation warning
-    (void)nodeNumber;
-
-    // TODO:Implementation related to node number
-    if (!isValidLocationCode(locationCode))
-    {
-        // argument is not valid
-        elog<InvalidArgument>(Argument::ARGUMENT_NAME("LOCATIONCODE"),
-                              Argument::ARGUMENT_VALUE(locationCode.c_str()));
-    }
-
-    auto range = frusLocationCode.equal_range(locationCode);
-
-    if (range.first == frusLocationCode.end())
-    {
-        // TODO: Implementation of error logic till then throwing invalid
-        // argument
-        // the location code was not found in the system
-        // elog<LocationNotFound>();
-        elog<InvalidArgument>(Argument::ARGUMENT_NAME("LOCATIONCODE"),
-                              Argument::ARGUMENT_VALUE(locationCode.c_str()));
-    }
-
-    ListOfPaths inventoryPaths;
-
-    for_each(range.first, range.second,
-             [&inventoryPaths](
-                 const inventory::LocationCodeMap::value_type& mappedItem) {
-                 inventoryPaths.push_back(INVENTORY_PATH + mappedItem.second);
-             });
-    return inventoryPaths;
-}
-
-std::tuple<LocationCode, NodeNumber>
-    ReaderImpl::getCollapsedLocationCode(const LocationCode& locationCode) const
-{
-    // Location code should always start with U and fulfil minimum length
-    // criteria.
-    if (locationCode[0] != 'U' ||
-        locationCode.length() < EXP_LOCATIN_CODE_MIN_LENGTH)
-    {
-        elog<InvalidArgument>(Argument::ARGUMENT_NAME("LOCATIONCODE"),
-                              Argument::ARGUMENT_VALUE(locationCode.c_str()));
-    }
-
-    std::string fc{};
-#ifndef ManagerTest
-    utility utilObj;
-#endif
-
-    fc = utilObj.readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC");
-
-    // get the first part of expanded location code to check for FC or TM
-    std::string firstKeyword = locationCode.substr(1, 4);
-
-    LocationCode unexpandedLocationCode{};
-    NodeNumber nodeNummber = INVALID_NODE_NUMBER;
-
-    // check if this value matches the value of FC kwd
-    if (fc.substr(0, 4) ==
-        firstKeyword) // implies this is Ufcs format location code
-    {
-        // period(.) should be there in expanded location code to seggregate FC,
-        // Node number and SE values.
-        size_t nodeStartPos = locationCode.find('.');
-        if (nodeStartPos == std::string::npos)
-        {
-            elog<InvalidArgument>(
-                Argument::ARGUMENT_NAME("LOCATIONCODE"),
-                Argument::ARGUMENT_VALUE(locationCode.c_str()));
-        }
-
-        // second period(.) should be there to end the node details in non
-        // system location code
-        size_t nodeEndPos = locationCode.find('.', nodeStartPos + 1);
-        if (nodeEndPos == std::string::npos)
-        {
-            elog<InvalidArgument>(
-                Argument::ARGUMENT_NAME("LOCATIONCODE"),
-                Argument::ARGUMENT_VALUE(locationCode.c_str()));
-        }
-
-        // skip 3 for '.ND'
-        nodeNummber = std::stoi(locationCode.substr(
-            nodeStartPos + 3, (nodeEndPos - nodeStartPos - 3)));
-
-        // confirm if there are other details apart FC, Node number and SE in
-        // location code
-        if (locationCode.length() > EXP_LOCATIN_CODE_MIN_LENGTH)
-        {
-            unexpandedLocationCode =
-                locationCode[0] + (std::string) "fcs" +
-                locationCode.substr(nodeEndPos + 1 + SE_KWD_LENGTH,
-                                    std::string::npos);
-        }
-        else
-        {
-            unexpandedLocationCode = "Ufcs";
-        }
-    }
-    else
-    {
-        std::string tm{};
-        // read TM kwd value
-        tm =
-            utilObj.readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "TM");
-        ;
-
-        // check if the substr matches to TM kwd
-        if (tm.substr(0, 4) ==
-            firstKeyword) // implies this is Umts format of location code
-        {
-            // system location code will not have any other details and node
-            // number
-            unexpandedLocationCode = "Umts";
-        }
-        // it does not belong to either "fcs" or "mts"
-        else
-        {
-            elog<InvalidArgument>(
-                Argument::ARGUMENT_NAME("LOCATIONCODE"),
-                Argument::ARGUMENT_VALUE(locationCode.c_str()));
-        }
-    }
-
-    return std::make_tuple(unexpandedLocationCode, nodeNummber);
-}
-
-ListOfPaths ReaderImpl::getFRUsByExpandedLocationCode(
-    const inventory::LocationCode& locationCode,
-    const inventory::LocationCodeMap& frusLocationCode) const
-{
-    std::tuple<LocationCode, NodeNumber> locationAndNodePair =
-        getCollapsedLocationCode(locationCode);
-
-    return getFrusAtLocation(std::get<0>(locationAndNodePair),
-                             std::get<1>(locationAndNodePair),
-                             frusLocationCode);
-}
-} // namespace reader
-} // namespace manager
-} // namespace vpd
-} // namespace openpower
diff --git a/vpd-manager/reader_impl.hpp b/vpd-manager/reader_impl.hpp
deleted file mode 100644
index 7525a4f..0000000
--- a/vpd-manager/reader_impl.hpp
+++ /dev/null
@@ -1,90 +0,0 @@
-#pragma once
-
-#include "types.hpp"
-#include "utilInterface.hpp"
-
-namespace openpower
-{
-namespace vpd
-{
-namespace manager
-{
-namespace reader
-{
-
-using IUtil = openpower::vpd::utils::interface::UtilityInterface;
-/** @class ReaderImpl
- *  @brief Implements functionalities related to reading of VPD related data
- *  from the system.
- */
-class ReaderImpl
-{
-  public:
-    ReaderImpl() = default;
-    ReaderImpl(const ReaderImpl&) = default;
-    ReaderImpl& operator=(const ReaderImpl&) = delete;
-    ReaderImpl(ReaderImpl&&) = default;
-    ReaderImpl& operator=(ReaderImpl&&) = delete;
-    ~ReaderImpl() = default;
-
-#ifdef ManagerTest
-    explicit ReaderImpl(IUtil& obj) : utilObj(obj) {}
-#endif
-
-    /** @brief An API to expand a given unexpanded location code.
-     *  @param[in] locationCode - unexpanded location code.
-     *  @param[in] nodeNumber - node on which we are looking for location code.
-     *  @param[in] frusLocationCode - mapping of inventory path and location
-     * code.
-     *  @return Expanded location code.
-     */
-    inventory::LocationCode getExpandedLocationCode(
-        const inventory::LocationCode& locationCode,
-        const inventory::NodeNumber& nodeNumber,
-        const inventory::LocationCodeMap& frusLocationCode) const;
-
-    /** @brief An API to get list of all the FRUs at the given location code
-     *  @param[in] - location code in unexpanded format
-     *  @param[in] - node number
-     *  @param[in] - mapping of location code and Inventory path
-     *  @return list of Inventory paths at the given location
-     */
-    inventory::ListOfPaths getFrusAtLocation(
-        const inventory::LocationCode& locationCode,
-        const inventory::NodeNumber& nodeNumber,
-        const inventory::LocationCodeMap& frusLocationCode) const;
-
-    /** @brief An API to get list of all the FRUs at the given location code
-     *  @param[in] - location code in unexpanded format
-     *  @param[in] - mapping of location code and Inventory path
-     *  @return list of Inventory paths at the given location
-     */
-    inventory::ListOfPaths getFRUsByExpandedLocationCode(
-        const inventory::LocationCode& locationCode,
-        const inventory::LocationCodeMap& frusLocationCode) const;
-
-  private:
-    /** @brief An api to check validity of location code
-     *  @param[in] - location code
-     *  @return true/false based on validity check
-     */
-    bool isValidLocationCode(const inventory::LocationCode& locationCode) const;
-
-    /** @brief An API to split expanded location code to its un-expanded
-     *  format as represented in VPD JSON and the node number.
-     *  @param[in] Location code in expanded format.
-     *  @return Location code in un-expanded format and its node number.
-     */
-    std::tuple<inventory::LocationCode, inventory::NodeNumber>
-        getCollapsedLocationCode(
-            const inventory::LocationCode& locationCode) const;
-#ifdef ManagerTest
-    IUtil& utilObj;
-#endif
-
-}; // class ReaderImpl
-
-} // namespace reader
-} // namespace manager
-} // namespace vpd
-} // namespace openpower
diff --git a/vpd-manager/src/backup_restore.cpp b/vpd-manager/src/backup_restore.cpp
new file mode 100644
index 0000000..294efc4
--- /dev/null
+++ b/vpd-manager/src/backup_restore.cpp
@@ -0,0 +1,384 @@
+#include "backup_restore.hpp"
+
+#include "constants.hpp"
+#include "event_logger.hpp"
+#include "exceptions.hpp"
+#include "logger.hpp"
+#include "parser.hpp"
+#include "types.hpp"
+
+#include <utility/json_utility.hpp>
+#include <utility/vpd_specific_utility.hpp>
+
+namespace vpd
+{
+BackupAndRestoreStatus BackupAndRestore::m_backupAndRestoreStatus =
+    BackupAndRestoreStatus::NotStarted;
+
+BackupAndRestore::BackupAndRestore(const nlohmann::json& i_sysCfgJsonObj) :
+    m_sysCfgJsonObj(i_sysCfgJsonObj)
+{
+    std::string l_backupAndRestoreCfgFilePath =
+        i_sysCfgJsonObj.value("backupRestoreConfigPath", "");
+    try
+    {
+        m_backupAndRestoreCfgJsonObj =
+            jsonUtility::getParsedJson(l_backupAndRestoreCfgFilePath);
+    }
+    catch (const std::exception& ex)
+    {
+        logging::logMessage(
+            "Failed to intialize backup and restore object for file = " +
+            l_backupAndRestoreCfgFilePath);
+        throw(ex);
+    }
+}
+
+std::tuple<types::VPDMapVariant, types::VPDMapVariant>
+    BackupAndRestore::backupAndRestore()
+{
+    auto l_emptyVariantPair =
+        std::make_tuple(std::monostate{}, std::monostate{});
+
+    if (m_backupAndRestoreStatus >= BackupAndRestoreStatus::Invoked)
+    {
+        logging::logMessage("Backup and restore invoked already.");
+        return l_emptyVariantPair;
+    }
+
+    m_backupAndRestoreStatus = BackupAndRestoreStatus::Invoked;
+    try
+    {
+        if (m_backupAndRestoreCfgJsonObj.empty() ||
+            !m_backupAndRestoreCfgJsonObj.contains("source") ||
+            !m_backupAndRestoreCfgJsonObj.contains("destination") ||
+            !m_backupAndRestoreCfgJsonObj.contains("type") ||
+            !m_backupAndRestoreCfgJsonObj.contains("backupMap"))
+        {
+            logging::logMessage(
+                "Backup restore config JSON is missing necessary tag(s), can't initiate backup and restore.");
+            return l_emptyVariantPair;
+        }
+
+        std::string l_srcVpdPath;
+        types::VPDMapVariant l_srcVpdVariant;
+        if (l_srcVpdPath = m_backupAndRestoreCfgJsonObj["source"].value(
+                "hardwarePath", "");
+            !l_srcVpdPath.empty() && std::filesystem::exists(l_srcVpdPath))
+        {
+            std::shared_ptr<Parser> l_vpdParser =
+                std::make_shared<Parser>(l_srcVpdPath, m_sysCfgJsonObj);
+            l_srcVpdVariant = l_vpdParser->parse();
+        }
+        else if (l_srcVpdPath = m_backupAndRestoreCfgJsonObj["source"].value(
+                     "inventoryPath", "");
+                 l_srcVpdPath.empty())
+        {
+            logging::logMessage(
+                "Couldn't extract source path, can't initiate backup and restore.");
+            return l_emptyVariantPair;
+        }
+
+        std::string l_dstVpdPath;
+        types::VPDMapVariant l_dstVpdVariant;
+        if (l_dstVpdPath = m_backupAndRestoreCfgJsonObj["destination"].value(
+                "hardwarePath", "");
+            !l_dstVpdPath.empty() && std::filesystem::exists(l_dstVpdPath))
+        {
+            std::shared_ptr<Parser> l_vpdParser =
+                std::make_shared<Parser>(l_dstVpdPath, m_sysCfgJsonObj);
+            l_dstVpdVariant = l_vpdParser->parse();
+        }
+        else if (l_dstVpdPath = m_backupAndRestoreCfgJsonObj["destination"]
+                                    .value("inventoryPath", "");
+                 l_dstVpdPath.empty())
+        {
+            logging::logMessage(
+                "Couldn't extract destination path, can't initiate backup and restore.");
+            return l_emptyVariantPair;
+        }
+
+        // Implement backup and restore for IPZ type VPD
+        auto l_backupAndRestoreType =
+            m_backupAndRestoreCfgJsonObj.value("type", "");
+        if (l_backupAndRestoreType.compare("IPZ") == constants::STR_CMP_SUCCESS)
+        {
+            types::IPZVpdMap l_srcVpdMap;
+            if (auto l_srcVpdPtr =
+                    std::get_if<types::IPZVpdMap>(&l_srcVpdVariant))
+            {
+                l_srcVpdMap = *l_srcVpdPtr;
+            }
+            else if (!std::holds_alternative<std::monostate>(l_srcVpdVariant))
+            {
+                logging::logMessage("Source VPD is not of IPZ type.");
+                return l_emptyVariantPair;
+            }
+
+            types::IPZVpdMap l_dstVpdMap;
+            if (auto l_dstVpdPtr =
+                    std::get_if<types::IPZVpdMap>(&l_dstVpdVariant))
+            {
+                l_dstVpdMap = *l_dstVpdPtr;
+            }
+            else if (!std::holds_alternative<std::monostate>(l_dstVpdVariant))
+            {
+                logging::logMessage("Destination VPD is not of IPZ type.");
+                return l_emptyVariantPair;
+            }
+
+            backupAndRestoreIpzVpd(l_srcVpdMap, l_dstVpdMap, l_srcVpdPath,
+                                   l_dstVpdPath);
+            m_backupAndRestoreStatus = BackupAndRestoreStatus::Completed;
+
+            return std::make_tuple(l_srcVpdMap, l_dstVpdMap);
+        }
+        // Note: add implementation here to support any other VPD type.
+    }
+    catch (const std::exception& ex)
+    {
+        logging::logMessage("Back up and restore failed with exception: " +
+                            std::string(ex.what()));
+    }
+    return l_emptyVariantPair;
+}
+
+void BackupAndRestore::backupAndRestoreIpzVpd(
+    types::IPZVpdMap& io_srcVpdMap, types::IPZVpdMap& io_dstVpdMap,
+    const std::string& i_srcPath, const std::string& i_dstPath)
+{
+    if (!m_backupAndRestoreCfgJsonObj["backupMap"].is_array())
+    {
+        logging::logMessage(
+            "Invalid value found for tag backupMap, in backup and restore config JSON.");
+        return;
+    }
+
+    const std::string l_srcFruPath =
+        jsonUtility::getFruPathFromJson(m_sysCfgJsonObj, i_srcPath);
+    const std::string l_dstFruPath =
+        jsonUtility::getFruPathFromJson(m_sysCfgJsonObj, i_dstPath);
+    if (l_srcFruPath.empty() || l_dstFruPath.empty())
+    {
+        logging::logMessage(
+            "Couldn't find either source or destination FRU path.");
+        return;
+    }
+
+    const std::string l_srcInvPath =
+        jsonUtility::getInventoryObjPathFromJson(m_sysCfgJsonObj, i_srcPath);
+    const std::string l_dstInvPath =
+        jsonUtility::getInventoryObjPathFromJson(m_sysCfgJsonObj, i_dstPath);
+    if (l_srcInvPath.empty() || l_dstInvPath.empty())
+    {
+        logging::logMessage(
+            "Couldn't find either source or destination inventory path.");
+        return;
+    }
+
+    const std::string l_srcServiceName =
+        jsonUtility::getServiceName(m_sysCfgJsonObj, l_srcInvPath);
+    const std::string l_dstServiceName =
+        jsonUtility::getServiceName(m_sysCfgJsonObj, l_dstInvPath);
+    if (l_srcServiceName.empty() || l_dstServiceName.empty())
+    {
+        logging::logMessage(
+            "Couldn't find either source or destination DBus service name.");
+        return;
+    }
+
+    for (const auto& l_aRecordKwInfo :
+         m_backupAndRestoreCfgJsonObj["backupMap"])
+    {
+        const std::string& l_srcRecordName =
+            l_aRecordKwInfo.value("sourceRecord", "");
+        const std::string& l_srcKeywordName =
+            l_aRecordKwInfo.value("sourceKeyword", "");
+        const std::string& l_dstRecordName =
+            l_aRecordKwInfo.value("destinationRecord", "");
+        const std::string& l_dstKeywordName =
+            l_aRecordKwInfo.value("destinationKeyword", "");
+
+        if (l_srcRecordName.empty() || l_dstRecordName.empty() ||
+            l_srcKeywordName.empty() || l_dstKeywordName.empty())
+        {
+            logging::logMessage(
+                "Record or keyword not found in the backup and restore config JSON.");
+            continue;
+        }
+
+        if (!io_srcVpdMap.empty() &&
+            io_srcVpdMap.find(l_srcRecordName) == io_srcVpdMap.end())
+        {
+            logging::logMessage(
+                "Record: " + l_srcRecordName +
+                ", is not found in the source path: " + i_srcPath);
+            continue;
+        }
+
+        if (!io_dstVpdMap.empty() &&
+            io_dstVpdMap.find(l_dstRecordName) == io_dstVpdMap.end())
+        {
+            logging::logMessage(
+                "Record: " + l_dstRecordName +
+                ", is not found in the destination path: " + i_dstPath);
+            continue;
+        }
+
+        types::BinaryVector l_defaultBinaryValue;
+        if (l_aRecordKwInfo.contains("defaultValue") &&
+            l_aRecordKwInfo["defaultValue"].is_array())
+        {
+            l_defaultBinaryValue =
+                l_aRecordKwInfo["defaultValue"].get<types::BinaryVector>();
+        }
+        else
+        {
+            logging::logMessage(
+                "Couldn't read default value for record name: " +
+                l_srcRecordName + ", keyword name: " + l_srcKeywordName +
+                " from backup and restore config JSON file.");
+            continue;
+        }
+
+        bool l_isPelRequired = l_aRecordKwInfo.value("isPelRequired", false);
+
+        types::BinaryVector l_srcBinaryValue;
+        std::string l_srcStrValue;
+        if (!io_srcVpdMap.empty())
+        {
+            vpdSpecificUtility::getKwVal(io_srcVpdMap.at(l_srcRecordName),
+                                         l_srcKeywordName, l_srcStrValue);
+            l_srcBinaryValue =
+                types::BinaryVector(l_srcStrValue.begin(), l_srcStrValue.end());
+        }
+        else
+        {
+            // Read keyword value from DBus
+            const auto l_value = dbusUtility::readDbusProperty(
+                l_srcServiceName, l_srcInvPath,
+                constants::ipzVpdInf + l_srcRecordName, l_srcKeywordName);
+            if (const auto l_binaryValue =
+                    std::get_if<types::BinaryVector>(&l_value))
+            {
+                l_srcBinaryValue = *l_binaryValue;
+                l_srcStrValue = std::string(l_srcBinaryValue.begin(),
+                                            l_srcBinaryValue.end());
+            }
+        }
+
+        types::BinaryVector l_dstBinaryValue;
+        std::string l_dstStrValue;
+        if (!io_dstVpdMap.empty())
+        {
+            vpdSpecificUtility::getKwVal(io_dstVpdMap.at(l_dstRecordName),
+                                         l_dstKeywordName, l_dstStrValue);
+            l_dstBinaryValue =
+                types::BinaryVector(l_dstStrValue.begin(), l_dstStrValue.end());
+        }
+        else
+        {
+            // Read keyword value from DBus
+            const auto l_value = dbusUtility::readDbusProperty(
+                l_dstServiceName, l_dstInvPath,
+                constants::ipzVpdInf + l_dstRecordName, l_dstKeywordName);
+            if (const auto l_binaryValue =
+                    std::get_if<types::BinaryVector>(&l_value))
+            {
+                l_dstBinaryValue = *l_binaryValue;
+                l_dstStrValue = std::string(l_dstBinaryValue.begin(),
+                                            l_dstBinaryValue.end());
+            }
+        }
+
+        if (l_srcBinaryValue != l_dstBinaryValue)
+        {
+            // ToDo: Handle if there is no valid default value in the backup and
+            // restore config JSON.
+            if (l_dstBinaryValue == l_defaultBinaryValue)
+            {
+                // Update keyword's value on hardware
+                auto l_vpdParser =
+                    std::make_shared<Parser>(l_dstFruPath, m_sysCfgJsonObj);
+
+                auto l_bytesUpdatedOnHardware = l_vpdParser->updateVpdKeyword(
+                    types::IpzData(l_dstRecordName, l_dstKeywordName,
+                                   l_srcBinaryValue));
+
+                /* To keep the data in sync between hardware and parsed map
+                 updating the io_dstVpdMap. This should only be done if write
+                 on hardware returns success.*/
+                if (!io_dstVpdMap.empty() && l_bytesUpdatedOnHardware > 0)
+                {
+                    io_dstVpdMap[l_dstRecordName][l_dstKeywordName] =
+                        l_srcStrValue;
+                }
+                continue;
+            }
+
+            if (l_srcBinaryValue == l_defaultBinaryValue)
+            {
+                // Update keyword's value on hardware
+                auto l_vpdParser =
+                    std::make_shared<Parser>(l_srcFruPath, m_sysCfgJsonObj);
+
+                auto l_bytesUpdatedOnHardware = l_vpdParser->updateVpdKeyword(
+                    types::IpzData(l_srcRecordName, l_srcKeywordName,
+                                   l_dstBinaryValue));
+
+                /* To keep the data in sync between hardware and parsed map
+                 updating the io_srcVpdMap. This should only be done if write
+                 on hardware returns success.*/
+                if (!io_srcVpdMap.empty() && l_bytesUpdatedOnHardware > 0)
+                {
+                    io_srcVpdMap[l_srcRecordName][l_srcKeywordName] =
+                        l_dstStrValue;
+                }
+            }
+            else
+            {
+                /**
+                 * Update io_srcVpdMap to publish the same data on DBus, which
+                 * is already present on the DBus. Because after calling
+                 * backupAndRestore API the map value will get published to DBus
+                 * in the worker flow.
+                 */
+                if (!io_srcVpdMap.empty() && io_dstVpdMap.empty())
+                {
+                    io_srcVpdMap[l_srcRecordName][l_srcKeywordName] =
+                        l_dstStrValue;
+                }
+
+                std::string l_errorMsg(
+                    "Mismatch found between source and destination VPD for record : " +
+                    l_srcRecordName + " and keyword : " + l_srcKeywordName +
+                    " . Value read from source : " + l_srcStrValue +
+                    " . Value read from destination : " + l_dstStrValue);
+
+                EventLogger::createSyncPel(
+                    types::ErrorType::VpdMismatch, types::SeverityType::Warning,
+                    __FILE__, __FUNCTION__, 0, l_errorMsg, std::nullopt,
+                    std::nullopt, std::nullopt, std::nullopt);
+            }
+        }
+        else if (l_srcBinaryValue == l_defaultBinaryValue &&
+                 l_dstBinaryValue == l_defaultBinaryValue && l_isPelRequired)
+        {
+            std::string l_errorMsg(
+                "Default value found on both source and destination VPD, for record: " +
+                l_srcRecordName + " and keyword: " + l_srcKeywordName);
+
+            EventLogger::createSyncPel(
+                types::ErrorType::DefaultValue, types::SeverityType::Error,
+                __FILE__, __FUNCTION__, 0, l_errorMsg, std::nullopt,
+                std::nullopt, std::nullopt, std::nullopt);
+        }
+    }
+}
+
+void BackupAndRestore::setBackupAndRestoreStatus(
+    const BackupAndRestoreStatus& i_status)
+{
+    m_backupAndRestoreStatus = i_status;
+}
+} // namespace vpd
diff --git a/vpd-manager/src/bios_handler.cpp b/vpd-manager/src/bios_handler.cpp
new file mode 100644
index 0000000..44afff3
--- /dev/null
+++ b/vpd-manager/src/bios_handler.cpp
@@ -0,0 +1,764 @@
+#include "config.h"
+
+#include "bios_handler.hpp"
+
+#include "constants.hpp"
+#include "logger.hpp"
+
+#include <sdbusplus/bus/match.hpp>
+#include <utility/common_utility.hpp>
+#include <utility/dbus_utility.hpp>
+
+#include <string>
+
+namespace vpd
+{
+// Template declaration to define APIs.
+template class BiosHandler<IbmBiosHandler>;
+
+template <typename T>
+void BiosHandler<T>::checkAndListenPldmService()
+{
+    // Setup a call back match on NameOwnerChanged to determine when PLDM is up.
+    static std::shared_ptr<sdbusplus::bus::match_t> l_nameOwnerMatch =
+        std::make_shared<sdbusplus::bus::match_t>(
+            *m_asioConn,
+            sdbusplus::bus::match::rules::nameOwnerChanged(
+                constants::pldmServiceName),
+            [this](sdbusplus::message_t& l_msg) {
+                if (l_msg.is_method_error())
+                {
+                    logging::logMessage(
+                        "Error in reading PLDM name owner changed signal.");
+                    return;
+                }
+
+                std::string l_name;
+                std::string l_newOwner;
+                std::string l_oldOwner;
+
+                l_msg.read(l_name, l_oldOwner, l_newOwner);
+
+                if (!l_newOwner.empty() &&
+                    (l_name.compare(constants::pldmServiceName) ==
+                     constants::STR_CMP_SUCCESS))
+                {
+                    m_specificBiosHandler->backUpOrRestoreBiosAttributes();
+
+                    // Start listener now that we have done the restore.
+                    listenBiosAttributes();
+
+                    //  We don't need the match anymore
+                    l_nameOwnerMatch.reset();
+                }
+            });
+
+    // Based on PLDM service status reset owner match registered above and
+    // trigger BIOS attribute sync.
+    if (dbusUtility::isServiceRunning(constants::pldmServiceName))
+    {
+        l_nameOwnerMatch.reset();
+        m_specificBiosHandler->backUpOrRestoreBiosAttributes();
+
+        // Start listener now that we have done the restore.
+        listenBiosAttributes();
+    }
+}
+
+template <typename T>
+void BiosHandler<T>::listenBiosAttributes()
+{
+    static std::shared_ptr<sdbusplus::bus::match_t> l_biosMatch =
+        std::make_shared<sdbusplus::bus::match_t>(
+            *m_asioConn,
+            sdbusplus::bus::match::rules::propertiesChanged(
+                constants::biosConfigMgrObjPath,
+                constants::biosConfigMgrInterface),
+            [this](sdbusplus::message_t& l_msg) {
+                m_specificBiosHandler->biosAttributesCallback(l_msg);
+            });
+}
+
+void IbmBiosHandler::biosAttributesCallback(sdbusplus::message_t& i_msg)
+{
+    if (i_msg.is_method_error())
+    {
+        logging::logMessage("Error in reading BIOS attribute signal. ");
+        return;
+    }
+
+    std::string l_objPath;
+    types::BiosBaseTableType l_propMap;
+    i_msg.read(l_objPath, l_propMap);
+
+    for (auto l_property : l_propMap)
+    {
+        if (l_property.first != "BaseBIOSTable")
+        {
+            // Looking for change in Base BIOS table only.
+            continue;
+        }
+
+        if (auto l_attributeList =
+                std::get_if<std::map<std::string, types::BiosProperty>>(
+                    &(l_property.second)))
+        {
+            for (const auto& l_attribute : *l_attributeList)
+            {
+                if (auto l_val = std::get_if<std::string>(
+                        &(std::get<5>(std::get<1>(l_attribute)))))
+                {
+                    std::string l_attributeName = std::get<0>(l_attribute);
+                    if (l_attributeName == "hb_memory_mirror_mode")
+                    {
+                        saveAmmToVpd(*l_val);
+                    }
+
+                    if (l_attributeName == "pvm_keep_and_clear")
+                    {
+                        saveKeepAndClearToVpd(*l_val);
+                    }
+
+                    if (l_attributeName == "pvm_create_default_lpar")
+                    {
+                        saveCreateDefaultLparToVpd(*l_val);
+                    }
+
+                    if (l_attributeName == "pvm_clear_nvram")
+                    {
+                        saveClearNvramToVpd(*l_val);
+                    }
+
+                    continue;
+                }
+
+                if (auto l_val = std::get_if<int64_t>(
+                        &(std::get<5>(std::get<1>(l_attribute)))))
+                {
+                    std::string l_attributeName = std::get<0>(l_attribute);
+                    if (l_attributeName == "hb_field_core_override")
+                    {
+                        saveFcoToVpd(*l_val);
+                    }
+                }
+            }
+        }
+        else
+        {
+            // TODO: log a predicitive PEL.
+            logging::logMessage("Invalid typre received from BIOS table.");
+            break;
+        }
+    }
+}
+
+void IbmBiosHandler::backUpOrRestoreBiosAttributes()
+{
+    // process FCO
+    processFieldCoreOverride();
+
+    // process AMM
+    processActiveMemoryMirror();
+
+    // process LPAR
+    processCreateDefaultLpar();
+
+    // process clear NVRAM
+    processClearNvram();
+
+    // process keep and clear
+    processKeepAndClear();
+}
+
+types::BiosAttributeCurrentValue
+    IbmBiosHandler::readBiosAttribute(const std::string& i_attributeName)
+{
+    types::BiosAttributeCurrentValue l_attrValueVariant =
+        dbusUtility::biosGetAttributeMethodCall(i_attributeName);
+
+    return l_attrValueVariant;
+}
+
+void IbmBiosHandler::processFieldCoreOverride()
+{
+    // TODO: Should we avoid doing this at runtime?
+
+    // Read required keyword from Dbus.
+    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
+        constants::pimServiceName, constants::systemVpdInvPath,
+        constants::vsysInf, constants::kwdRG);
+
+    if (auto l_fcoInVpd = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
+    {
+        // default length of the keyword is 4 bytes.
+        if (l_fcoInVpd->size() != constants::VALUE_4)
+        {
+            logging::logMessage(
+                "Invalid value read for FCO from D-Bus. Skipping.");
+        }
+
+        //  If FCO in VPD contains anything other that ASCII Space, restore to
+        //  BIOS
+        if (std::any_of(l_fcoInVpd->cbegin(), l_fcoInVpd->cend(),
+                        [](uint8_t l_val) {
+                            return l_val != constants::ASCII_OF_SPACE;
+                        }))
+        {
+            // Restore the data to BIOS.
+            saveFcoToBios(*l_fcoInVpd);
+        }
+        else
+        {
+            types::BiosAttributeCurrentValue l_attrValueVariant =
+                readBiosAttribute("hb_field_core_override");
+
+            if (auto l_fcoInBios = std::get_if<int64_t>(&l_attrValueVariant))
+            {
+                // save the BIOS data to VPD
+                saveFcoToVpd(*l_fcoInBios);
+
+                return;
+            }
+            logging::logMessage("Invalid type recieved for FCO from BIOS.");
+        }
+        return;
+    }
+    logging::logMessage("Invalid type recieved for FCO from VPD.");
+}
+
+void IbmBiosHandler::saveFcoToVpd(int64_t i_fcoInBios)
+{
+    if (i_fcoInBios < 0)
+    {
+        logging::logMessage("Invalid FCO value in BIOS. Skip updating to VPD");
+        return;
+    }
+
+    // Read required keyword from Dbus.
+    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
+        constants::pimServiceName, constants::systemVpdInvPath,
+        constants::vsysInf, constants::kwdRG);
+
+    if (auto l_fcoInVpd = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
+    {
+        // default length of the keyword is 4 bytes.
+        if (l_fcoInVpd->size() != constants::VALUE_4)
+        {
+            logging::logMessage(
+                "Invalid value read for FCO from D-Bus. Skipping.");
+            return;
+        }
+
+        // convert to VPD value type
+        types::BinaryVector l_biosValInVpdFormat = {
+            0, 0, 0, static_cast<uint8_t>(i_fcoInBios)};
+
+        // Update only when the data are different.
+        if (std::memcmp(l_biosValInVpdFormat.data(), l_fcoInVpd->data(),
+                        constants::VALUE_4) != constants::SUCCESS)
+        {
+            if (constants::FAILURE ==
+                m_manager->updateKeyword(
+                    SYSTEM_VPD_FILE_PATH,
+                    types::IpzData("VSYS", constants::kwdRG,
+                                   l_biosValInVpdFormat)))
+            {
+                logging::logMessage(
+                    "Failed to update " + std::string(constants::kwdRG) +
+                    " keyword to VPD.");
+            }
+        }
+    }
+    else
+    {
+        logging::logMessage("Invalid type read for FCO from DBus.");
+    }
+}
+
+void IbmBiosHandler::saveFcoToBios(const types::BinaryVector& i_fcoVal)
+{
+    if (i_fcoVal.size() != constants::VALUE_4)
+    {
+        logging::logMessage("Bad size for FCO received. Skip writing to BIOS");
+        return;
+    }
+
+    types::PendingBIOSAttrs l_pendingBiosAttribute;
+    l_pendingBiosAttribute.push_back(std::make_pair(
+        "hb_field_core_override",
+        std::make_tuple(
+            "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Integer",
+            i_fcoVal.at(constants::VALUE_3))));
+
+    try
+    {
+        dbusUtility::writeDbusProperty(
+            constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
+            constants::biosConfigMgrInterface, "PendingAttributes",
+            l_pendingBiosAttribute);
+    }
+    catch (const std::exception& l_ex)
+    {
+        // TODO: Should we log informational PEL here as well?
+        logging::logMessage(
+            "DBus call to update FCO value in pending attribute failed. " +
+            std::string(l_ex.what()));
+    }
+}
+
+void IbmBiosHandler::saveAmmToVpd(const std::string& i_memoryMirrorMode)
+{
+    if (i_memoryMirrorMode.empty())
+    {
+        logging::logMessage(
+            "Empty memory mirror mode value from BIOS. Skip writing to VPD");
+        return;
+    }
+
+    // Read existing value.
+    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
+        constants::pimServiceName, constants::systemVpdInvPath,
+        constants::utilInf, constants::kwdAMM);
+
+    if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
+    {
+        auto l_ammValInVpd = *l_pVal;
+
+        types::BinaryVector l_valToUpdateInVpd{
+            (i_memoryMirrorMode == "Enabled" ? constants::AMM_ENABLED_IN_VPD
+                                             : constants::AMM_DISABLED_IN_VPD)};
+
+        // Check if value is already updated on VPD.
+        if (l_ammValInVpd.at(0) == l_valToUpdateInVpd.at(0))
+        {
+            return;
+        }
+
+        if (constants::FAILURE ==
+            m_manager->updateKeyword(
+                SYSTEM_VPD_FILE_PATH,
+                types::IpzData("UTIL", constants::kwdAMM, l_valToUpdateInVpd)))
+        {
+            logging::logMessage(
+                "Failed to update " + std::string(constants::kwdAMM) +
+                " keyword to VPD");
+        }
+    }
+    else
+    {
+        // TODO: Add PEL
+        logging::logMessage(
+            "Invalid type read for memory mirror mode value from DBus. Skip writing to VPD");
+    }
+}
+
+void IbmBiosHandler::saveAmmToBios(const std::string& i_ammVal)
+{
+    if (i_ammVal.size() != constants::VALUE_1)
+    {
+        logging::logMessage("Bad size for AMM received, Skip writing to BIOS");
+        return;
+    }
+
+    const std::string l_valtoUpdate =
+        (i_ammVal.at(0) == constants::VALUE_2) ? "Enabled" : "Disabled";
+
+    types::PendingBIOSAttrs l_pendingBiosAttribute;
+    l_pendingBiosAttribute.push_back(std::make_pair(
+        "hb_memory_mirror_mode",
+        std::make_tuple(
+            "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
+            l_valtoUpdate)));
+
+    try
+    {
+        dbusUtility::writeDbusProperty(
+            constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
+            constants::biosConfigMgrInterface, "PendingAttributes",
+            l_pendingBiosAttribute);
+    }
+    catch (const std::exception& l_ex)
+    {
+        // TODO: Should we log informational PEL here as well?
+        logging::logMessage(
+            "DBus call to update AMM value in pending attribute failed. " +
+            std::string(l_ex.what()));
+    }
+}
+
+void IbmBiosHandler::processActiveMemoryMirror()
+{
+    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
+        constants::pimServiceName, constants::systemVpdInvPath,
+        constants::utilInf, constants::kwdAMM);
+
+    if (auto pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
+    {
+        auto l_ammValInVpd = *pVal;
+
+        // Check if active memory mirror value is default in VPD.
+        if (l_ammValInVpd.at(0) == constants::VALUE_0)
+        {
+            types::BiosAttributeCurrentValue l_attrValueVariant =
+                readBiosAttribute("hb_memory_mirror_mode");
+
+            if (auto pVal = std::get_if<std::string>(&l_attrValueVariant))
+            {
+                saveAmmToVpd(*pVal);
+                return;
+            }
+            logging::logMessage(
+                "Invalid type recieved for auto memory mirror mode from BIOS.");
+            return;
+        }
+        else
+        {
+            saveAmmToBios(std::to_string(l_ammValInVpd.at(0)));
+        }
+        return;
+    }
+    logging::logMessage(
+        "Invalid type recieved for auto memory mirror mode from VPD.");
+}
+
+void IbmBiosHandler::saveCreateDefaultLparToVpd(
+    const std::string& i_createDefaultLparVal)
+{
+    if (i_createDefaultLparVal.empty())
+    {
+        logging::logMessage(
+            "Empty value received for Lpar from BIOS. Skip writing in VPD.");
+        return;
+    }
+
+    // Read required keyword from DBus as we need to set only a Bit.
+    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
+        constants::pimServiceName, constants::systemVpdInvPath,
+        constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);
+
+    if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
+    {
+        commonUtility::toLower(
+            const_cast<std::string&>(i_createDefaultLparVal));
+
+        // Check for second bit. Bit set for enabled else disabled.
+        if (((((*l_pVal).at(0) & 0x02) == 0x02) &&
+             (i_createDefaultLparVal.compare("enabled") ==
+              constants::STR_CMP_SUCCESS)) ||
+            ((((*l_pVal).at(0) & 0x02) == 0x00) &&
+             (i_createDefaultLparVal.compare("disabled") ==
+              constants::STR_CMP_SUCCESS)))
+        {
+            // Values are same, Don;t update.
+            return;
+        }
+
+        types::BinaryVector l_valToUpdateInVpd;
+        if (i_createDefaultLparVal.compare("enabled") ==
+            constants::STR_CMP_SUCCESS)
+        {
+            // 2nd Bit is used to store the value.
+            l_valToUpdateInVpd.emplace_back((*l_pVal).at(0) | 0x02);
+        }
+        else
+        {
+            // 2nd Bit is used to store the value.
+            l_valToUpdateInVpd.emplace_back((*l_pVal).at(0) & ~(0x02));
+        }
+
+        if (-1 ==
+            m_manager->updateKeyword(
+                SYSTEM_VPD_FILE_PATH,
+                types::IpzData("UTIL", constants::kwdClearNVRAM_CreateLPAR,
+                               l_valToUpdateInVpd)))
+        {
+            logging::logMessage(
+                "Failed to update " +
+                std::string(constants::kwdClearNVRAM_CreateLPAR) +
+                " keyword to VPD");
+        }
+
+        return;
+    }
+    logging::logMessage(
+        "Invalid type recieved for create default Lpar from VPD.");
+}
+
+void IbmBiosHandler::saveCreateDefaultLparToBios(
+    const std::string& i_createDefaultLparVal)
+{
+    // checking for exact length as it is a string and can have garbage value.
+    if (i_createDefaultLparVal.size() != constants::VALUE_1)
+    {
+        logging::logMessage(
+            "Bad size for Create default LPAR in VPD. Skip writing to BIOS.");
+        return;
+    }
+
+    std::string l_valtoUpdate =
+        (i_createDefaultLparVal.at(0) & 0x02) ? "Enabled" : "Disabled";
+
+    types::PendingBIOSAttrs l_pendingBiosAttribute;
+    l_pendingBiosAttribute.push_back(std::make_pair(
+        "pvm_create_default_lpar",
+        std::make_tuple(
+            "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
+            l_valtoUpdate)));
+
+    try
+    {
+        dbusUtility::writeDbusProperty(
+            constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
+            constants::biosConfigMgrInterface, "PendingAttributes",
+            l_pendingBiosAttribute);
+    }
+    catch (const std::exception& l_ex)
+    {
+        logging::logMessage(
+            "DBus call to update lpar value in pending attribute failed. " +
+            std::string(l_ex.what()));
+    }
+
+    return;
+}
+
+void IbmBiosHandler::processCreateDefaultLpar()
+{
+    // Read required keyword from DBus.
+    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
+        constants::pimServiceName, constants::systemVpdInvPath,
+        constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);
+
+    if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
+    {
+        saveCreateDefaultLparToBios(std::to_string(l_pVal->at(0)));
+        return;
+    }
+    logging::logMessage(
+        "Invalid type recieved for create default Lpar from VPD.");
+}
+
+void IbmBiosHandler::saveClearNvramToVpd(const std::string& i_clearNvramVal)
+{
+    if (i_clearNvramVal.empty())
+    {
+        logging::logMessage(
+            "Empty value received for clear NVRAM from BIOS. Skip updating to VPD.");
+        return;
+    }
+
+    // Read required keyword from DBus as we need to set only a Bit.
+    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
+        constants::pimServiceName, constants::systemVpdInvPath,
+        constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);
+
+    if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
+    {
+        commonUtility::toLower(const_cast<std::string&>(i_clearNvramVal));
+
+        // Check for third bit. Bit set for enabled else disabled.
+        if (((((*l_pVal).at(0) & 0x04) == 0x04) &&
+             (i_clearNvramVal.compare("enabled") ==
+              constants::STR_CMP_SUCCESS)) ||
+            ((((*l_pVal).at(0) & 0x04) == 0x00) &&
+             (i_clearNvramVal.compare("disabled") ==
+              constants::STR_CMP_SUCCESS)))
+        {
+            // Don't update, values are same.
+            return;
+        }
+
+        types::BinaryVector l_valToUpdateInVpd;
+        if (i_clearNvramVal.compare("enabled") == constants::STR_CMP_SUCCESS)
+        {
+            // 3rd bit is used to store the value.
+            l_valToUpdateInVpd.emplace_back(
+                (*l_pVal).at(0) | constants::VALUE_4);
+        }
+        else
+        {
+            // 3rd bit is used to store the value.
+            l_valToUpdateInVpd.emplace_back(
+                (*l_pVal).at(0) & ~(constants::VALUE_4));
+        }
+
+        if (-1 ==
+            m_manager->updateKeyword(
+                SYSTEM_VPD_FILE_PATH,
+                types::IpzData("UTIL", constants::kwdClearNVRAM_CreateLPAR,
+                               l_valToUpdateInVpd)))
+        {
+            logging::logMessage(
+                "Failed to update " +
+                std::string(constants::kwdClearNVRAM_CreateLPAR) +
+                " keyword to VPD");
+        }
+
+        return;
+    }
+    logging::logMessage("Invalid type recieved for clear NVRAM from VPD.");
+}
+
+void IbmBiosHandler::saveClearNvramToBios(const std::string& i_clearNvramVal)
+{
+    // Check for the exact length as it is a string and it can have a garbage
+    // value.
+    if (i_clearNvramVal.size() != constants::VALUE_1)
+    {
+        logging::logMessage(
+            "Bad size for clear NVRAM in VPD. Skip writing to BIOS.");
+        return;
+    }
+
+    // 3rd bit is used to store clear NVRAM value.
+    std::string l_valtoUpdate =
+        (i_clearNvramVal.at(0) & constants::VALUE_4) ? "Enabled" : "Disabled";
+
+    types::PendingBIOSAttrs l_pendingBiosAttribute;
+    l_pendingBiosAttribute.push_back(std::make_pair(
+        "pvm_clear_nvram",
+        std::make_tuple(
+            "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
+            l_valtoUpdate)));
+
+    try
+    {
+        dbusUtility::writeDbusProperty(
+            constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
+            constants::biosConfigMgrInterface, "PendingAttributes",
+            l_pendingBiosAttribute);
+    }
+    catch (const std::exception& l_ex)
+    {
+        logging::logMessage(
+            "DBus call to update NVRAM value in pending attribute failed. " +
+            std::string(l_ex.what()));
+    }
+}
+
+void IbmBiosHandler::processClearNvram()
+{
+    // Read required keyword from VPD.
+    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
+        constants::pimServiceName, constants::systemVpdInvPath,
+        constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);
+
+    if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
+    {
+        saveClearNvramToBios(std::to_string(l_pVal->at(0)));
+        return;
+    }
+    logging::logMessage("Invalid type recieved for clear NVRAM from VPD.");
+}
+
+void IbmBiosHandler::saveKeepAndClearToVpd(const std::string& i_KeepAndClearVal)
+{
+    if (i_KeepAndClearVal.empty())
+    {
+        logging::logMessage(
+            "Empty value received for keep and clear from BIOS. Skip updating to VPD.");
+        return;
+    }
+
+    // Read required keyword from DBus as we need to set only a Bit.
+    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
+        constants::pimServiceName, constants::systemVpdInvPath,
+        constants::utilInf, constants::kwdKeepAndClear);
+
+    if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
+    {
+        commonUtility::toLower(const_cast<std::string&>(i_KeepAndClearVal));
+
+        // Check for first bit. Bit set for enabled else disabled.
+        if (((((*l_pVal).at(0) & 0x01) == 0x01) &&
+             (i_KeepAndClearVal.compare("enabled") ==
+              constants::STR_CMP_SUCCESS)) ||
+            ((((*l_pVal).at(0) & 0x01) == 0x00) &&
+             (i_KeepAndClearVal.compare("disabled") ==
+              constants::STR_CMP_SUCCESS)))
+        {
+            // Don't update, values are same.
+            return;
+        }
+
+        types::BinaryVector l_valToUpdateInVpd;
+        if (i_KeepAndClearVal.compare("enabled") == constants::STR_CMP_SUCCESS)
+        {
+            // 1st bit is used to store the value.
+            l_valToUpdateInVpd.emplace_back(
+                (*l_pVal).at(0) | constants::VALUE_1);
+        }
+        else
+        {
+            // 1st bit is used to store the value.
+            l_valToUpdateInVpd.emplace_back(
+                (*l_pVal).at(0) & ~(constants::VALUE_1));
+        }
+
+        if (-1 == m_manager->updateKeyword(
+                      SYSTEM_VPD_FILE_PATH,
+                      types::IpzData("UTIL", constants::kwdKeepAndClear,
+                                     l_valToUpdateInVpd)))
+        {
+            logging::logMessage(
+                "Failed to update " + std::string(constants::kwdKeepAndClear) +
+                " keyword to VPD");
+        }
+
+        return;
+    }
+    logging::logMessage("Invalid type recieved for keep and clear from VPD.");
+}
+
+void IbmBiosHandler::saveKeepAndClearToBios(
+    const std::string& i_KeepAndClearVal)
+{
+    // checking for exact length as it is a string and can have garbage value.
+    if (i_KeepAndClearVal.size() != constants::VALUE_1)
+    {
+        logging::logMessage(
+            "Bad size for keep and clear in VPD. Skip writing to BIOS.");
+        return;
+    }
+
+    // 1st bit is used to store keep and clear value.
+    std::string l_valtoUpdate =
+        (i_KeepAndClearVal.at(0) & constants::VALUE_1) ? "Enabled" : "Disabled";
+
+    types::PendingBIOSAttrs l_pendingBiosAttribute;
+    l_pendingBiosAttribute.push_back(std::make_pair(
+        "pvm_keep_and_clear",
+        std::make_tuple(
+            "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
+            l_valtoUpdate)));
+
+    try
+    {
+        dbusUtility::writeDbusProperty(
+            constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
+            constants::biosConfigMgrInterface, "PendingAttributes",
+            l_pendingBiosAttribute);
+    }
+    catch (const std::exception& l_ex)
+    {
+        logging::logMessage(
+            "DBus call to update keep and clear value in pending attribute failed. " +
+            std::string(l_ex.what()));
+    }
+}
+
+void IbmBiosHandler::processKeepAndClear()
+{
+    // Read required keyword from VPD.
+    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
+        constants::pimServiceName, constants::systemVpdInvPath,
+        constants::utilInf, constants::kwdKeepAndClear);
+
+    if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
+    {
+        saveKeepAndClearToBios(std::to_string(l_pVal->at(0)));
+        return;
+    }
+    logging::logMessage("Invalid type recieved for keep and clear from VPD.");
+}
+} // namespace vpd
diff --git a/vpd-manager/src/ddimm_parser.cpp b/vpd-manager/src/ddimm_parser.cpp
new file mode 100644
index 0000000..0da4ddc
--- /dev/null
+++ b/vpd-manager/src/ddimm_parser.cpp
@@ -0,0 +1,393 @@
+#include "ddimm_parser.hpp"
+
+#include "constants.hpp"
+#include "exceptions.hpp"
+
+#include <cmath>
+#include <cstdint>
+#include <iostream>
+#include <numeric>
+#include <string>
+
+namespace vpd
+{
+
+static constexpr auto SDRAM_DENSITY_PER_DIE_24GB = 24;
+static constexpr auto SDRAM_DENSITY_PER_DIE_32GB = 32;
+static constexpr auto SDRAM_DENSITY_PER_DIE_48GB = 48;
+static constexpr auto SDRAM_DENSITY_PER_DIE_64GB = 64;
+static constexpr auto SDRAM_DENSITY_PER_DIE_UNDEFINED = 0;
+
+static constexpr auto PRIMARY_BUS_WIDTH_32_BITS = 32;
+static constexpr auto PRIMARY_BUS_WIDTH_UNUSED = 0;
+
+bool DdimmVpdParser::checkValidValue(uint8_t i_ByteValue, uint8_t i_shift,
+                                     uint8_t i_minValue, uint8_t i_maxValue)
+{
+    bool l_isValid = true;
+    uint8_t l_ByteValue = i_ByteValue >> i_shift;
+    if ((l_ByteValue > i_maxValue) || (l_ByteValue < i_minValue))
+    {
+        logging::logMessage(
+            "Non valid Value encountered value[" + std::to_string(l_ByteValue) +
+            "] range [" + std::to_string(i_minValue) + ".." +
+            std::to_string(i_maxValue) + "] found ");
+        return false;
+    }
+    return l_isValid;
+}
+
+uint8_t DdimmVpdParser::getDdr5DensityPerDie(uint8_t i_ByteValue)
+{
+    uint8_t l_densityPerDie = SDRAM_DENSITY_PER_DIE_UNDEFINED;
+    if (i_ByteValue < constants::VALUE_5)
+    {
+        l_densityPerDie = i_ByteValue * constants::VALUE_4;
+    }
+    else
+    {
+        switch (i_ByteValue)
+        {
+            case constants::VALUE_5:
+                l_densityPerDie = SDRAM_DENSITY_PER_DIE_24GB;
+                break;
+
+            case constants::VALUE_6:
+                l_densityPerDie = SDRAM_DENSITY_PER_DIE_32GB;
+                break;
+
+            case constants::VALUE_7:
+                l_densityPerDie = SDRAM_DENSITY_PER_DIE_48GB;
+                break;
+
+            case constants::VALUE_8:
+                l_densityPerDie = SDRAM_DENSITY_PER_DIE_64GB;
+                break;
+
+            default:
+                logging::logMessage(
+                    "default value encountered for density per die");
+                l_densityPerDie = SDRAM_DENSITY_PER_DIE_UNDEFINED;
+                break;
+        }
+    }
+    return l_densityPerDie;
+}
+
+uint8_t DdimmVpdParser::getDdr5DiePerPackage(uint8_t i_ByteValue)
+{
+    uint8_t l_DiePerPackage = constants::VALUE_0;
+    if (i_ByteValue < constants::VALUE_2)
+    {
+        l_DiePerPackage = i_ByteValue + constants::VALUE_1;
+    }
+    else
+    {
+        l_DiePerPackage =
+            pow(constants::VALUE_2, (i_ByteValue - constants::VALUE_1));
+    }
+    return l_DiePerPackage;
+}
+
+size_t DdimmVpdParser::getDdr5BasedDdimmSize(
+    types::BinaryVector::const_iterator i_iterator)
+{
+    size_t l_dimmSize = 0;
+
+    do
+    {
+        if (!checkValidValue(i_iterator[constants::SPD_BYTE_235] &
+                                 constants::MASK_BYTE_BITS_01,
+                             constants::SHIFT_BITS_0, constants::VALUE_1,
+                             constants::VALUE_3) ||
+            !checkValidValue(i_iterator[constants::SPD_BYTE_235] &
+                                 constants::MASK_BYTE_BITS_345,
+                             constants::SHIFT_BITS_3, constants::VALUE_1,
+                             constants::VALUE_3))
+        {
+            logging::logMessage(
+                "Capacity calculation failed for channels per DIMM. DDIMM Byte "
+                "235 value [" +
+                std::to_string(i_iterator[constants::SPD_BYTE_235]) + "]");
+            break;
+        }
+        uint8_t l_channelsPerPhy =
+            (((i_iterator[constants::SPD_BYTE_235] &
+               constants::MASK_BYTE_BITS_01)
+                  ? constants::VALUE_1
+                  : constants::VALUE_0) +
+             ((i_iterator[constants::SPD_BYTE_235] &
+               constants::MASK_BYTE_BITS_345)
+                  ? constants::VALUE_1
+                  : constants::VALUE_0));
+
+        uint8_t l_channelsPerDdimm =
+            (((i_iterator[constants::SPD_BYTE_235] &
+               constants::MASK_BYTE_BIT_6) >>
+              constants::VALUE_6) +
+             ((i_iterator[constants::SPD_BYTE_235] &
+               constants::MASK_BYTE_BIT_7) >>
+              constants::VALUE_7)) *
+            l_channelsPerPhy;
+
+        if (!checkValidValue(i_iterator[constants::SPD_BYTE_235] &
+                                 constants::MASK_BYTE_BITS_012,
+                             constants::SHIFT_BITS_0, constants::VALUE_1,
+                             constants::VALUE_3))
+        {
+            logging::logMessage(
+                "Capacity calculation failed for bus width per channel. DDIMM "
+                "Byte 235 value [" +
+                std::to_string(i_iterator[constants::SPD_BYTE_235]) + "]");
+            break;
+        }
+        uint8_t l_busWidthPerChannel =
+            (i_iterator[constants::SPD_BYTE_235] &
+             constants::MASK_BYTE_BITS_012)
+                ? PRIMARY_BUS_WIDTH_32_BITS
+                : PRIMARY_BUS_WIDTH_UNUSED;
+
+        if (!checkValidValue(i_iterator[constants::SPD_BYTE_4] &
+                                 constants::MASK_BYTE_BITS_567,
+                             constants::SHIFT_BITS_5, constants::VALUE_0,
+                             constants::VALUE_5))
+        {
+            logging::logMessage(
+                "Capacity calculation failed for die per package. DDIMM Byte 4 "
+                "value [" +
+                std::to_string(i_iterator[constants::SPD_BYTE_4]) + "]");
+            break;
+        }
+        uint8_t l_diePerPackage = getDdr5DiePerPackage(
+            (i_iterator[constants::SPD_BYTE_4] &
+             constants::MASK_BYTE_BITS_567) >>
+            constants::VALUE_5);
+
+        if (!checkValidValue(i_iterator[constants::SPD_BYTE_4] &
+                                 constants::MASK_BYTE_BITS_01234,
+                             constants::SHIFT_BITS_0, constants::VALUE_1,
+                             constants::VALUE_8))
+        {
+            logging::logMessage(
+                "Capacity calculation failed for SDRAM Density per Die. DDIMM "
+                "Byte 4 value [" +
+                std::to_string(i_iterator[constants::SPD_BYTE_4]) + "]");
+            break;
+        }
+        uint8_t l_densityPerDie = getDdr5DensityPerDie(
+            i_iterator[constants::SPD_BYTE_4] &
+            constants::MASK_BYTE_BITS_01234);
+
+        uint8_t l_ranksPerChannel = 0;
+
+        if (((i_iterator[constants::SPD_BYTE_234] &
+              constants::MASK_BYTE_BIT_7) >>
+             constants::VALUE_7))
+        {
+            l_ranksPerChannel = ((i_iterator[constants::SPD_BYTE_234] &
+                                  constants::MASK_BYTE_BITS_345) >>
+                                 constants::VALUE_3) +
+                                constants::VALUE_1;
+        }
+        else if (((i_iterator[constants::SPD_BYTE_235] &
+                   constants::MASK_BYTE_BIT_6) >>
+                  constants::VALUE_6))
+        {
+            l_ranksPerChannel = (i_iterator[constants::SPD_BYTE_234] &
+                                 constants::MASK_BYTE_BITS_012) +
+                                constants::VALUE_1;
+        }
+
+        if (!checkValidValue(i_iterator[constants::SPD_BYTE_6] &
+                                 constants::MASK_BYTE_BITS_567,
+                             constants::SHIFT_BITS_5, constants::VALUE_0,
+                             constants::VALUE_3))
+        {
+            logging::logMessage(
+                "Capacity calculation failed for dram width DDIMM Byte 6 value "
+                "[" +
+                std::to_string(i_iterator[constants::SPD_BYTE_6]) + "]");
+            break;
+        }
+        uint8_t l_dramWidth =
+            constants::VALUE_4 *
+            (constants::VALUE_1 << ((i_iterator[constants::SPD_BYTE_6] &
+                                     constants::MASK_BYTE_BITS_567) >>
+                                    constants::VALUE_5));
+
+        // DDIMM size is calculated in GB
+        l_dimmSize = (l_channelsPerDdimm * l_busWidthPerChannel *
+                      l_diePerPackage * l_densityPerDie * l_ranksPerChannel) /
+                     (8 * l_dramWidth);
+
+    } while (false);
+
+    return constants::CONVERT_GB_TO_KB * l_dimmSize;
+}
+
+size_t DdimmVpdParser::getDdr4BasedDdimmSize(
+    types::BinaryVector::const_iterator i_iterator)
+{
+    size_t l_dimmSize = 0;
+    try
+    {
+        uint8_t l_tmpValue = 0;
+
+        // Calculate SDRAM capacity
+        l_tmpValue = i_iterator[constants::SPD_BYTE_4] &
+                     constants::JEDEC_SDRAM_CAP_MASK;
+
+        /* Make sure the bits are not Reserved */
+        if (l_tmpValue > constants::JEDEC_SDRAMCAP_RESERVED)
+        {
+            throw std::runtime_error(
+                "Bad data in VPD byte 4. Can't calculate SDRAM capacity and so "
+                "dimm size.\n ");
+        }
+
+        uint16_t l_sdramCapacity = 1;
+        l_sdramCapacity = (l_sdramCapacity << l_tmpValue) *
+                          constants::JEDEC_SDRAMCAP_MULTIPLIER;
+
+        /* Calculate Primary bus width */
+        l_tmpValue = i_iterator[constants::SPD_BYTE_13] &
+                     constants::JEDEC_PRI_BUS_WIDTH_MASK;
+
+        if (l_tmpValue > constants::JEDEC_RESERVED_BITS)
+        {
+            throw std::runtime_error(
+                "Bad data in VPD byte 13. Can't calculate primary bus width "
+                "and so dimm size.");
+        }
+
+        uint8_t l_primaryBusWid = 1;
+        l_primaryBusWid = (l_primaryBusWid << l_tmpValue) *
+                          constants::JEDEC_PRI_BUS_WIDTH_MULTIPLIER;
+
+        /* Calculate SDRAM width */
+        l_tmpValue = i_iterator[constants::SPD_BYTE_12] &
+                     constants::JEDEC_SDRAM_WIDTH_MASK;
+
+        if (l_tmpValue > constants::JEDEC_RESERVED_BITS)
+        {
+            throw std::runtime_error(
+                "Bad data in VPD byte 12. Can't calculate SDRAM width and so "
+                "dimm size.");
+        }
+
+        uint8_t l_sdramWidth = 1;
+        l_sdramWidth = (l_sdramWidth << l_tmpValue) *
+                       constants::JEDEC_SDRAM_WIDTH_MULTIPLIER;
+
+        /* Calculate Number of ranks */
+        l_tmpValue = i_iterator[constants::SPD_BYTE_12] &
+                     constants::JEDEC_NUM_RANKS_MASK;
+        l_tmpValue >>= constants::JEDEC_RESERVED_BITS;
+
+        if (l_tmpValue > constants::JEDEC_RESERVED_BITS)
+        {
+            throw std::runtime_error(
+                "Bad data in VPD byte 12, can't calculate number of ranks. Invalid data found.");
+        }
+
+        uint8_t l_logicalRanksPerDimm = l_tmpValue + 1;
+
+        // Determine is single load stack (3DS) or not
+        l_tmpValue = i_iterator[constants::SPD_BYTE_6] &
+                     constants::JEDEC_SIGNAL_LOADING_MASK;
+
+        if (l_tmpValue == constants::JEDEC_SINGLE_LOAD_STACK)
+        {
+            // Fetch die count
+            l_tmpValue = i_iterator[constants::SPD_BYTE_6] &
+                         constants::JEDEC_DIE_COUNT_MASK;
+            l_tmpValue >>= constants::JEDEC_DIE_COUNT_RIGHT_SHIFT;
+
+            uint8_t l_dieCount = l_tmpValue + 1;
+            l_logicalRanksPerDimm *= l_dieCount;
+        }
+
+        l_dimmSize =
+            (l_sdramCapacity / constants::JEDEC_PRI_BUS_WIDTH_MULTIPLIER) *
+            (l_primaryBusWid / l_sdramWidth) * l_logicalRanksPerDimm;
+
+        // Converting dimm size from MB to KB
+        l_dimmSize *= constants::CONVERT_MB_TO_KB;
+    }
+    catch (const std::exception& l_ex)
+    {
+        // TODO:: Need an error log here
+        logging::logMessage("DDR4 DDIMM calculation is failed, reason: " +
+                            std::string(l_ex.what()));
+    }
+    return l_dimmSize;
+}
+
+size_t
+    DdimmVpdParser::getDdimmSize(types::BinaryVector::const_iterator i_iterator)
+{
+    size_t l_dimmSize = 0;
+    if (i_iterator[constants::SPD_BYTE_2] == constants::SPD_DRAM_TYPE_DDR5)
+    {
+        l_dimmSize = getDdr5BasedDdimmSize(i_iterator);
+    }
+    else if (i_iterator[constants::SPD_BYTE_2] == constants::SPD_DRAM_TYPE_DDR4)
+    {
+        l_dimmSize = getDdr4BasedDdimmSize(i_iterator);
+    }
+    else
+    {
+        logging::logMessage(
+            "Error: DDIMM is neither DDR4 nor DDR5. DDIMM Byte 2 value [" +
+            std::to_string(i_iterator[constants::SPD_BYTE_2]) + "]");
+    }
+    return l_dimmSize;
+}
+
+void DdimmVpdParser::readKeywords(
+    types::BinaryVector::const_iterator i_iterator)
+{
+    // collect DDIMM size value
+    auto l_dimmSize = getDdimmSize(i_iterator);
+    if (!l_dimmSize)
+    {
+        throw(DataException("Error: Calculated dimm size is 0."));
+    }
+
+    m_parsedVpdMap.emplace("MemorySizeInKB", l_dimmSize);
+    // point the i_iterator to DIMM data and skip "11S"
+    advance(i_iterator, constants::DDIMM_11S_BARCODE_START +
+                            constants::DDIMM_11S_FORMAT_LEN);
+    types::BinaryVector l_partNumber(i_iterator,
+                                     i_iterator + constants::PART_NUM_LEN);
+
+    advance(i_iterator, constants::PART_NUM_LEN);
+    types::BinaryVector l_serialNumber(i_iterator,
+                                       i_iterator + constants::SERIAL_NUM_LEN);
+
+    advance(i_iterator, constants::SERIAL_NUM_LEN);
+    types::BinaryVector l_ccin(i_iterator, i_iterator + constants::CCIN_LEN);
+
+    m_parsedVpdMap.emplace("FN", l_partNumber);
+    m_parsedVpdMap.emplace("PN", move(l_partNumber));
+    m_parsedVpdMap.emplace("SN", move(l_serialNumber));
+    m_parsedVpdMap.emplace("CC", move(l_ccin));
+}
+
+types::VPDMapVariant DdimmVpdParser::parse()
+{
+    try
+    {
+        // Read the data and return the map
+        auto l_iterator = m_vpdVector.cbegin();
+        readKeywords(l_iterator);
+        return m_parsedVpdMap;
+    }
+    catch (const std::exception& exp)
+    {
+        logging::logMessage(exp.what());
+        throw exp;
+    }
+}
+
+} // namespace vpd
diff --git a/vpd-manager/src/event_logger.cpp b/vpd-manager/src/event_logger.cpp
new file mode 100644
index 0000000..11861d1
--- /dev/null
+++ b/vpd-manager/src/event_logger.cpp
@@ -0,0 +1,294 @@
+#include "event_logger.hpp"
+
+#include "logger.hpp"
+
+#include <systemd/sd-bus.h>
+
+namespace vpd
+{
+const std::unordered_map<types::SeverityType, std::string>
+    EventLogger::m_severityMap = {
+        {types::SeverityType::Notice,
+         "xyz.openbmc_project.Logging.Entry.Level.Notice"},
+        {types::SeverityType::Informational,
+         "xyz.openbmc_project.Logging.Entry.Level.Informational"},
+        {types::SeverityType::Debug,
+         "xyz.openbmc_project.Logging.Entry.Level.Debug"},
+        {types::SeverityType::Warning,
+         "xyz.openbmc_project.Logging.Entry.Level.Warning"},
+        {types::SeverityType::Critical,
+         "xyz.openbmc_project.Logging.Entry.Level.Critical"},
+        {types::SeverityType::Emergency,
+         "xyz.openbmc_project.Logging.Entry.Level.Emergency"},
+        {types::SeverityType::Alert,
+         "xyz.openbmc_project.Logging.Entry.Level.Alert"},
+        {types::SeverityType::Error,
+         "xyz.openbmc_project.Logging.Entry.Level.Error"}};
+
+const std::unordered_map<types::ErrorType, std::string>
+    EventLogger::m_errorMsgMap = {
+        {types::ErrorType::DefaultValue, "com.ibm.VPD.Error.DefaultValue"},
+        {types::ErrorType::InvalidVpdMessage, "com.ibm.VPD.Error.InvalidVPD"},
+        {types::ErrorType::VpdMismatch, "com.ibm.VPD.Error.Mismatch"},
+        {types::ErrorType::InvalidEeprom,
+         "com.ibm.VPD.Error.InvalidEepromPath"},
+        {types::ErrorType::EccCheckFailed, "com.ibm.VPD.Error.EccCheckFailed"},
+        {types::ErrorType::JsonFailure, "com.ibm.VPD.Error.InvalidJson"},
+        {types::ErrorType::DbusFailure, "com.ibm.VPD.Error.DbusFailure"},
+        {types::ErrorType::InvalidSystem,
+         "com.ibm.VPD.Error.UnknownSystemType"},
+        {types::ErrorType::EssentialFru,
+         "com.ibm.VPD.Error.RequiredFRUMissing"},
+        {types::ErrorType::GpioError, "com.ibm.VPD.Error.GPIOError"}};
+
+const std::unordered_map<types::CalloutPriority, std::string>
+    EventLogger::m_priorityMap = {
+        {types::CalloutPriority::High, "H"},
+        {types::CalloutPriority::Medium, "M"},
+        {types::CalloutPriority::MediumGroupA, "A"},
+        {types::CalloutPriority::MediumGroupB, "B"},
+        {types::CalloutPriority::MediumGroupC, "C"},
+        {types::CalloutPriority::Low, "L"}};
+
+void EventLogger::createAsyncPelWithInventoryCallout(
+    const types::ErrorType& i_errorType, const types::SeverityType& i_severity,
+    const std::vector<types::InventoryCalloutData>& i_callouts,
+    const std::string& i_fileName, const std::string& i_funcName,
+    const uint8_t i_internalRc, const std::string& i_description,
+    const std::optional<std::string> i_userData1,
+    const std::optional<std::string> i_userData2,
+    const std::optional<std::string> i_symFru,
+    const std::optional<std::string> i_procedure)
+{
+    (void)i_symFru;
+    (void)i_procedure;
+
+    try
+    {
+        if (i_callouts.empty())
+        {
+            logging::logMessage("Callout information is missing to create PEL");
+            // TODO: Revisit this instead of simpley returning.
+            return;
+        }
+
+        if (m_errorMsgMap.find(i_errorType) == m_errorMsgMap.end())
+        {
+            throw std::runtime_error(
+                "Error type not found in the error message map to create PEL");
+            // TODO: Need to handle, instead of throwing exception. Create
+            // default message in message_registry.json.
+        }
+
+        const std::string& l_message = m_errorMsgMap.at(i_errorType);
+
+        const std::string& l_severity =
+            (m_severityMap.find(i_severity) != m_severityMap.end()
+                 ? m_severityMap.at(i_severity)
+                 : m_severityMap.at(types::SeverityType::Informational));
+
+        std::string l_description =
+            (!i_description.empty() ? i_description : "VPD generic error");
+
+        std::string l_userData1 = (i_userData1) ? (*i_userData1) : "";
+
+        std::string l_userData2 = (i_userData2) ? (*i_userData2) : "";
+
+        const types::InventoryCalloutData& l_invCallout = i_callouts[0];
+        // TODO: Need to handle multiple inventory path callout's, when multiple
+        // callout's is supported by "Logging" service.
+
+        const types::CalloutPriority& l_priorityEnum = get<1>(l_invCallout);
+
+        const std::string& l_priority =
+            (m_priorityMap.find(l_priorityEnum) != m_priorityMap.end()
+                 ? m_priorityMap.at(l_priorityEnum)
+                 : m_priorityMap.at(types::CalloutPriority::Low));
+
+        sd_bus* l_sdBus = nullptr;
+        sd_bus_default(&l_sdBus);
+
+        const uint8_t l_additionalDataCount = 8;
+        auto l_rc = sd_bus_call_method_async(
+            l_sdBus, NULL, constants::eventLoggingServiceName,
+            constants::eventLoggingObjectPath, constants::eventLoggingInterface,
+            "Create", NULL, NULL, "ssa{ss}", l_message.c_str(),
+            l_severity.c_str(), l_additionalDataCount, "FileName",
+            i_fileName.c_str(), "FunctionName", i_funcName.c_str(),
+            "InternalRc", std::to_string(i_internalRc).c_str(), "DESCRIPTION",
+            l_description.c_str(), "UserData1", l_userData1.c_str(),
+            "UserData2", l_userData2.c_str(), "CALLOUT_INVENTORY_PATH",
+            get<0>(l_invCallout).c_str(), "CALLOUT_PRIORITY",
+            l_priority.c_str());
+
+        if (l_rc < 0)
+        {
+            logging::logMessage(
+                "Error calling sd_bus_call_method_async, Message = " +
+                std::string(strerror(-l_rc)));
+        }
+    }
+    catch (const std::exception& l_ex)
+    {
+        logging::logMessage(
+            "Create PEL failed with error: " + std::string(l_ex.what()));
+    }
+}
+
+void EventLogger::createAsyncPelWithI2cDeviceCallout(
+    const types::ErrorType i_errorType, const types::SeverityType i_severity,
+    const std::vector<types::DeviceCalloutData>& i_callouts,
+    const std::string& i_fileName, const std::string& i_funcName,
+    const uint8_t i_internalRc,
+    const std::optional<std::pair<std::string, std::string>> i_userData1,
+    const std::optional<std::pair<std::string, std::string>> i_userData2)
+{
+    // TODO, implementation needs to be added.
+    (void)i_errorType;
+    (void)i_severity;
+    (void)i_callouts;
+    (void)i_fileName;
+    (void)i_funcName;
+    (void)i_internalRc;
+    (void)i_userData1;
+    (void)i_userData2;
+}
+
+void EventLogger::createAsyncPelWithI2cBusCallout(
+    const types::ErrorType i_errorType, const types::SeverityType i_severity,
+    const std::vector<types::I2cBusCalloutData>& i_callouts,
+    const std::string& i_fileName, const std::string& i_funcName,
+    const uint8_t i_internalRc,
+    const std::optional<std::pair<std::string, std::string>> i_userData1,
+    const std::optional<std::pair<std::string, std::string>> i_userData2)
+{
+    // TODO, implementation needs to be added.
+    (void)i_errorType;
+    (void)i_severity;
+    (void)i_callouts;
+    (void)i_fileName;
+    (void)i_funcName;
+    (void)i_internalRc;
+    (void)i_userData1;
+    (void)i_userData2;
+}
+
+void EventLogger::createAsyncPel(
+    const types::ErrorType& i_errorType, const types::SeverityType& i_severity,
+    const std::string& i_fileName, const std::string& i_funcName,
+    const uint8_t i_internalRc, const std::string& i_description,
+    const std::optional<std::string> i_userData1,
+    const std::optional<std::string> i_userData2,
+    const std::optional<std::string> i_symFru,
+    const std::optional<std::string> i_procedure)
+{
+    (void)i_symFru;
+    (void)i_procedure;
+    try
+    {
+        if (m_errorMsgMap.find(i_errorType) == m_errorMsgMap.end())
+        {
+            throw std::runtime_error("Unsupported error type received");
+            // TODO: Need to handle, instead of throwing an exception.
+        }
+
+        const std::string& l_message = m_errorMsgMap.at(i_errorType);
+
+        const std::string& l_severity =
+            (m_severityMap.find(i_severity) != m_severityMap.end()
+                 ? m_severityMap.at(i_severity)
+                 : m_severityMap.at(types::SeverityType::Informational));
+
+        const std::string l_description =
+            ((!i_description.empty() ? i_description : "VPD generic error"));
+
+        const std::string l_userData1 = ((i_userData1) ? (*i_userData1) : "");
+
+        const std::string l_userData2 = ((i_userData2) ? (*i_userData2) : "");
+
+        sd_bus* l_sdBus = nullptr;
+        sd_bus_default(&l_sdBus);
+
+        // VALUE_6 represents the additional data pair count passing to create
+        // PEL. If there any change in additional data, we need to pass the
+        // correct number.
+        auto l_rc = sd_bus_call_method_async(
+            l_sdBus, NULL, constants::eventLoggingServiceName,
+            constants::eventLoggingObjectPath, constants::eventLoggingInterface,
+            "Create", NULL, NULL, "ssa{ss}", l_message.c_str(),
+            l_severity.c_str(), constants::VALUE_6, "FileName",
+            i_fileName.c_str(), "FunctionName", i_funcName.c_str(),
+            "InternalRc", std::to_string(i_internalRc).c_str(), "DESCRIPTION",
+            l_description.c_str(), "UserData1", l_userData1.c_str(),
+            "UserData2", l_userData2.c_str());
+
+        if (l_rc < 0)
+        {
+            logging::logMessage(
+                "Error calling sd_bus_call_method_async, Message = " +
+                std::string(strerror(-l_rc)));
+        }
+    }
+    catch (const sdbusplus::exception::SdBusError& l_ex)
+    {
+        logging::logMessage("Async PEL creation failed with an error: " +
+                            std::string(l_ex.what()));
+    }
+}
+
+void EventLogger::createSyncPel(
+    const types::ErrorType& i_errorType, const types::SeverityType& i_severity,
+    const std::string& i_fileName, const std::string& i_funcName,
+    const uint8_t i_internalRc, const std::string& i_description,
+    const std::optional<std::string> i_userData1,
+    const std::optional<std::string> i_userData2,
+    const std::optional<std::string> i_symFru,
+    const std::optional<std::string> i_procedure)
+{
+    (void)i_symFru;
+    (void)i_procedure;
+    try
+    {
+        if (m_errorMsgMap.find(i_errorType) == m_errorMsgMap.end())
+        {
+            throw std::runtime_error("Unsupported error type received");
+            // TODO: Need to handle, instead of throwing an exception.
+        }
+
+        const std::string& l_message = m_errorMsgMap.at(i_errorType);
+
+        const std::string& l_severity =
+            (m_severityMap.find(i_severity) != m_severityMap.end()
+                 ? m_severityMap.at(i_severity)
+                 : m_severityMap.at(types::SeverityType::Informational));
+
+        const std::string l_description =
+            ((!i_description.empty() ? i_description : "VPD generic error"));
+
+        const std::string l_userData1 = ((i_userData1) ? (*i_userData1) : "");
+
+        const std::string l_userData2 = ((i_userData2) ? (*i_userData2) : "");
+
+        std::map<std::string, std::string> l_additionalData{
+            {"FileName", i_fileName},
+            {"FunctionName", i_funcName},
+            {"DESCRIPTION", l_description},
+            {"InteranlRc", std::to_string(i_internalRc)},
+            {"UserData1", l_userData1.c_str()},
+            {"UserData2", l_userData2.c_str()}};
+
+        auto l_bus = sdbusplus::bus::new_default();
+        auto l_method =
+            l_bus.new_method_call(constants::eventLoggingServiceName,
+                                  constants::eventLoggingObjectPath,
+                                  constants::eventLoggingInterface, "Create");
+        l_method.append(l_message, l_severity, l_additionalData);
+        l_bus.call(l_method);
+    }
+    catch (const sdbusplus::exception::SdBusError& l_ex)
+    {
+        logging::logMessage("Sync PEL creation failed with an error: " +
+                            std::string(l_ex.what()));
+    }
+}
+} // namespace vpd
diff --git a/vpd-manager/src/gpio_monitor.cpp b/vpd-manager/src/gpio_monitor.cpp
new file mode 100644
index 0000000..521037c
--- /dev/null
+++ b/vpd-manager/src/gpio_monitor.cpp
@@ -0,0 +1,131 @@
+#include "gpio_monitor.hpp"
+
+#include "constants.hpp"
+#include "logger.hpp"
+#include "types.hpp"
+#include "utility/dbus_utility.hpp"
+#include "utility/json_utility.hpp"
+
+#include <boost/asio.hpp>
+#include <boost/bind/bind.hpp>
+#include <gpiod.hpp>
+
+namespace vpd
+{
+void GpioEventHandler::handleChangeInGpioPin(const bool& i_isFruPresent)
+{
+    try
+    {
+        if (i_isFruPresent)
+        {
+            types::VPDMapVariant l_parsedVpd =
+                m_worker->parseVpdFile(m_fruPath);
+
+            if (std::holds_alternative<std::monostate>(l_parsedVpd))
+            {
+                throw std::runtime_error(
+                    "VPD parsing failed for " + std::string(m_fruPath));
+            }
+
+            types::ObjectMap l_dbusObjectMap;
+            m_worker->populateDbus(l_parsedVpd, l_dbusObjectMap, m_fruPath);
+
+            if (l_dbusObjectMap.empty())
+            {
+                throw std::runtime_error("Failed to create D-bus object map.");
+            }
+
+            if (!dbusUtility::callPIM(move(l_dbusObjectMap)))
+            {
+                throw std::runtime_error("call PIM failed");
+            }
+        }
+        else
+        {
+            // TODO -- Add implementation to Delete FRU if FRU is not present.
+        }
+    }
+    catch (std::exception& l_ex)
+    {
+        logging::logMessage(std::string(l_ex.what()));
+    }
+}
+
+void GpioEventHandler::handleTimerExpiry(
+    const boost::system::error_code& i_errorCode,
+    const std::shared_ptr<boost::asio::steady_timer>& i_timerObj)
+{
+    if (i_errorCode == boost::asio::error::operation_aborted)
+    {
+        logging::logMessage("Timer aborted for GPIO pin");
+        return;
+    }
+
+    if (i_errorCode)
+    {
+        logging::logMessage("Timer wait failed for gpio pin" +
+                            std::string(i_errorCode.message()));
+        return;
+    }
+
+    bool l_currentPresencePinValue = jsonUtility::processGpioPresenceTag(
+        m_worker->getSysCfgJsonObj(), m_fruPath, "pollingRequired",
+        "hotPlugging");
+
+    if (m_prevPresencePinValue != l_currentPresencePinValue)
+    {
+        m_prevPresencePinValue = l_currentPresencePinValue;
+        handleChangeInGpioPin(l_currentPresencePinValue);
+    }
+
+    i_timerObj->expires_at(std::chrono::steady_clock::now() +
+                           std::chrono::seconds(constants::VALUE_5));
+    i_timerObj->async_wait(
+        boost::bind(&GpioEventHandler::handleTimerExpiry, this,
+                    boost::asio::placeholders::error, i_timerObj));
+}
+
+void GpioEventHandler::setEventHandlerForGpioPresence(
+    const std::shared_ptr<boost::asio::io_context>& i_ioContext)
+{
+    m_prevPresencePinValue = jsonUtility::processGpioPresenceTag(
+        m_worker->getSysCfgJsonObj(), m_fruPath, "pollingRequired",
+        "hotPlugging");
+
+    static std::vector<std::shared_ptr<boost::asio::steady_timer>> l_timers;
+
+    auto l_timerObj = make_shared<boost::asio::steady_timer>(
+        *i_ioContext, std::chrono::seconds(constants::VALUE_5));
+
+    l_timerObj->async_wait(
+        boost::bind(&GpioEventHandler::handleTimerExpiry, this,
+                    boost::asio::placeholders::error, l_timerObj));
+
+    l_timers.push_back(l_timerObj);
+}
+
+void GpioMonitor::initHandlerForGpio(
+    const std::shared_ptr<boost::asio::io_context>& i_ioContext,
+    const std::shared_ptr<Worker>& i_worker)
+{
+    try
+    {
+        std::vector<std::string> l_gpioPollingRequiredFrusList =
+            jsonUtility::getListOfGpioPollingFrus(m_sysCfgJsonObj);
+
+        for (const auto& l_fruPath : l_gpioPollingRequiredFrusList)
+        {
+            std::shared_ptr<GpioEventHandler> l_gpioEventHandlerObj =
+                std::make_shared<GpioEventHandler>(l_fruPath, i_worker,
+                                                   i_ioContext);
+
+            m_gpioEventHandlerObjects.push_back(l_gpioEventHandlerObj);
+        }
+    }
+    catch (std::exception& l_ex)
+    {
+        // TODO log PEL for exception.
+        logging::logMessage(l_ex.what());
+    }
+}
+} // namespace vpd
diff --git a/vpd-manager/src/ipz_parser.cpp b/vpd-manager/src/ipz_parser.cpp
new file mode 100644
index 0000000..4300e12
--- /dev/null
+++ b/vpd-manager/src/ipz_parser.cpp
@@ -0,0 +1,842 @@
+#include "config.h"
+
+#include "ipz_parser.hpp"
+
+#include "vpdecc/vpdecc.h"
+
+#include "constants.hpp"
+#include "exceptions.hpp"
+
+#include <nlohmann/json.hpp>
+
+#include <typeindex>
+
+namespace vpd
+{
+
+// Offset of different entries in VPD data.
+enum Offset
+{
+    VHDR = 17,
+    VHDR_TOC_ENTRY = 29,
+    VTOC_PTR = 35,
+    VTOC_REC_LEN = 37,
+    VTOC_ECC_OFF = 39,
+    VTOC_ECC_LEN = 41,
+    VTOC_DATA = 13,
+    VHDR_ECC = 0,
+    VHDR_RECORD = 11
+};
+
+// Length of some specific entries w.r.t VPD data.
+enum Length
+{
+    RECORD_NAME = 4,
+    KW_NAME = 2,
+    RECORD_OFFSET = 2,
+    RECORD_MIN = 44,
+    RECORD_LENGTH = 2,
+    RECORD_ECC_OFFSET = 2,
+    VHDR_ECC_LENGTH = 11,
+    VHDR_RECORD_LENGTH = 44,
+    RECORD_TYPE = 2,
+    SKIP_A_RECORD_IN_PT = 14,
+    JUMP_TO_RECORD_NAME = 6
+}; // enum Length
+
+/**
+ * @brief API to read 2 bytes LE data.
+ *
+ * @param[in] iterator - iterator to VPD vector.
+ * @return read bytes.
+ */
+static uint16_t readUInt16LE(types::BinaryVector::const_iterator iterator)
+{
+    uint16_t lowByte = *iterator;
+    uint16_t highByte = *(iterator + 1);
+    lowByte |= (highByte << 8);
+    return lowByte;
+}
+
+bool IpzVpdParser::vhdrEccCheck()
+{
+    auto vpdPtr = m_vpdVector.cbegin();
+
+    auto l_status = vpdecc_check_data(
+        const_cast<uint8_t*>(&vpdPtr[Offset::VHDR_RECORD]),
+        Length::VHDR_RECORD_LENGTH,
+        const_cast<uint8_t*>(&vpdPtr[Offset::VHDR_ECC]),
+        Length::VHDR_ECC_LENGTH);
+    if (l_status == VPD_ECC_CORRECTABLE_DATA)
+    {
+        try
+        {
+            if (m_vpdFileStream.is_open())
+            {
+                m_vpdFileStream.seekp(m_vpdStartOffset + Offset::VHDR_RECORD,
+                                      std::ios::beg);
+                m_vpdFileStream.write(reinterpret_cast<const char*>(
+                                          &m_vpdVector[Offset::VHDR_RECORD]),
+                                      Length::VHDR_RECORD_LENGTH);
+            }
+            else
+            {
+                logging::logMessage("File not open");
+                return false;
+            }
+        }
+        catch (const std::fstream::failure& e)
+        {
+            logging::logMessage(
+                "Error while operating on file with exception: " +
+                std::string(e.what()));
+            return false;
+        }
+    }
+    else if (l_status != VPD_ECC_OK)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool IpzVpdParser::vtocEccCheck()
+{
+    auto vpdPtr = m_vpdVector.cbegin();
+
+    std::advance(vpdPtr, Offset::VTOC_PTR);
+
+    // The offset to VTOC could be 1 or 2 bytes long
+    auto vtocOffset = readUInt16LE(vpdPtr);
+
+    // Get the VTOC Length
+    std::advance(vpdPtr, sizeof(types::RecordOffset));
+    auto vtocLength = readUInt16LE(vpdPtr);
+
+    // Get the ECC Offset
+    std::advance(vpdPtr, sizeof(types::RecordLength));
+    auto vtocECCOffset = readUInt16LE(vpdPtr);
+
+    // Get the ECC length
+    std::advance(vpdPtr, sizeof(types::ECCOffset));
+    auto vtocECCLength = readUInt16LE(vpdPtr);
+
+    // Reset pointer to start of the vpd,
+    // so that Offset will point to correct address
+    vpdPtr = m_vpdVector.cbegin();
+    auto l_status = vpdecc_check_data(
+        const_cast<uint8_t*>(&m_vpdVector[vtocOffset]), vtocLength,
+        const_cast<uint8_t*>(&m_vpdVector[vtocECCOffset]), vtocECCLength);
+    if (l_status == VPD_ECC_CORRECTABLE_DATA)
+    {
+        try
+        {
+            if (m_vpdFileStream.is_open())
+            {
+                m_vpdFileStream.seekp(m_vpdStartOffset + vtocOffset,
+                                      std::ios::beg);
+                m_vpdFileStream.write(
+                    reinterpret_cast<const char*>(&m_vpdVector[vtocOffset]),
+                    vtocLength);
+            }
+            else
+            {
+                logging::logMessage("File not open");
+                return false;
+            }
+        }
+        catch (const std::fstream::failure& e)
+        {
+            logging::logMessage(
+                "Error while operating on file with exception " +
+                std::string(e.what()));
+            return false;
+        }
+    }
+    else if (l_status != VPD_ECC_OK)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+bool IpzVpdParser::recordEccCheck(types::BinaryVector::const_iterator iterator)
+{
+    auto recordOffset = readUInt16LE(iterator);
+
+    std::advance(iterator, sizeof(types::RecordOffset));
+    auto recordLength = readUInt16LE(iterator);
+
+    if (recordOffset == 0 || recordLength == 0)
+    {
+        throw(DataException("Invalid record offset or length"));
+    }
+
+    std::advance(iterator, sizeof(types::RecordLength));
+    auto eccOffset = readUInt16LE(iterator);
+
+    std::advance(iterator, sizeof(types::ECCOffset));
+    auto eccLength = readUInt16LE(iterator);
+
+    if (eccLength == 0 || eccOffset == 0)
+    {
+        throw(EccException("Invalid ECC length or offset."));
+    }
+
+    auto vpdPtr = m_vpdVector.cbegin();
+
+    if (vpdecc_check_data(
+            const_cast<uint8_t*>(&vpdPtr[recordOffset]), recordLength,
+            const_cast<uint8_t*>(&vpdPtr[eccOffset]), eccLength) == VPD_ECC_OK)
+    {
+        return true;
+    }
+
+    return false;
+}
+
+void IpzVpdParser::checkHeader(types::BinaryVector::const_iterator itrToVPD)
+{
+    if (m_vpdVector.empty() || (Length::RECORD_MIN > m_vpdVector.size()))
+    {
+        throw(DataException("Malformed VPD"));
+    }
+
+    std::advance(itrToVPD, Offset::VHDR);
+    auto stop = std::next(itrToVPD, Length::RECORD_NAME);
+
+    std::string record(itrToVPD, stop);
+    if ("VHDR" != record)
+    {
+        throw(DataException("VHDR record not found"));
+    }
+
+    if (!vhdrEccCheck())
+    {
+        throw(EccException("ERROR: VHDR ECC check Failed"));
+    }
+}
+
+auto IpzVpdParser::readTOC(types::BinaryVector::const_iterator& itrToVPD)
+{
+    // The offset to VTOC could be 1 or 2 bytes long
+    uint16_t vtocOffset =
+        readUInt16LE((itrToVPD + Offset::VTOC_PTR)); // itrToVPD);
+
+    // Got the offset to VTOC, skip past record header and keyword header
+    // to get to the record name.
+    std::advance(itrToVPD, vtocOffset + sizeof(types::RecordId) +
+                               sizeof(types::RecordSize) +
+                               // Skip past the RT keyword, which contains
+                               // the record name.
+                               Length::KW_NAME + sizeof(types::KwSize));
+
+    std::string record(itrToVPD, std::next(itrToVPD, Length::RECORD_NAME));
+    if ("VTOC" != record)
+    {
+        throw(DataException("VTOC record not found"));
+    }
+
+    if (!vtocEccCheck())
+    {
+        throw(EccException("ERROR: VTOC ECC check Failed"));
+    }
+
+    // VTOC record name is good, now read through the TOC, stored in the PT
+    // PT keyword; vpdBuffer is now pointing at the first character of the
+    // name 'VTOC', jump to PT data.
+    // Skip past record name and KW name, 'PT'
+    std::advance(itrToVPD, Length::RECORD_NAME + Length::KW_NAME);
+
+    // Note size of PT
+    auto ptLen = *itrToVPD;
+
+    // Skip past PT size
+    std::advance(itrToVPD, sizeof(types::KwSize));
+
+    // length of PT keyword
+    return ptLen;
+}
+
+types::RecordOffsetList IpzVpdParser::readPT(
+    types::BinaryVector::const_iterator& itrToPT, auto ptLength)
+{
+    types::RecordOffsetList recordOffsets;
+
+    auto end = itrToPT;
+    std::advance(end, ptLength);
+
+    // Look at each entry in the PT keyword. In the entry,
+    // we care only about the record offset information.
+    while (itrToPT < end)
+    {
+        std::string recordName(itrToPT, itrToPT + Length::RECORD_NAME);
+        // Skip record name and record type
+        std::advance(itrToPT, Length::RECORD_NAME + sizeof(types::RecordType));
+
+        // Get record offset
+        recordOffsets.push_back(readUInt16LE(itrToPT));
+        try
+        {
+            // Verify the ECC for this Record
+            if (!recordEccCheck(itrToPT))
+            {
+                throw(EccException("ERROR: ECC check failed"));
+            }
+        }
+        catch (const EccException& ex)
+        {
+            logging::logMessage(ex.what());
+
+            /*TODO: uncomment when PEL code goes in */
+
+            /*std::string errMsg =
+                std::string{ex.what()} + " Record: " + recordName;
+
+            inventory::PelAdditionalData additionalData{};
+            additionalData.emplace("DESCRIPTION", errMsg);
+            additionalData.emplace("CALLOUT_INVENTORY_PATH", inventoryPath);
+            createPEL(additionalData, PelSeverity::WARNING,
+                      errIntfForEccCheckFail, nullptr);*/
+        }
+        catch (const DataException& ex)
+        {
+            logging::logMessage(ex.what());
+
+            /*TODO: uncomment when PEL code goes in */
+
+            /*std::string errMsg =
+                std::string{ex.what()} + " Record: " + recordName;
+
+            inventory::PelAdditionalData additionalData{};
+            additionalData.emplace("DESCRIPTION", errMsg);
+            additionalData.emplace("CALLOUT_INVENTORY_PATH", inventoryPath);
+            createPEL(additionalData, PelSeverity::WARNING,
+                      errIntfForInvalidVPD, nullptr);*/
+        }
+
+        // Jump record size, record length, ECC offset and ECC length
+        std::advance(itrToPT,
+                     sizeof(types::RecordOffset) + sizeof(types::RecordLength) +
+                         sizeof(types::ECCOffset) + sizeof(types::ECCLength));
+    }
+
+    return recordOffsets;
+}
+
+types::IPZVpdMap::mapped_type
+    IpzVpdParser::readKeywords(types::BinaryVector::const_iterator& itrToKwds)
+{
+    types::IPZVpdMap::mapped_type kwdValueMap{};
+    while (true)
+    {
+        // Note keyword name
+        std::string kwdName(itrToKwds, itrToKwds + Length::KW_NAME);
+        if (constants::LAST_KW == kwdName)
+        {
+            // We're done
+            break;
+        }
+        // Check if the Keyword is '#kw'
+        char kwNameStart = *itrToKwds;
+
+        // Jump past keyword name
+        std::advance(itrToKwds, Length::KW_NAME);
+
+        std::size_t kwdDataLength;
+        std::size_t lengthHighByte;
+
+        if (constants::POUND_KW == kwNameStart)
+        {
+            // Note keyword data length
+            kwdDataLength = *itrToKwds;
+            lengthHighByte = *(itrToKwds + 1);
+            kwdDataLength |= (lengthHighByte << 8);
+
+            // Jump past 2Byte keyword length
+            std::advance(itrToKwds, sizeof(types::PoundKwSize));
+        }
+        else
+        {
+            // Note keyword data length
+            kwdDataLength = *itrToKwds;
+
+            // Jump past keyword length
+            std::advance(itrToKwds, sizeof(types::KwSize));
+        }
+
+        // support all the Keywords
+        auto stop = std::next(itrToKwds, kwdDataLength);
+        std::string kwdata(itrToKwds, stop);
+        kwdValueMap.emplace(std::move(kwdName), std::move(kwdata));
+
+        // Jump past keyword data length
+        std::advance(itrToKwds, kwdDataLength);
+    }
+
+    return kwdValueMap;
+}
+
+void IpzVpdParser::processRecord(auto recordOffset)
+{
+    // Jump to record name
+    auto recordNameOffset =
+        recordOffset + sizeof(types::RecordId) + sizeof(types::RecordSize) +
+        // Skip past the RT keyword, which contains
+        // the record name.
+        Length::KW_NAME + sizeof(types::KwSize);
+
+    // Get record name
+    auto itrToVPDStart = m_vpdVector.cbegin();
+    std::advance(itrToVPDStart, recordNameOffset);
+
+    std::string recordName(itrToVPDStart, itrToVPDStart + Length::RECORD_NAME);
+
+    // proceed to find contained keywords and their values.
+    std::advance(itrToVPDStart, Length::RECORD_NAME);
+
+    // Reverse back to RT Kw, in ipz vpd, to Read RT KW & value
+    std::advance(itrToVPDStart, -(Length::KW_NAME + sizeof(types::KwSize) +
+                                  Length::RECORD_NAME));
+
+    // Add entry for this record (and contained keyword:value pairs)
+    // to the parsed vpd output.
+    m_parsedVPDMap.emplace(std::move(recordName),
+                           std::move(readKeywords(itrToVPDStart)));
+}
+
+types::VPDMapVariant IpzVpdParser::parse()
+{
+    try
+    {
+        auto itrToVPD = m_vpdVector.cbegin();
+
+        // Check vaidity of VHDR record
+        checkHeader(itrToVPD);
+
+        // Read the table of contents
+        auto ptLen = readTOC(itrToVPD);
+
+        // Read the table of contents record, to get offsets
+        // to other records.
+        auto recordOffsets = readPT(itrToVPD, ptLen);
+        for (const auto& offset : recordOffsets)
+        {
+            processRecord(offset);
+        }
+
+        return m_parsedVPDMap;
+    }
+    catch (const std::exception& e)
+    {
+        logging::logMessage(e.what());
+        throw e;
+    }
+}
+
+types::BinaryVector IpzVpdParser::getKeywordValueFromRecord(
+    const types::Record& i_recordName, const types::Keyword& i_keywordName,
+    const types::RecordOffset& i_recordDataOffset)
+{
+    auto l_iterator = m_vpdVector.cbegin();
+
+    // Go to the record name in the given record's offset
+    std::ranges::advance(l_iterator,
+                         i_recordDataOffset + Length::JUMP_TO_RECORD_NAME,
+                         m_vpdVector.cend());
+
+    // Check if the record is present in the given record's offset
+    if (i_recordName !=
+        std::string(l_iterator,
+                    std::ranges::next(l_iterator, Length::RECORD_NAME,
+                                      m_vpdVector.cend())))
+    {
+        throw std::runtime_error(
+            "Given record is not present in the offset provided");
+    }
+
+    std::ranges::advance(l_iterator, Length::RECORD_NAME, m_vpdVector.cend());
+
+    std::string l_kwName = std::string(
+        l_iterator,
+        std::ranges::next(l_iterator, Length::KW_NAME, m_vpdVector.cend()));
+
+    // Iterate through the keywords until the last keyword PF is found.
+    while (l_kwName != constants::LAST_KW)
+    {
+        // First character required for #D keyword check
+        char l_kwNameStart = *l_iterator;
+
+        std::ranges::advance(l_iterator, Length::KW_NAME, m_vpdVector.cend());
+
+        // Get the keyword's data length
+        auto l_kwdDataLength = 0;
+
+        if (constants::POUND_KW == l_kwNameStart)
+        {
+            l_kwdDataLength = readUInt16LE(l_iterator);
+            std::ranges::advance(l_iterator, sizeof(types::PoundKwSize),
+                                 m_vpdVector.cend());
+        }
+        else
+        {
+            l_kwdDataLength = *l_iterator;
+            std::ranges::advance(l_iterator, sizeof(types::KwSize),
+                                 m_vpdVector.cend());
+        }
+
+        if (l_kwName == i_keywordName)
+        {
+            // Return keyword's value to the caller
+            return types::BinaryVector(
+                l_iterator, std::ranges::next(l_iterator, l_kwdDataLength,
+                                              m_vpdVector.cend()));
+        }
+
+        // next keyword search
+        std::ranges::advance(l_iterator, l_kwdDataLength, m_vpdVector.cend());
+
+        // next keyword name
+        l_kwName = std::string(
+            l_iterator,
+            std::ranges::next(l_iterator, Length::KW_NAME, m_vpdVector.cend()));
+    }
+
+    // Keyword not found
+    throw std::runtime_error("Given keyword not found.");
+}
+
+types::RecordData IpzVpdParser::getRecordDetailsFromVTOC(
+    const types::Record& i_recordName, const types::RecordOffset& i_vtocOffset)
+{
+    // Get VTOC's PT keyword value.
+    const auto l_vtocPTKwValue =
+        getKeywordValueFromRecord("VTOC", "PT", i_vtocOffset);
+
+    // Parse through VTOC PT keyword value to find the record which we are
+    // interested in.
+    auto l_vtocPTItr = l_vtocPTKwValue.cbegin();
+
+    types::RecordData l_recordData;
+
+    while (l_vtocPTItr < l_vtocPTKwValue.cend())
+    {
+        if (i_recordName ==
+            std::string(l_vtocPTItr, l_vtocPTItr + Length::RECORD_NAME))
+        {
+            // Record found in VTOC PT keyword. Get offset
+            std::ranges::advance(l_vtocPTItr,
+                                 Length::RECORD_NAME + Length::RECORD_TYPE,
+                                 l_vtocPTKwValue.cend());
+            const auto l_recordOffset = readUInt16LE(l_vtocPTItr);
+
+            std::ranges::advance(l_vtocPTItr, Length::RECORD_OFFSET,
+                                 l_vtocPTKwValue.cend());
+            const auto l_recordLength = readUInt16LE(l_vtocPTItr);
+
+            std::ranges::advance(l_vtocPTItr, Length::RECORD_LENGTH,
+                                 l_vtocPTKwValue.cend());
+            const auto l_eccOffset = readUInt16LE(l_vtocPTItr);
+
+            std::ranges::advance(l_vtocPTItr, Length::RECORD_ECC_OFFSET,
+                                 l_vtocPTKwValue.cend());
+            const auto l_eccLength = readUInt16LE(l_vtocPTItr);
+
+            l_recordData = std::make_tuple(l_recordOffset, l_recordLength,
+                                           l_eccOffset, l_eccLength);
+            break;
+        }
+
+        std::ranges::advance(l_vtocPTItr, Length::SKIP_A_RECORD_IN_PT,
+                             l_vtocPTKwValue.cend());
+    }
+
+    return l_recordData;
+}
+
+types::DbusVariantType IpzVpdParser::readKeywordFromHardware(
+    const types::ReadVpdParams i_paramsToReadData)
+{
+    // Extract record and keyword from i_paramsToReadData
+    types::Record l_record;
+    types::Keyword l_keyword;
+
+    if (const types::IpzType* l_ipzData =
+            std::get_if<types::IpzType>(&i_paramsToReadData))
+    {
+        l_record = std::get<0>(*l_ipzData);
+        l_keyword = std::get<1>(*l_ipzData);
+    }
+    else
+    {
+        logging::logMessage(
+            "Input parameter type provided isn't compatible with the given VPD type.");
+        throw types::DbusInvalidArgument();
+    }
+
+    // Read keyword's value from vector
+    auto l_itrToVPD = m_vpdVector.cbegin();
+
+    if (l_record == "VHDR")
+    {
+// Disable providing a way to read keywords from VHDR for the time being.
+#if 0
+        std::ranges::advance(l_itrToVPD, Offset::VHDR_RECORD,
+                             m_vpdVector.cend());
+
+        return types::DbusVariantType{getKeywordValueFromRecord(
+            l_record, l_keyword, Offset::VHDR_RECORD)};
+#endif
+
+        logging::logMessage("Read cannot be performed on VHDR record.");
+        throw types::DbusInvalidArgument();
+    }
+
+    // Get VTOC offset
+    std::ranges::advance(l_itrToVPD, Offset::VTOC_PTR, m_vpdVector.cend());
+    auto l_vtocOffset = readUInt16LE(l_itrToVPD);
+
+    if (l_record == "VTOC")
+    {
+        // Disable providing a way to read keywords from VTOC for the time
+        // being.
+#if 0
+        return types::DbusVariantType{
+            getKeywordValueFromRecord(l_record, l_keyword, l_vtocOffset)};
+#endif
+
+        logging::logMessage("Read cannot be performed on VTOC record.");
+        throw types::DbusInvalidArgument();
+    }
+
+    // Get record offset from VTOC's PT keyword value.
+    auto l_recordData = getRecordDetailsFromVTOC(l_record, l_vtocOffset);
+    const auto l_recordOffset = std::get<0>(l_recordData);
+
+    if (l_recordOffset == 0)
+    {
+        throw std::runtime_error("Record not found in VTOC PT keyword.");
+    }
+
+    // Get the given keyword's value
+    return types::DbusVariantType{
+        getKeywordValueFromRecord(l_record, l_keyword, l_recordOffset)};
+}
+
+void IpzVpdParser::updateRecordECC(
+    const auto& i_recordDataOffset, const auto& i_recordDataLength,
+    const auto& i_recordECCOffset, size_t i_recordECCLength,
+    types::BinaryVector& io_vpdVector)
+{
+    auto l_recordDataBegin =
+        std::next(io_vpdVector.begin(), i_recordDataOffset);
+
+    auto l_recordECCBegin = std::next(io_vpdVector.begin(), i_recordECCOffset);
+
+    auto l_eccStatus = vpdecc_create_ecc(
+        const_cast<uint8_t*>(&l_recordDataBegin[0]), i_recordDataLength,
+        const_cast<uint8_t*>(&l_recordECCBegin[0]), &i_recordECCLength);
+
+    if (l_eccStatus != VPD_ECC_OK)
+    {
+        throw(EccException("ECC update failed with error " + l_eccStatus));
+    }
+
+    auto l_recordECCEnd = std::next(l_recordECCBegin, i_recordECCLength);
+
+    m_vpdFileStream.seekp(m_vpdStartOffset + i_recordECCOffset, std::ios::beg);
+
+    std::copy(l_recordECCBegin, l_recordECCEnd,
+              std::ostreambuf_iterator<char>(m_vpdFileStream));
+}
+
+int IpzVpdParser::setKeywordValueInRecord(
+    const types::Record& i_recordName, const types::Keyword& i_keywordName,
+    const types::BinaryVector& i_keywordData,
+    const types::RecordOffset& i_recordDataOffset,
+    types::BinaryVector& io_vpdVector)
+{
+    auto l_iterator = io_vpdVector.begin();
+
+    // Go to the record name in the given record's offset
+    std::ranges::advance(l_iterator,
+                         i_recordDataOffset + Length::JUMP_TO_RECORD_NAME,
+                         io_vpdVector.end());
+
+    const std::string l_recordFound(
+        l_iterator,
+        std::ranges::next(l_iterator, Length::RECORD_NAME, io_vpdVector.end()));
+
+    // Check if the record is present in the given record's offset
+    if (i_recordName != l_recordFound)
+    {
+        throw(DataException("Given record found at the offset " +
+                            std::to_string(i_recordDataOffset) + " is : " +
+                            l_recordFound + " and not " + i_recordName));
+    }
+
+    std::ranges::advance(l_iterator, Length::RECORD_NAME, io_vpdVector.end());
+
+    std::string l_kwName = std::string(
+        l_iterator,
+        std::ranges::next(l_iterator, Length::KW_NAME, io_vpdVector.end()));
+
+    // Iterate through the keywords until the last keyword PF is found.
+    while (l_kwName != constants::LAST_KW)
+    {
+        // First character required for #D keyword check
+        char l_kwNameStart = *l_iterator;
+
+        std::ranges::advance(l_iterator, Length::KW_NAME, io_vpdVector.end());
+
+        // Find the keyword's data length
+        size_t l_kwdDataLength = 0;
+
+        if (constants::POUND_KW == l_kwNameStart)
+        {
+            l_kwdDataLength = readUInt16LE(l_iterator);
+            std::ranges::advance(l_iterator, sizeof(types::PoundKwSize),
+                                 io_vpdVector.end());
+        }
+        else
+        {
+            l_kwdDataLength = *l_iterator;
+            std::ranges::advance(l_iterator, sizeof(types::KwSize),
+                                 io_vpdVector.end());
+        }
+
+        if (l_kwName == i_keywordName)
+        {
+            // Before writing the keyword's value, get the maximum size that can
+            // be updated.
+            const auto l_lengthToUpdate =
+                i_keywordData.size() <= l_kwdDataLength
+                    ? i_keywordData.size()
+                    : l_kwdDataLength;
+
+            // Set the keyword's value on vector. This is required to update the
+            // record's ECC based on the new value set.
+            const auto i_keywordDataEnd = std::ranges::next(
+                i_keywordData.cbegin(), l_lengthToUpdate, i_keywordData.cend());
+
+            std::copy(i_keywordData.cbegin(), i_keywordDataEnd, l_iterator);
+
+            // Set the keyword's value on hardware
+            const auto l_kwdDataOffset =
+                std::distance(io_vpdVector.begin(), l_iterator);
+            m_vpdFileStream.seekp(m_vpdStartOffset + l_kwdDataOffset,
+                                  std::ios::beg);
+
+            std::copy(i_keywordData.cbegin(), i_keywordDataEnd,
+                      std::ostreambuf_iterator<char>(m_vpdFileStream));
+
+            // return no of bytes set
+            return l_lengthToUpdate;
+        }
+
+        // next keyword search
+        std::ranges::advance(l_iterator, l_kwdDataLength, io_vpdVector.end());
+
+        // next keyword name
+        l_kwName = std::string(
+            l_iterator,
+            std::ranges::next(l_iterator, Length::KW_NAME, io_vpdVector.end()));
+    }
+
+    // Keyword not found
+    throw(DataException(
+        "Keyword " + i_keywordName + " not found in record " + i_recordName));
+}
+
+int IpzVpdParser::writeKeywordOnHardware(
+    const types::WriteVpdParams i_paramsToWriteData)
+{
+    int l_sizeWritten = -1;
+
+    try
+    {
+        types::Record l_recordName;
+        types::Keyword l_keywordName;
+        types::BinaryVector l_keywordData;
+
+        // Extract record, keyword and value from i_paramsToWriteData
+        if (const types::IpzData* l_ipzData =
+                std::get_if<types::IpzData>(&i_paramsToWriteData))
+        {
+            l_recordName = std::get<0>(*l_ipzData);
+            l_keywordName = std::get<1>(*l_ipzData);
+            l_keywordData = std::get<2>(*l_ipzData);
+        }
+        else
+        {
+            logging::logMessage(
+                "Input parameter type provided isn't compatible with the given FRU's VPD type.");
+            throw types::DbusInvalidArgument();
+        }
+
+        if (l_recordName == "VHDR" || l_recordName == "VTOC")
+        {
+            logging::logMessage(
+                "Write operation not allowed on the given record : " +
+                l_recordName);
+            throw types::DbusNotAllowed();
+        }
+
+        if (l_keywordData.size() == 0)
+        {
+            logging::logMessage(
+                "Write operation not allowed as the given keyword's data length is 0.");
+            throw types::DbusInvalidArgument();
+        }
+
+        auto l_vpdBegin = m_vpdVector.begin();
+
+        // Get VTOC offset
+        std::ranges::advance(l_vpdBegin, Offset::VTOC_PTR, m_vpdVector.end());
+        auto l_vtocOffset = readUInt16LE(l_vpdBegin);
+
+        // Get the details of user given record from VTOC
+        const types::RecordData& l_inputRecordDetails =
+            getRecordDetailsFromVTOC(l_recordName, l_vtocOffset);
+
+        const auto& l_inputRecordOffset = std::get<0>(l_inputRecordDetails);
+
+        if (l_inputRecordOffset == 0)
+        {
+            throw(DataException("Record not found in VTOC PT keyword."));
+        }
+
+        // Create a local copy of m_vpdVector to perform keyword update and ecc
+        // update on filestream.
+        types::BinaryVector l_vpdVector = m_vpdVector;
+
+        // write keyword's value on hardware
+        l_sizeWritten =
+            setKeywordValueInRecord(l_recordName, l_keywordName, l_keywordData,
+                                    l_inputRecordOffset, l_vpdVector);
+
+        if (l_sizeWritten <= 0)
+        {
+            throw(DataException("Unable to set value on " + l_recordName + ":" +
+                                l_keywordName));
+        }
+
+        // Update the record's ECC
+        updateRecordECC(l_inputRecordOffset, std::get<1>(l_inputRecordDetails),
+                        std::get<2>(l_inputRecordDetails),
+                        std::get<3>(l_inputRecordDetails), l_vpdVector);
+
+        logging::logMessage(std::to_string(l_sizeWritten) +
+                            " bytes updated successfully on hardware for " +
+                            l_recordName + ":" + l_keywordName);
+    }
+    catch (const std::exception& l_exception)
+    {
+        throw;
+    }
+
+    return l_sizeWritten;
+}
+} // namespace vpd
diff --git a/vpd-manager/src/isdimm_parser.cpp b/vpd-manager/src/isdimm_parser.cpp
new file mode 100644
index 0000000..76e1dea
--- /dev/null
+++ b/vpd-manager/src/isdimm_parser.cpp
@@ -0,0 +1,313 @@
+#include "isdimm_parser.hpp"
+
+#include "constants.hpp"
+#include "logger.hpp"
+
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+#include <optional>
+#include <string>
+#include <unordered_map>
+
+namespace vpd
+{
+
+// Constants
+constexpr auto SPD_JEDEC_DDR4_SDRAM_CAP_MASK = 0x0F;
+constexpr auto SPD_JEDEC_DDR4_PRI_BUS_WIDTH_MASK = 0x07;
+constexpr auto SPD_JEDEC_DDR4_SDRAM_WIDTH_MASK = 0x07;
+constexpr auto SPD_JEDEC_DDR4_NUM_RANKS_MASK = 0x38;
+constexpr auto SPD_JEDEC_DDR4_DIE_COUNT_MASK = 0x70;
+constexpr auto SPD_JEDEC_DDR4_SINGLE_LOAD_STACK = 0x02;
+constexpr auto SPD_JEDEC_DDR4_SIGNAL_LOADING_MASK = 0x03;
+
+constexpr auto SPD_JEDEC_DDR4_SDRAMCAP_MULTIPLIER = 256;
+constexpr auto SPD_JEDEC_DDR4_PRI_BUS_WIDTH_MULTIPLIER = 8;
+constexpr auto SPD_JEDEC_DDR4_SDRAM_WIDTH_MULTIPLIER = 4;
+constexpr auto SPD_JEDEC_DDR4_SDRAMCAP_RESERVED = 8;
+constexpr auto SPD_JEDEC_DDR4_4_RESERVED_BITS = 4;
+constexpr auto SPD_JEDEC_DDR4_3_RESERVED_BITS = 3;
+constexpr auto SPD_JEDEC_DDR4_DIE_COUNT_RIGHT_SHIFT = 4;
+
+constexpr auto SPD_JEDEC_DDR4_MFG_ID_MSB_OFFSET = 321;
+constexpr auto SPD_JEDEC_DDR4_MFG_ID_LSB_OFFSET = 320;
+constexpr auto SPD_JEDEC_DDR4_SN_BYTE0_OFFSET = 325;
+constexpr auto SPD_JEDEC_DDR4_SN_BYTE1_OFFSET = 326;
+constexpr auto SPD_JEDEC_DDR4_SN_BYTE2_OFFSET = 327;
+constexpr auto SPD_JEDEC_DDR4_SN_BYTE3_OFFSET = 328;
+constexpr auto SPD_JEDEC_DDR4_SDRAM_DENSITY_BANK_OFFSET = 4;
+constexpr auto SPD_JEDEC_DDR4_SDRAM_ADDR_OFFSET = 5;
+constexpr auto SPD_JEDEC_DDR4_DRAM_PRI_PACKAGE_OFFSET = 6;
+constexpr auto SPD_JEDEC_DDR4_DRAM_MODULE_ORG_OFFSET = 12;
+
+// Lookup tables
+const std::map<std::tuple<std::string, uint8_t>, std::string> pnFreqFnMap = {
+    {std::make_tuple("8421000", 6), "78P4191"},
+    {std::make_tuple("8421008", 6), "78P4192"},
+    {std::make_tuple("8529000", 6), "78P4197"},
+    {std::make_tuple("8529008", 6), "78P4198"},
+    {std::make_tuple("8529928", 6), "78P4199"},
+    {std::make_tuple("8529B28", 6), "78P4200"},
+    {std::make_tuple("8631928", 6), "78P6925"},
+    {std::make_tuple("8529000", 5), "78P7317"},
+    {std::make_tuple("8529008", 5), "78P7318"},
+    {std::make_tuple("8631008", 5), "78P6815"}};
+
+const std::unordered_map<std::string, std::string> pnCCINMap = {
+    {"78P4191", "324D"}, {"78P4192", "324E"}, {"78P4197", "324E"},
+    {"78P4198", "324F"}, {"78P4199", "325A"}, {"78P4200", "324C"},
+    {"78P6925", "32BC"}, {"78P7317", "331A"}, {"78P7318", "331F"},
+    {"78P6815", "32BB"}};
+
+auto JedecSpdParser::getDDR4DimmCapacity(
+    types::BinaryVector::const_iterator& i_iterator)
+{
+    size_t l_tmp = 0, l_dimmSize = 0;
+
+    size_t l_sdramCap = 1, l_priBusWid = 1, l_sdramWid = 1,
+           l_logicalRanksPerDimm = 1;
+    size_t l_dieCount = 1;
+
+    // NOTE: This calculation is Only for DDR4
+
+    // Calculate SDRAM  capacity
+    l_tmp = i_iterator[constants::SPD_BYTE_4] & SPD_JEDEC_DDR4_SDRAM_CAP_MASK;
+
+    /* Make sure the bits are not Reserved */
+    if (l_tmp >= SPD_JEDEC_DDR4_SDRAMCAP_RESERVED)
+    {
+        logging::logMessage(
+            "Bad data in spd byte 4. Can't calculate SDRAM capacity "
+            "and so dimm size.\n ");
+        return l_dimmSize;
+    }
+    l_sdramCap = (l_sdramCap << l_tmp) * SPD_JEDEC_DDR4_SDRAMCAP_MULTIPLIER;
+
+    /* Calculate Primary bus width */
+    l_tmp = i_iterator[constants::SPD_BYTE_13] &
+            SPD_JEDEC_DDR4_PRI_BUS_WIDTH_MASK;
+    if (l_tmp >= SPD_JEDEC_DDR4_4_RESERVED_BITS)
+    {
+        logging::logMessage(
+            "Bad data in spd byte 13. Can't calculate primary bus "
+            "width and so dimm size.\n ");
+        return l_dimmSize;
+    }
+    l_priBusWid = (l_priBusWid << l_tmp) *
+                  SPD_JEDEC_DDR4_PRI_BUS_WIDTH_MULTIPLIER;
+
+    /* Calculate SDRAM width */
+    l_tmp = i_iterator[constants::SPD_BYTE_12] &
+            SPD_JEDEC_DDR4_SDRAM_WIDTH_MASK;
+    if (l_tmp >= SPD_JEDEC_DDR4_4_RESERVED_BITS)
+    {
+        logging::logMessage(
+            "Bad data in spd byte 12. Can't calculate SDRAM width and "
+            "so dimm size.\n ");
+        return l_dimmSize;
+    }
+    l_sdramWid = (l_sdramWid << l_tmp) * SPD_JEDEC_DDR4_SDRAM_WIDTH_MULTIPLIER;
+
+    l_tmp = i_iterator[constants::SPD_BYTE_6] &
+            SPD_JEDEC_DDR4_SIGNAL_LOADING_MASK;
+    if (l_tmp == SPD_JEDEC_DDR4_SINGLE_LOAD_STACK)
+    {
+        // Fetch die count
+        l_tmp = i_iterator[constants::SPD_BYTE_6] &
+                SPD_JEDEC_DDR4_DIE_COUNT_MASK;
+        l_tmp >>= SPD_JEDEC_DDR4_DIE_COUNT_RIGHT_SHIFT;
+        l_dieCount = l_tmp + 1;
+    }
+
+    /* Calculate Number of ranks */
+    l_tmp = i_iterator[constants::SPD_BYTE_12] & SPD_JEDEC_DDR4_NUM_RANKS_MASK;
+    l_tmp >>= SPD_JEDEC_DDR4_3_RESERVED_BITS;
+
+    if (l_tmp >= SPD_JEDEC_DDR4_4_RESERVED_BITS)
+    {
+        logging::logMessage(
+            "Can't calculate number of ranks. Invalid data found.\n ");
+        return l_dimmSize;
+    }
+    l_logicalRanksPerDimm = (l_tmp + 1) * l_dieCount;
+
+    l_dimmSize = (l_sdramCap / SPD_JEDEC_DDR4_PRI_BUS_WIDTH_MULTIPLIER) *
+                 (l_priBusWid / l_sdramWid) * l_logicalRanksPerDimm;
+
+    return l_dimmSize;
+}
+
+std::string_view JedecSpdParser::getDDR4PartNumber(
+    types::BinaryVector::const_iterator& i_iterator)
+{
+    char l_tmpPN[constants::PART_NUM_LEN + 1] = {'\0'};
+    sprintf(l_tmpPN, "%02X%02X%02X%X",
+            i_iterator[SPD_JEDEC_DDR4_SDRAM_DENSITY_BANK_OFFSET],
+            i_iterator[SPD_JEDEC_DDR4_SDRAM_ADDR_OFFSET],
+            i_iterator[SPD_JEDEC_DDR4_DRAM_PRI_PACKAGE_OFFSET],
+            i_iterator[SPD_JEDEC_DDR4_DRAM_MODULE_ORG_OFFSET] & 0x0F);
+    std::string l_partNumber(l_tmpPN, sizeof(l_tmpPN) - 1);
+    return l_partNumber;
+}
+
+std::string JedecSpdParser::getDDR4SerialNumber(
+    types::BinaryVector::const_iterator& i_iterator)
+{
+    char l_tmpSN[constants::SERIAL_NUM_LEN + 1] = {'\0'};
+    sprintf(l_tmpSN, "%02X%02X%02X%02X%02X%02X",
+            i_iterator[SPD_JEDEC_DDR4_MFG_ID_MSB_OFFSET],
+            i_iterator[SPD_JEDEC_DDR4_MFG_ID_LSB_OFFSET],
+            i_iterator[SPD_JEDEC_DDR4_SN_BYTE0_OFFSET],
+            i_iterator[SPD_JEDEC_DDR4_SN_BYTE1_OFFSET],
+            i_iterator[SPD_JEDEC_DDR4_SN_BYTE2_OFFSET],
+            i_iterator[SPD_JEDEC_DDR4_SN_BYTE3_OFFSET]);
+    std::string l_serialNumber(l_tmpSN, sizeof(l_tmpSN) - 1);
+    return l_serialNumber;
+}
+
+std::string_view JedecSpdParser::getDDR4FruNumber(
+    const std::string& i_partNumber,
+    types::BinaryVector::const_iterator& i_iterator)
+{
+    // check for 128GB ISRDIMM not implemented
+    //(128GB 2RX4(8GX72) IS RDIMM 36*(16GBIT, 2H),1.2V 288PIN,1.2" ROHS) - NA
+
+    // MTB Units is used in deciding the frequency of the DIMM
+    // This is applicable only for DDR4 specification
+    // 10 - DDR4-1600
+    // 9  - DDR4-1866
+    // 8  - DDR4-2133
+    // 7  - DDR4-2400
+    // 6  - DDR4-2666
+    // 5  - DDR4-3200
+    // pnFreqFnMap < tuple <partNumber, MTBUnits>, fruNumber>
+    uint8_t l_mtbUnits = i_iterator[constants::SPD_BYTE_18] &
+                         constants::SPD_BYTE_MASK;
+    std::string l_fruNumber = "FFFFFFF";
+    auto it = pnFreqFnMap.find({i_partNumber, l_mtbUnits});
+    if (it != pnFreqFnMap.end())
+    {
+        l_fruNumber = it->second;
+    }
+
+    return l_fruNumber;
+}
+
+std::string_view JedecSpdParser::getDDR4CCIN(const std::string& i_fruNumber)
+{
+    auto it = pnCCINMap.find(i_fruNumber);
+    if (it != pnCCINMap.end())
+    {
+        return it->second;
+    }
+    return "XXXX"; // Return default value as XXXX
+}
+
+auto JedecSpdParser::getDDR5DimmCapacity(
+    types::BinaryVector::const_iterator& i_iterator)
+{
+    // dummy implementation to be updated when required
+    size_t dimmSize = 0;
+    (void)i_iterator;
+    return dimmSize;
+}
+
+auto JedecSpdParser::getDDR5PartNumber(
+    types::BinaryVector::const_iterator& i_iterator)
+{
+    // dummy implementation to be updated when required
+    std::string l_partNumber;
+    (void)i_iterator;
+    l_partNumber = "0123456";
+    return l_partNumber;
+}
+
+auto JedecSpdParser::getDDR5SerialNumber(
+    types::BinaryVector::const_iterator& i_iterator)
+{
+    // dummy implementation to be updated when required
+    std::string l_serialNumber;
+    (void)i_iterator;
+    l_serialNumber = "444444444444";
+    return l_serialNumber;
+}
+
+auto JedecSpdParser::getDDR5FruNumber(const std::string& i_partNumber)
+{
+    // dummy implementation to be updated when required
+    static std::unordered_map<std::string, std::string> pnFruMap = {
+        {"1234567", "XXXXXXX"}};
+
+    std::string l_fruNumber;
+    auto itr = pnFruMap.find(i_partNumber);
+    if (itr != pnFruMap.end())
+    {
+        l_fruNumber = itr->second;
+    }
+    else
+    {
+        l_fruNumber = "FFFFFFF";
+    }
+    return l_fruNumber;
+}
+
+auto JedecSpdParser::getDDR5CCIN(const std::string& i_partNumber)
+{
+    // dummy implementation to be updated when required
+    static std::unordered_map<std::string, std::string> pnCCINMap = {
+        {"1234567", "XXXX"}};
+
+    std::string ccin = "XXXX";
+    auto itr = pnCCINMap.find(i_partNumber);
+    if (itr != pnCCINMap.end())
+    {
+        ccin = itr->second;
+    }
+    return ccin;
+}
+
+types::JedecSpdMap JedecSpdParser::readKeywords(
+    types::BinaryVector::const_iterator& i_iterator)
+{
+    types::JedecSpdMap l_keywordValueMap{};
+    size_t dimmSize = getDDR4DimmCapacity(i_iterator);
+    if (!dimmSize)
+    {
+        logging::logMessage("Error: Calculated dimm size is 0.");
+    }
+    else
+    {
+        l_keywordValueMap.emplace("MemorySizeInKB",
+                                  dimmSize * constants::CONVERT_MB_TO_KB);
+    }
+
+    auto l_partNumber = getDDR4PartNumber(i_iterator);
+    auto l_fruNumber = getDDR4FruNumber(
+        std::string(l_partNumber.begin(), l_partNumber.end()), i_iterator);
+    auto l_serialNumber = getDDR4SerialNumber(i_iterator);
+    auto ccin =
+        getDDR4CCIN(std::string(l_fruNumber.begin(), l_fruNumber.end()));
+    // PN value is made same as FN value
+    auto l_displayPartNumber = l_fruNumber;
+    l_keywordValueMap.emplace("PN",
+                              move(std::string(l_displayPartNumber.begin(),
+                                               l_displayPartNumber.end())));
+    l_keywordValueMap.emplace(
+        "FN", move(std::string(l_fruNumber.begin(), l_fruNumber.end())));
+    l_keywordValueMap.emplace("SN", move(l_serialNumber));
+    l_keywordValueMap.emplace("CC",
+                              move(std::string(ccin.begin(), ccin.end())));
+
+    return l_keywordValueMap;
+}
+
+types::VPDMapVariant JedecSpdParser::parse()
+{
+    // Read the data and return the map
+    auto l_iterator = m_memSpd.cbegin();
+    auto l_spdDataMap = readKeywords(l_iterator);
+    return l_spdDataMap;
+}
+
+} // namespace vpd
diff --git a/vpd-manager/src/keyword_vpd_parser.cpp b/vpd-manager/src/keyword_vpd_parser.cpp
new file mode 100644
index 0000000..9997f94
--- /dev/null
+++ b/vpd-manager/src/keyword_vpd_parser.cpp
@@ -0,0 +1,136 @@
+#include "keyword_vpd_parser.hpp"
+
+#include "constants.hpp"
+#include "exceptions.hpp"
+#include "logger.hpp"
+
+#include <iostream>
+#include <numeric>
+#include <string>
+
+namespace vpd
+{
+
+types::VPDMapVariant KeywordVpdParser::parse()
+{
+    if (m_keywordVpdVector.empty())
+    {
+        throw(DataException("Vector for Keyword format VPD is empty"));
+    }
+    m_vpdIterator = m_keywordVpdVector.begin();
+
+    if (*m_vpdIterator != constants::KW_VPD_START_TAG)
+    {
+        throw(DataException("Invalid Large resource type Identifier String"));
+    }
+
+    checkNextBytesValidity(sizeof(constants::KW_VPD_START_TAG));
+    std::advance(m_vpdIterator, sizeof(constants::KW_VPD_START_TAG));
+
+    uint16_t l_dataSize = getKwDataSize();
+
+    checkNextBytesValidity(constants::TWO_BYTES + l_dataSize);
+    std::advance(m_vpdIterator, constants::TWO_BYTES + l_dataSize);
+
+    // Check for invalid vendor defined large resource type
+    if (*m_vpdIterator != constants::KW_VPD_PAIR_START_TAG)
+    {
+        if (*m_vpdIterator != constants::ALT_KW_VPD_PAIR_START_TAG)
+        {
+            throw(DataException("Invalid Keyword Vpd Start Tag"));
+        }
+    }
+    types::BinaryVector::const_iterator l_checkSumStart = m_vpdIterator;
+    auto l_kwValMap = populateVpdMap();
+
+    // Do these validations before returning parsed data.
+    // Check for small resource type end tag
+    if (*m_vpdIterator != constants::KW_VAL_PAIR_END_TAG)
+    {
+        throw(DataException("Invalid Small resource type End"));
+    }
+
+    types::BinaryVector::const_iterator l_checkSumEnd = m_vpdIterator;
+    validateChecksum(l_checkSumStart, l_checkSumEnd);
+
+    checkNextBytesValidity(constants::TWO_BYTES);
+    std::advance(m_vpdIterator, constants::TWO_BYTES);
+
+    // Check VPD end Tag.
+    if (*m_vpdIterator != constants::KW_VPD_END_TAG)
+    {
+        throw(DataException("Invalid Small resource type."));
+    }
+
+    return l_kwValMap;
+}
+
+types::KeywordVpdMap KeywordVpdParser::populateVpdMap()
+{
+    checkNextBytesValidity(constants::ONE_BYTE);
+    std::advance(m_vpdIterator, constants::ONE_BYTE);
+
+    auto l_totalSize = getKwDataSize();
+    if (l_totalSize == 0)
+    {
+        throw(DataException("Data size is 0, badly formed keyword VPD"));
+    }
+
+    checkNextBytesValidity(constants::TWO_BYTES);
+    std::advance(m_vpdIterator, constants::TWO_BYTES);
+
+    types::KeywordVpdMap l_kwValMap;
+
+    // Parse the keyword-value and store the pairs in map
+    while (l_totalSize > 0)
+    {
+        checkNextBytesValidity(constants::TWO_BYTES);
+        std::string l_keywordName(m_vpdIterator,
+                                  m_vpdIterator + constants::TWO_BYTES);
+        std::advance(m_vpdIterator, constants::TWO_BYTES);
+
+        size_t l_kwSize = *m_vpdIterator;
+        checkNextBytesValidity(constants::ONE_BYTE + l_kwSize);
+        m_vpdIterator++;
+        std::vector<uint8_t> l_valueBytes(m_vpdIterator,
+                                          m_vpdIterator + l_kwSize);
+        std::advance(m_vpdIterator, l_kwSize);
+
+        l_kwValMap.emplace(
+            std::make_pair(std::move(l_keywordName), std::move(l_valueBytes)));
+
+        l_totalSize -= constants::TWO_BYTES + constants::ONE_BYTE + l_kwSize;
+    }
+
+    return l_kwValMap;
+}
+
+void KeywordVpdParser::validateChecksum(
+    types::BinaryVector::const_iterator i_checkSumStart,
+    types::BinaryVector::const_iterator i_checkSumEnd)
+{
+    uint8_t l_checkSumCalculated = 0;
+
+    // Checksum calculation
+    l_checkSumCalculated =
+        std::accumulate(i_checkSumStart, i_checkSumEnd, l_checkSumCalculated);
+    l_checkSumCalculated = ~l_checkSumCalculated + 1;
+    uint8_t l_checksumVpdValue = *(m_vpdIterator + constants::ONE_BYTE);
+
+    if (l_checkSumCalculated != l_checksumVpdValue)
+    {
+        throw(DataException("Invalid Checksum"));
+    }
+}
+
+void KeywordVpdParser::checkNextBytesValidity(uint8_t i_numberOfBytes)
+{
+    if ((std::distance(m_keywordVpdVector.begin(),
+                       m_vpdIterator + i_numberOfBytes)) >
+        std::distance(m_keywordVpdVector.begin(), m_keywordVpdVector.end()))
+    {
+        throw(DataException("Truncated VPD data"));
+    }
+}
+
+} // namespace vpd
diff --git a/vpd-manager/src/logger.cpp b/vpd-manager/src/logger.cpp
new file mode 100644
index 0000000..19959a1
--- /dev/null
+++ b/vpd-manager/src/logger.cpp
@@ -0,0 +1,23 @@
+#include "logger.hpp"
+
+#include <sstream>
+
+namespace vpd
+{
+namespace logging
+{
+void logMessage(std::string_view message, const std::source_location& location)
+{
+    std::ostringstream log;
+    log << "FileName: " << location.file_name() << ","
+        << " Line: " << location.line() << " " << message;
+
+    /* TODO: Check on this later.
+    log << "FileName: " << location.file_name() << ","
+        << " Line: " << location.line() << ","
+        << " Func: " << location.function_name() << ", " << message;*/
+
+    std::cout << log.str() << std::endl;
+}
+} // namespace logging
+} // namespace vpd
diff --git a/vpd-manager/src/manager.cpp b/vpd-manager/src/manager.cpp
new file mode 100644
index 0000000..51eb4af
--- /dev/null
+++ b/vpd-manager/src/manager.cpp
@@ -0,0 +1,915 @@
+#include "config.h"
+
+#include "manager.hpp"
+
+#include "backup_restore.hpp"
+#include "constants.hpp"
+#include "exceptions.hpp"
+#include "logger.hpp"
+#include "parser.hpp"
+#include "parser_factory.hpp"
+#include "parser_interface.hpp"
+#include "types.hpp"
+#include "utility/dbus_utility.hpp"
+#include "utility/json_utility.hpp"
+#include "utility/vpd_specific_utility.hpp"
+
+#include <boost/asio/steady_timer.hpp>
+#include <sdbusplus/bus/match.hpp>
+#include <sdbusplus/message.hpp>
+
+namespace vpd
+{
+Manager::Manager(
+    const std::shared_ptr<boost::asio::io_context>& ioCon,
+    const std::shared_ptr<sdbusplus::asio::dbus_interface>& iFace,
+    const std::shared_ptr<sdbusplus::asio::connection>& asioConnection) :
+    m_ioContext(ioCon), m_interface(iFace), m_asioConnection(asioConnection)
+{
+    try
+    {
+#ifdef IBM_SYSTEM
+        m_worker = std::make_shared<Worker>(INVENTORY_JSON_DEFAULT);
+
+        // Set up minimal things that is needed before bus name is claimed.
+        m_worker->performInitialSetup();
+
+        // set callback to detect any asset tag change
+        registerAssetTagChangeCallback();
+
+        // set async timer to detect if system VPD is published on D-Bus.
+        SetTimerToDetectSVPDOnDbus();
+
+        // set async timer to detect if VPD collection is done.
+        SetTimerToDetectVpdCollectionStatus();
+
+        // Instantiate GpioMonitor class
+        m_gpioMonitor = std::make_shared<GpioMonitor>(
+            m_worker->getSysCfgJsonObj(), m_worker, m_ioContext);
+
+#endif
+        // set callback to detect host state change.
+        registerHostStateChangeCallback();
+
+        // For backward compatibility. Should be depricated.
+        iFace->register_method(
+            "WriteKeyword",
+            [this](const sdbusplus::message::object_path i_path,
+                   const std::string i_recordName, const std::string i_keyword,
+                   const types::BinaryVector i_value) -> int {
+                return this->updateKeyword(
+                    i_path, std::make_tuple(i_recordName, i_keyword, i_value));
+            });
+
+        // Register methods under com.ibm.VPD.Manager interface
+        iFace->register_method(
+            "UpdateKeyword",
+            [this](const types::Path i_vpdPath,
+                   const types::WriteVpdParams i_paramsToWriteData) -> int {
+                return this->updateKeyword(i_vpdPath, i_paramsToWriteData);
+            });
+
+        iFace->register_method(
+            "WriteKeywordOnHardware",
+            [this](const types::Path i_fruPath,
+                   const types::WriteVpdParams i_paramsToWriteData) -> int {
+                return this->updateKeywordOnHardware(i_fruPath,
+                                                     i_paramsToWriteData);
+            });
+
+        iFace->register_method(
+            "ReadKeyword",
+            [this](const types::Path i_fruPath,
+                   const types::ReadVpdParams i_paramsToReadData)
+                -> types::DbusVariantType {
+                return this->readKeyword(i_fruPath, i_paramsToReadData);
+            });
+
+        iFace->register_method(
+            "CollectFRUVPD",
+            [this](const sdbusplus::message::object_path& i_dbusObjPath) {
+                this->collectSingleFruVpd(i_dbusObjPath);
+            });
+
+        iFace->register_method(
+            "deleteFRUVPD",
+            [this](const sdbusplus::message::object_path& i_dbusObjPath) {
+                this->deleteSingleFruVpd(i_dbusObjPath);
+            });
+
+        iFace->register_method(
+            "GetExpandedLocationCode",
+            [this](const std::string& i_unexpandedLocationCode,
+                   uint16_t& i_nodeNumber) -> std::string {
+                return this->getExpandedLocationCode(i_unexpandedLocationCode,
+                                                     i_nodeNumber);
+            });
+
+        iFace->register_method("GetFRUsByExpandedLocationCode",
+                               [this](const std::string& i_expandedLocationCode)
+                                   -> types::ListOfPaths {
+                                   return this->getFrusByExpandedLocationCode(
+                                       i_expandedLocationCode);
+                               });
+
+        iFace->register_method(
+            "GetFRUsByUnexpandedLocationCode",
+            [this](const std::string& i_unexpandedLocationCode,
+                   uint16_t& i_nodeNumber) -> types::ListOfPaths {
+                return this->getFrusByUnexpandedLocationCode(
+                    i_unexpandedLocationCode, i_nodeNumber);
+            });
+
+        iFace->register_method(
+            "GetHardwarePath",
+            [this](const sdbusplus::message::object_path& i_dbusObjPath)
+                -> std::string { return this->getHwPath(i_dbusObjPath); });
+
+        iFace->register_method("PerformVPDRecollection", [this]() {
+            this->performVpdRecollection();
+        });
+
+        // Indicates FRU VPD collection for the system has not started.
+        iFace->register_property_rw<std::string>(
+            "CollectionStatus", sdbusplus::vtable::property_::emits_change,
+            [this](const std::string l_currStatus, const auto&) {
+                m_vpdCollectionStatus = l_currStatus;
+                return 0;
+            },
+            [this](const auto&) { return m_vpdCollectionStatus; });
+    }
+    catch (const std::exception& e)
+    {
+        logging::logMessage(
+            "VPD-Manager service failed. " + std::string(e.what()));
+        throw;
+    }
+}
+
+#ifdef IBM_SYSTEM
+void Manager::registerAssetTagChangeCallback()
+{
+    static std::shared_ptr<sdbusplus::bus::match_t> l_assetMatch =
+        std::make_shared<sdbusplus::bus::match_t>(
+            *m_asioConnection,
+            sdbusplus::bus::match::rules::propertiesChanged(
+                constants::systemInvPath, constants::assetTagInf),
+            [this](sdbusplus::message_t& l_msg) {
+                processAssetTagChangeCallback(l_msg);
+            });
+}
+
+void Manager::processAssetTagChangeCallback(sdbusplus::message_t& i_msg)
+{
+    try
+    {
+        if (i_msg.is_method_error())
+        {
+            throw std::runtime_error(
+                "Error reading callback msg for asset tag.");
+        }
+
+        std::string l_objectPath;
+        types::PropertyMap l_propMap;
+        i_msg.read(l_objectPath, l_propMap);
+
+        const auto& l_itrToAssetTag = l_propMap.find("AssetTag");
+        if (l_itrToAssetTag != l_propMap.end())
+        {
+            if (auto l_assetTag =
+                    std::get_if<std::string>(&(l_itrToAssetTag->second)))
+            {
+                // Call Notify to persist the AssetTag
+                types::ObjectMap l_objectMap = {
+                    {sdbusplus::message::object_path(constants::systemInvPath),
+                     {{constants::assetTagInf, {{"AssetTag", *l_assetTag}}}}}};
+
+                // Notify PIM
+                if (!dbusUtility::callPIM(move(l_objectMap)))
+                {
+                    throw std::runtime_error(
+                        "Call to PIM failed for asset tag update.");
+                }
+            }
+        }
+        else
+        {
+            throw std::runtime_error(
+                "Could not find asset tag in callback message.");
+        }
+    }
+    catch (const std::exception& l_ex)
+    {
+        // TODO: Log PEL with below description.
+        logging::logMessage("Asset tag callback update failed with error: " +
+                            std::string(l_ex.what()));
+    }
+}
+
+void Manager::SetTimerToDetectSVPDOnDbus()
+{
+    static boost::asio::steady_timer timer(*m_ioContext);
+
+    // timer for 2 seconds
+    auto asyncCancelled = timer.expires_after(std::chrono::seconds(2));
+
+    (asyncCancelled == 0) ? logging::logMessage("Timer started")
+                          : logging::logMessage("Timer re-started");
+
+    timer.async_wait([this](const boost::system::error_code& ec) {
+        if (ec == boost::asio::error::operation_aborted)
+        {
+            throw std::runtime_error(
+                "Timer to detect system VPD collection status was aborted");
+        }
+
+        if (ec)
+        {
+            throw std::runtime_error(
+                "Timer to detect System VPD collection failed");
+        }
+
+        if (m_worker->isSystemVPDOnDBus())
+        {
+            // cancel the timer
+            timer.cancel();
+
+            // Triggering FRU VPD collection. Setting status to "In
+            // Progress".
+            m_interface->set_property("CollectionStatus",
+                                      std::string("InProgress"));
+            m_worker->collectFrusFromJson();
+        }
+    });
+}
+
+void Manager::SetTimerToDetectVpdCollectionStatus()
+{
+    // Keeping max retry for 2 minutes. TODO: Make it cinfigurable based on
+    // system type.
+    static constexpr auto MAX_RETRY = 40;
+
+    static boost::asio::steady_timer l_timer(*m_ioContext);
+    static uint8_t l_timerRetry = 0;
+
+    auto l_asyncCancelled = l_timer.expires_after(std::chrono::seconds(3));
+
+    (l_asyncCancelled == 0)
+        ? logging::logMessage("Collection Timer started")
+        : logging::logMessage("Collection Timer re-started");
+
+    l_timer.async_wait([this](const boost::system::error_code& ec) {
+        if (ec == boost::asio::error::operation_aborted)
+        {
+            throw std::runtime_error(
+                "Timer to detect thread collection status was aborted");
+        }
+
+        if (ec)
+        {
+            throw std::runtime_error(
+                "Timer to detect thread collection failed");
+        }
+
+        if (m_worker->isAllFruCollectionDone())
+        {
+            // cancel the timer
+            l_timer.cancel();
+            m_interface->set_property("CollectionStatus",
+                                      std::string("Completed"));
+
+            const nlohmann::json& l_sysCfgJsonObj =
+                m_worker->getSysCfgJsonObj();
+            if (jsonUtility::isBackupAndRestoreRequired(l_sysCfgJsonObj))
+            {
+                BackupAndRestore l_backupAndRestoreObj(l_sysCfgJsonObj);
+                l_backupAndRestoreObj.backupAndRestore();
+            }
+        }
+        else
+        {
+            auto l_threadCount = m_worker->getActiveThreadCount();
+            if (l_timerRetry == MAX_RETRY)
+            {
+                l_timer.cancel();
+                logging::logMessage("Taking too long. Active thread = " +
+                                    std::to_string(l_threadCount));
+            }
+            else
+            {
+                l_timerRetry++;
+                logging::logMessage("Waiting... active thread = " +
+                                    std::to_string(l_threadCount) + "After " +
+                                    std::to_string(l_timerRetry) + " re-tries");
+
+                SetTimerToDetectVpdCollectionStatus();
+            }
+        }
+    });
+}
+#endif
+
+int Manager::updateKeyword(const types::Path i_vpdPath,
+                           const types::WriteVpdParams i_paramsToWriteData)
+{
+    if (i_vpdPath.empty())
+    {
+        logging::logMessage("Given VPD path is empty.");
+        return -1;
+    }
+
+    types::Path l_fruPath;
+    nlohmann::json l_sysCfgJsonObj{};
+
+    if (m_worker.get() != nullptr)
+    {
+        l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
+
+        // Get the EEPROM path
+        if (!l_sysCfgJsonObj.empty())
+        {
+            try
+            {
+                l_fruPath =
+                    jsonUtility::getFruPathFromJson(l_sysCfgJsonObj, i_vpdPath);
+            }
+            catch (const std::exception& l_exception)
+            {
+                logging::logMessage(
+                    "Error while getting FRU path, Path: " + i_vpdPath +
+                    ", error: " + std::string(l_exception.what()));
+                return -1;
+            }
+        }
+    }
+
+    if (l_fruPath.empty())
+    {
+        l_fruPath = i_vpdPath;
+    }
+
+    try
+    {
+        std::shared_ptr<Parser> l_parserObj =
+            std::make_shared<Parser>(l_fruPath, l_sysCfgJsonObj);
+        return l_parserObj->updateVpdKeyword(i_paramsToWriteData);
+    }
+    catch (const std::exception& l_exception)
+    {
+        // TODO:: error log needed
+        logging::logMessage("Update keyword failed for file[" + i_vpdPath +
+                            "], reason: " + std::string(l_exception.what()));
+        return -1;
+    }
+}
+
+int Manager::updateKeywordOnHardware(
+    const types::Path i_fruPath,
+    const types::WriteVpdParams i_paramsToWriteData) noexcept
+{
+    try
+    {
+        if (i_fruPath.empty())
+        {
+            throw std::runtime_error("Given FRU path is empty");
+        }
+
+        nlohmann::json l_sysCfgJsonObj{};
+
+        if (m_worker.get() != nullptr)
+        {
+            l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
+        }
+
+        std::shared_ptr<Parser> l_parserObj =
+            std::make_shared<Parser>(i_fruPath, l_sysCfgJsonObj);
+        return l_parserObj->updateVpdKeywordOnHardware(i_paramsToWriteData);
+    }
+    catch (const std::exception& l_exception)
+    {
+        EventLogger::createAsyncPel(
+            types::ErrorType::InvalidEeprom, types::SeverityType::Informational,
+            __FILE__, __FUNCTION__, 0,
+            "Update keyword on hardware failed for file[" + i_fruPath +
+                "], reason: " + std::string(l_exception.what()),
+            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+
+        return constants::FAILURE;
+    }
+}
+
+types::DbusVariantType Manager::readKeyword(
+    const types::Path i_fruPath, const types::ReadVpdParams i_paramsToReadData)
+{
+    try
+    {
+        nlohmann::json l_jsonObj{};
+
+        if (m_worker.get() != nullptr)
+        {
+            l_jsonObj = m_worker->getSysCfgJsonObj();
+        }
+
+        std::error_code ec;
+
+        // Check if given path is filesystem path
+        if (!std::filesystem::exists(i_fruPath, ec) && (ec))
+        {
+            throw std::runtime_error(
+                "Given file path " + i_fruPath + " not found.");
+        }
+
+        logging::logMessage("Performing VPD read on " + i_fruPath);
+
+        std::shared_ptr<vpd::Parser> l_parserObj =
+            std::make_shared<vpd::Parser>(i_fruPath, l_jsonObj);
+
+        std::shared_ptr<vpd::ParserInterface> l_vpdParserInstance =
+            l_parserObj->getVpdParserInstance();
+
+        return (
+            l_vpdParserInstance->readKeywordFromHardware(i_paramsToReadData));
+    }
+    catch (const std::exception& e)
+    {
+        logging::logMessage(
+            e.what() + std::string(". VPD manager read operation failed for ") +
+            i_fruPath);
+        throw types::DeviceError::ReadFailure();
+    }
+}
+
+void Manager::collectSingleFruVpd(
+    const sdbusplus::message::object_path& i_dbusObjPath)
+{
+    try
+    {
+        if (m_vpdCollectionStatus != "Completed")
+        {
+            throw std::runtime_error(
+                "Currently VPD CollectionStatus is not completed. Cannot perform single FRU VPD collection for " +
+                std::string(i_dbusObjPath));
+        }
+
+        // Get system config JSON object from worker class
+        nlohmann::json l_sysCfgJsonObj{};
+
+        if (m_worker.get() != nullptr)
+        {
+            l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
+        }
+
+        // Check if system config JSON is present
+        if (l_sysCfgJsonObj.empty())
+        {
+            throw std::runtime_error(
+                "System config JSON object not present. Single FRU VPD collection failed for " +
+                std::string(i_dbusObjPath));
+        }
+
+        // Get FRU path for the given D-bus object path from JSON
+        const std::string& l_fruPath =
+            jsonUtility::getFruPathFromJson(l_sysCfgJsonObj, i_dbusObjPath);
+
+        if (l_fruPath.empty())
+        {
+            throw std::runtime_error(
+                "D-bus object path not present in JSON. Single FRU VPD collection failed for " +
+                std::string(i_dbusObjPath));
+        }
+
+        // Check if host is up and running
+        if (dbusUtility::isHostRunning())
+        {
+            if (!jsonUtility::isFruReplaceableAtRuntime(l_sysCfgJsonObj,
+                                                        l_fruPath))
+            {
+                throw std::runtime_error(
+                    "Given FRU is not replaceable at host runtime. Single FRU VPD collection failed for " +
+                    std::string(i_dbusObjPath));
+            }
+        }
+        else if (dbusUtility::isBMCReady())
+        {
+            if (!jsonUtility::isFruReplaceableAtStandby(l_sysCfgJsonObj,
+                                                        l_fruPath) &&
+                (!jsonUtility::isFruReplaceableAtRuntime(l_sysCfgJsonObj,
+                                                         l_fruPath)))
+            {
+                throw std::runtime_error(
+                    "Given FRU is neither replaceable at standby nor replaceable at runtime. Single FRU VPD collection failed for " +
+                    std::string(i_dbusObjPath));
+            }
+        }
+
+        // Parse VPD
+        types::VPDMapVariant l_parsedVpd = m_worker->parseVpdFile(l_fruPath);
+
+        // If l_parsedVpd is pointing to std::monostate
+        if (l_parsedVpd.index() == 0)
+        {
+            throw std::runtime_error(
+                "VPD parsing failed for " + std::string(i_dbusObjPath));
+        }
+
+        // Get D-bus object map from worker class
+        types::ObjectMap l_dbusObjectMap;
+        m_worker->populateDbus(l_parsedVpd, l_dbusObjectMap, l_fruPath);
+
+        if (l_dbusObjectMap.empty())
+        {
+            throw std::runtime_error(
+                "Failed to create D-bus object map. Single FRU VPD collection failed for " +
+                std::string(i_dbusObjPath));
+        }
+
+        // Call PIM's Notify method
+        if (!dbusUtility::callPIM(move(l_dbusObjectMap)))
+        {
+            throw std::runtime_error(
+                "Notify PIM failed. Single FRU VPD collection failed for " +
+                std::string(i_dbusObjPath));
+        }
+    }
+    catch (const std::exception& l_error)
+    {
+        // TODO: Log PEL
+        logging::logMessage(std::string(l_error.what()));
+    }
+}
+
+void Manager::deleteSingleFruVpd(
+    const sdbusplus::message::object_path& i_dbusObjPath)
+{
+    try
+    {
+        if (std::string(i_dbusObjPath).empty())
+        {
+            throw std::runtime_error(
+                "Given DBus object path is empty. Aborting FRU VPD deletion.");
+        }
+
+        if (m_worker.get() == nullptr)
+        {
+            throw std::runtime_error(
+                "Worker object not found, can't perform FRU VPD deletion for: " +
+                std::string(i_dbusObjPath));
+        }
+
+        m_worker->deleteFruVpd(std::string(i_dbusObjPath));
+    }
+    catch (const std::exception& l_ex)
+    {
+        // TODO: Log PEL
+        logging::logMessage(l_ex.what());
+    }
+}
+
+bool Manager::isValidUnexpandedLocationCode(
+    const std::string& i_unexpandedLocationCode)
+{
+    if ((i_unexpandedLocationCode.length() <
+         constants::UNEXP_LOCATION_CODE_MIN_LENGTH) ||
+        ((i_unexpandedLocationCode.compare(0, 4, "Ufcs") !=
+          constants::STR_CMP_SUCCESS) &&
+         (i_unexpandedLocationCode.compare(0, 4, "Umts") !=
+          constants::STR_CMP_SUCCESS)) ||
+        ((i_unexpandedLocationCode.length() >
+          constants::UNEXP_LOCATION_CODE_MIN_LENGTH) &&
+         (i_unexpandedLocationCode.find("-") != 4)))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+std::string Manager::getExpandedLocationCode(
+    const std::string& i_unexpandedLocationCode,
+    [[maybe_unused]] const uint16_t i_nodeNumber)
+{
+    if (!isValidUnexpandedLocationCode(i_unexpandedLocationCode))
+    {
+        phosphor::logging::elog<types::DbusInvalidArgument>(
+            types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
+            types::InvalidArgument::ARGUMENT_VALUE(
+                i_unexpandedLocationCode.c_str()));
+    }
+
+    const nlohmann::json& l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
+    if (!l_sysCfgJsonObj.contains("frus"))
+    {
+        logging::logMessage("Missing frus tag in system config JSON");
+    }
+
+    const nlohmann::json& l_listOfFrus =
+        l_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+    for (const auto& l_frus : l_listOfFrus.items())
+    {
+        for (const auto& l_aFru : l_frus.value())
+        {
+            if (l_aFru["extraInterfaces"].contains(
+                    constants::locationCodeInf) &&
+                l_aFru["extraInterfaces"][constants::locationCodeInf].value(
+                    "LocationCode", "") == i_unexpandedLocationCode)
+            {
+                return std::get<std::string>(dbusUtility::readDbusProperty(
+                    l_aFru["serviceName"], l_aFru["inventoryPath"],
+                    constants::locationCodeInf, "LocationCode"));
+            }
+        }
+    }
+    phosphor::logging::elog<types::DbusInvalidArgument>(
+        types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
+        types::InvalidArgument::ARGUMENT_VALUE(
+            i_unexpandedLocationCode.c_str()));
+}
+
+types::ListOfPaths Manager::getFrusByUnexpandedLocationCode(
+    const std::string& i_unexpandedLocationCode,
+    [[maybe_unused]] const uint16_t i_nodeNumber)
+{
+    types::ListOfPaths l_inventoryPaths;
+
+    if (!isValidUnexpandedLocationCode(i_unexpandedLocationCode))
+    {
+        phosphor::logging::elog<types::DbusInvalidArgument>(
+            types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
+            types::InvalidArgument::ARGUMENT_VALUE(
+                i_unexpandedLocationCode.c_str()));
+    }
+
+    const nlohmann::json& l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
+    if (!l_sysCfgJsonObj.contains("frus"))
+    {
+        logging::logMessage("Missing frus tag in system config JSON");
+    }
+
+    const nlohmann::json& l_listOfFrus =
+        l_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+    for (const auto& l_frus : l_listOfFrus.items())
+    {
+        for (const auto& l_aFru : l_frus.value())
+        {
+            if (l_aFru["extraInterfaces"].contains(
+                    constants::locationCodeInf) &&
+                l_aFru["extraInterfaces"][constants::locationCodeInf].value(
+                    "LocationCode", "") == i_unexpandedLocationCode)
+            {
+                l_inventoryPaths.push_back(
+                    l_aFru.at("inventoryPath")
+                        .get_ref<const nlohmann::json::string_t&>());
+            }
+        }
+    }
+
+    if (l_inventoryPaths.empty())
+    {
+        phosphor::logging::elog<types::DbusInvalidArgument>(
+            types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
+            types::InvalidArgument::ARGUMENT_VALUE(
+                i_unexpandedLocationCode.c_str()));
+    }
+
+    return l_inventoryPaths;
+}
+
+std::string
+    Manager::getHwPath(const sdbusplus::message::object_path& i_dbusObjPath)
+{
+    // Dummy code to supress unused variable warning. To be removed.
+    logging::logMessage(std::string(i_dbusObjPath));
+
+    return std::string{};
+}
+
+std::tuple<std::string, uint16_t> Manager::getUnexpandedLocationCode(
+    const std::string& i_expandedLocationCode)
+{
+    /**
+     * Location code should always start with U and fulfil minimum length
+     * criteria.
+     */
+    if (i_expandedLocationCode[0] != 'U' ||
+        i_expandedLocationCode.length() <
+            constants::EXP_LOCATION_CODE_MIN_LENGTH)
+    {
+        phosphor::logging::elog<types::DbusInvalidArgument>(
+            types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
+            types::InvalidArgument::ARGUMENT_VALUE(
+                i_expandedLocationCode.c_str()));
+    }
+
+    std::string l_fcKwd;
+
+    auto l_fcKwdValue = dbusUtility::readDbusProperty(
+        "xyz.openbmc_project.Inventory.Manager",
+        "/xyz/openbmc_project/inventory/system/chassis/motherboard",
+        "com.ibm.ipzvpd.VCEN", "FC");
+
+    if (auto l_kwdValue = std::get_if<types::BinaryVector>(&l_fcKwdValue))
+    {
+        l_fcKwd.assign(l_kwdValue->begin(), l_kwdValue->end());
+    }
+
+    // Get the first part of expanded location code to check for FC or TM.
+    std::string l_firstKwd = i_expandedLocationCode.substr(1, 4);
+
+    std::string l_unexpandedLocationCode{};
+    uint16_t l_nodeNummber = constants::INVALID_NODE_NUMBER;
+
+    // Check if this value matches the value of FC keyword.
+    if (l_fcKwd.substr(0, 4) == l_firstKwd)
+    {
+        /**
+         * Period(.) should be there in expanded location code to seggregate
+         * FC, node number and SE values.
+         */
+        size_t l_nodeStartPos = i_expandedLocationCode.find('.');
+        if (l_nodeStartPos == std::string::npos)
+        {
+            phosphor::logging::elog<types::DbusInvalidArgument>(
+                types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
+                types::InvalidArgument::ARGUMENT_VALUE(
+                    i_expandedLocationCode.c_str()));
+        }
+
+        size_t l_nodeEndPos =
+            i_expandedLocationCode.find('.', l_nodeStartPos + 1);
+        if (l_nodeEndPos == std::string::npos)
+        {
+            phosphor::logging::elog<types::DbusInvalidArgument>(
+                types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
+                types::InvalidArgument::ARGUMENT_VALUE(
+                    i_expandedLocationCode.c_str()));
+        }
+
+        // Skip 3 bytes for '.ND'
+        l_nodeNummber = std::stoi(i_expandedLocationCode.substr(
+            l_nodeStartPos + 3, (l_nodeEndPos - l_nodeStartPos - 3)));
+
+        /**
+         * Confirm if there are other details apart FC, node number and SE
+         * in location code
+         */
+        if (i_expandedLocationCode.length() >
+            constants::EXP_LOCATION_CODE_MIN_LENGTH)
+        {
+            l_unexpandedLocationCode =
+                i_expandedLocationCode[0] + std::string("fcs") +
+                i_expandedLocationCode.substr(
+                    l_nodeEndPos + 1 + constants::SE_KWD_LENGTH,
+                    std::string::npos);
+        }
+        else
+        {
+            l_unexpandedLocationCode = "Ufcs";
+        }
+    }
+    else
+    {
+        std::string l_tmKwd;
+        // Read TM keyword value.
+        auto l_tmKwdValue = dbusUtility::readDbusProperty(
+            "xyz.openbmc_project.Inventory.Manager",
+            "/xyz/openbmc_project/inventory/system/chassis/motherboard",
+            "com.ibm.ipzvpd.VSYS", "TM");
+
+        if (auto l_kwdValue = std::get_if<types::BinaryVector>(&l_tmKwdValue))
+        {
+            l_tmKwd.assign(l_kwdValue->begin(), l_kwdValue->end());
+        }
+
+        // Check if the substr matches to TM keyword value.
+        if (l_tmKwd.substr(0, 4) == l_firstKwd)
+        {
+            /**
+             * System location code will not have node number and any other
+             * details.
+             */
+            l_unexpandedLocationCode = "Umts";
+        }
+        // The given location code is neither "fcs" or "mts".
+        else
+        {
+            phosphor::logging::elog<types::DbusInvalidArgument>(
+                types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
+                types::InvalidArgument::ARGUMENT_VALUE(
+                    i_expandedLocationCode.c_str()));
+        }
+    }
+
+    return std::make_tuple(l_unexpandedLocationCode, l_nodeNummber);
+}
+
+types::ListOfPaths Manager::getFrusByExpandedLocationCode(
+    const std::string& i_expandedLocationCode)
+{
+    std::tuple<std::string, uint16_t> l_locationAndNodePair =
+        getUnexpandedLocationCode(i_expandedLocationCode);
+
+    return getFrusByUnexpandedLocationCode(std::get<0>(l_locationAndNodePair),
+                                           std::get<1>(l_locationAndNodePair));
+}
+
+void Manager::registerHostStateChangeCallback()
+{
+    static std::shared_ptr<sdbusplus::bus::match_t> l_hostState =
+        std::make_shared<sdbusplus::bus::match_t>(
+            *m_asioConnection,
+            sdbusplus::bus::match::rules::propertiesChanged(
+                constants::hostObjectPath, constants::hostInterface),
+            [this](sdbusplus::message_t& i_msg) {
+                hostStateChangeCallBack(i_msg);
+            });
+}
+
+void Manager::hostStateChangeCallBack(sdbusplus::message_t& i_msg)
+{
+    try
+    {
+        if (i_msg.is_method_error())
+        {
+            throw std::runtime_error(
+                "Error reading callback message for host state");
+        }
+
+        std::string l_objectPath;
+        types::PropertyMap l_propMap;
+        i_msg.read(l_objectPath, l_propMap);
+
+        const auto l_itr = l_propMap.find("CurrentHostState");
+
+        if (l_itr == l_propMap.end())
+        {
+            throw std::runtime_error(
+                "CurrentHostState field is missing in callback message");
+        }
+
+        if (auto l_hostState = std::get_if<std::string>(&(l_itr->second)))
+        {
+            // implies system is moving from standby to power on state
+            if (*l_hostState == "xyz.openbmc_project.State.Host.HostState."
+                                "TransitioningToRunning")
+            {
+                // TODO: check for all the essential FRUs in the system.
+
+                // Perform recollection.
+                performVpdRecollection();
+                return;
+            }
+        }
+        else
+        {
+            throw std::runtime_error(
+                "Invalid type recieved in variant for host state.");
+        }
+    }
+    catch (const std::exception& l_ex)
+    {
+        // TODO: Log PEL.
+        logging::logMessage(l_ex.what());
+    }
+}
+
+void Manager::performVpdRecollection()
+{
+    try
+    {
+        if (m_worker.get() != nullptr)
+        {
+            nlohmann::json l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
+
+            // Check if system config JSON is present
+            if (l_sysCfgJsonObj.empty())
+            {
+                throw std::runtime_error(
+                    "System config json object is empty, can't process recollection.");
+            }
+
+            const auto& l_frusReplaceableAtStandby =
+                jsonUtility::getListOfFrusReplaceableAtStandby(l_sysCfgJsonObj);
+
+            for (const auto& l_fruInventoryPath : l_frusReplaceableAtStandby)
+            {
+                // ToDo: Add some logic/trace to know the flow to
+                // collectSingleFruVpd has been directed via
+                // performVpdRecollection.
+                collectSingleFruVpd(l_fruInventoryPath);
+            }
+            return;
+        }
+
+        throw std::runtime_error(
+            "Worker object not found can't process recollection");
+    }
+    catch (const std::exception& l_ex)
+    {
+        // TODO Log PEL
+        logging::logMessage(
+            "VPD recollection failed with error: " + std::string(l_ex.what()));
+    }
+}
+} // namespace vpd
diff --git a/vpd-manager/src/manager_main.cpp b/vpd-manager/src/manager_main.cpp
new file mode 100644
index 0000000..a1d61e4
--- /dev/null
+++ b/vpd-manager/src/manager_main.cpp
@@ -0,0 +1,94 @@
+#include "config.h"
+
+#include "bios_handler.hpp"
+#include "event_logger.hpp"
+#include "exceptions.hpp"
+#include "logger.hpp"
+#include "manager.hpp"
+#include "types.hpp"
+
+#include <sdbusplus/asio/connection.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+
+#include <iostream>
+
+/**
+ * @brief Main function for VPD parser application.
+ */
+int main(int, char**)
+{
+    try
+    {
+        auto io_con = std::make_shared<boost::asio::io_context>();
+        auto connection =
+            std::make_shared<sdbusplus::asio::connection>(*io_con);
+        auto server = sdbusplus::asio::object_server(connection);
+
+        std::shared_ptr<sdbusplus::asio::dbus_interface> interface =
+            server.add_interface(OBJPATH, IFACE);
+
+        auto vpdManager =
+            std::make_shared<vpd::Manager>(io_con, interface, connection);
+
+        // TODO: Take this under conditional compilation for IBM
+        auto biosHandler =
+            std::make_shared<vpd::BiosHandler<vpd::IbmBiosHandler>>(
+                connection, vpdManager);
+
+        interface->initialize();
+
+        vpd::logging::logMessage("Start VPD-Manager event loop");
+
+        // Grab the bus name
+        connection->request_name(BUSNAME);
+
+        // Start event loop.
+        io_con->run();
+
+        exit(EXIT_SUCCESS);
+    }
+    catch (const std::exception& l_ex)
+    {
+        if (typeid(l_ex) == typeid(vpd::JsonException))
+        {
+            // ToDo: Severity needs to be revisited.
+            vpd::EventLogger::createAsyncPel(
+                vpd::types::ErrorType::JsonFailure,
+                vpd::types::SeverityType::Informational, __FILE__, __FUNCTION__,
+                0,
+                std::string("VPD Manager service failed with : ") + l_ex.what(),
+                std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+        }
+        else if (typeid(l_ex) == typeid(vpd::GpioException))
+        {
+            // ToDo: Severity needs to be revisited.
+            vpd::EventLogger::createAsyncPel(
+                vpd::types::ErrorType::GpioError,
+                vpd::types::SeverityType::Informational, __FILE__, __FUNCTION__,
+                0,
+                std::string("VPD Manager service failed with : ") + l_ex.what(),
+                std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+        }
+        else if (typeid(l_ex) == typeid(sdbusplus::exception::SdBusError))
+        {
+            // ToDo: Severity needs to be revisited.
+            vpd::EventLogger::createAsyncPel(
+                vpd::types::ErrorType::DbusFailure,
+                vpd::types::SeverityType::Informational, __FILE__, __FUNCTION__,
+                0,
+                std::string("VPD Manager service failed with : ") + l_ex.what(),
+                std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+        }
+        else
+        {
+            // ToDo: Severity needs to be revisited.
+            vpd::EventLogger::createAsyncPel(
+                vpd::types::ErrorType::InvalidVpdMessage,
+                vpd::types::SeverityType::Informational, __FILE__, __FUNCTION__,
+                0,
+                std::string("VPD Manager service failed with : ") + l_ex.what(),
+                "BMC0001", std::nullopt, std::nullopt, std::nullopt);
+        }
+    }
+    exit(EXIT_FAILURE);
+}
diff --git a/vpd-manager/src/parser.cpp b/vpd-manager/src/parser.cpp
new file mode 100644
index 0000000..d6266cb
--- /dev/null
+++ b/vpd-manager/src/parser.cpp
@@ -0,0 +1,342 @@
+#include "parser.hpp"
+
+#include "constants.hpp"
+#include "event_logger.hpp"
+
+#include <utility/dbus_utility.hpp>
+#include <utility/json_utility.hpp>
+#include <utility/vpd_specific_utility.hpp>
+
+#include <fstream>
+
+namespace vpd
+{
+Parser::Parser(const std::string& vpdFilePath, nlohmann::json parsedJson) :
+    m_vpdFilePath(vpdFilePath), m_parsedJson(parsedJson)
+{
+    std::error_code l_errCode;
+
+    // ToDo: Add minimum file size check in all the concert praser classes,
+    // depends on their VPD type.
+    if (!std::filesystem::exists(m_vpdFilePath, l_errCode))
+    {
+        std::string l_message{"Parser object creation failed, file [" +
+                              m_vpdFilePath + "] doesn't exists."};
+
+        if (l_errCode)
+        {
+            l_message += " Error message: " + l_errCode.message();
+        }
+
+        throw std::runtime_error(l_message);
+    }
+
+    // Read VPD offset if applicable.
+    if (!m_parsedJson.empty())
+    {
+        m_vpdStartOffset = jsonUtility::getVPDOffset(m_parsedJson, vpdFilePath);
+    }
+}
+
+std::shared_ptr<vpd::ParserInterface> Parser::getVpdParserInstance()
+{
+    // Read the VPD data into a vector.
+    vpdSpecificUtility::getVpdDataInVector(m_vpdFilePath, m_vpdVector,
+                                           m_vpdStartOffset);
+
+    // This will detect the type of parser required.
+    std::shared_ptr<vpd::ParserInterface> l_parser =
+        ParserFactory::getParser(m_vpdVector, m_vpdFilePath, m_vpdStartOffset);
+
+    return l_parser;
+}
+
+types::VPDMapVariant Parser::parse()
+{
+    std::shared_ptr<vpd::ParserInterface> l_parser = getVpdParserInstance();
+    return l_parser->parse();
+}
+
+int Parser::updateVpdKeyword(const types::WriteVpdParams& i_paramsToWriteData)
+{
+    int l_bytesUpdatedOnHardware = constants::FAILURE;
+
+    // A lambda to extract Record : Keyword string from i_paramsToWriteData
+    auto l_keyWordIdentifier =
+        [](const types::WriteVpdParams& i_paramsToWriteData) -> std::string {
+        std::string l_keywordString{};
+        if (const types::IpzData* l_ipzData =
+                std::get_if<types::IpzData>(&i_paramsToWriteData))
+        {
+            l_keywordString =
+                std::get<0>(*l_ipzData) + ":" + std::get<1>(*l_ipzData);
+        }
+        else if (const types::KwData* l_kwData =
+                     std::get_if<types::KwData>(&i_paramsToWriteData))
+        {
+            l_keywordString = std::get<0>(*l_kwData);
+        }
+        return l_keywordString;
+    };
+
+    try
+    {
+        // Enable Reboot Guard
+        if (constants::FAILURE == dbusUtility::EnableRebootGuard())
+        {
+            EventLogger::createAsyncPel(
+                types::ErrorType::DbusFailure,
+                types::SeverityType::Informational, __FILE__, __FUNCTION__, 0,
+                std::string(
+                    "Failed to enable BMC Reboot Guard while updating " +
+                    l_keyWordIdentifier(i_paramsToWriteData)),
+                std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+
+            return constants::FAILURE;
+        }
+
+        // Update keyword's value on hardware
+        try
+        {
+            std::shared_ptr<ParserInterface> l_vpdParserInstance =
+                getVpdParserInstance();
+            l_bytesUpdatedOnHardware =
+                l_vpdParserInstance->writeKeywordOnHardware(
+                    i_paramsToWriteData);
+        }
+        catch (const std::exception& l_exception)
+        {
+            std::string l_errMsg(
+                "Error while updating keyword's value on hardware path " +
+                m_vpdFilePath + ", error: " + std::string(l_exception.what()));
+
+            // TODO : Log PEL
+
+            throw std::runtime_error(l_errMsg);
+        }
+
+        auto [l_fruPath, l_inventoryObjPath, l_redundantFruPath] =
+            jsonUtility::getAllPathsToUpdateKeyword(m_parsedJson,
+                                                    m_vpdFilePath);
+
+        // If inventory D-bus object path is present, update keyword's value on
+        // DBus
+        if (!l_inventoryObjPath.empty())
+        {
+            types::Record l_recordName;
+            std::string l_interfaceName;
+            std::string l_propertyName;
+            types::DbusVariantType l_keywordValue;
+
+            if (const types::IpzData* l_ipzData =
+                    std::get_if<types::IpzData>(&i_paramsToWriteData))
+            {
+                l_recordName = std::get<0>(*l_ipzData);
+                l_interfaceName = constants::ipzVpdInf + l_recordName;
+                l_propertyName = std::get<1>(*l_ipzData);
+
+                try
+                {
+                    // Read keyword's value from hardware to write the same on
+                    // D-bus.
+                    std::shared_ptr<ParserInterface> l_vpdParserInstance =
+                        getVpdParserInstance();
+
+                    logging::logMessage(
+                        "Performing VPD read on " + m_vpdFilePath);
+
+                    l_keywordValue =
+                        l_vpdParserInstance->readKeywordFromHardware(
+                            types::ReadVpdParams(
+                                std::make_tuple(l_recordName, l_propertyName)));
+                }
+                catch (const std::exception& l_exception)
+                {
+                    // Unable to read keyword's value from hardware.
+                    std::string l_errMsg(
+                        "Error while reading keyword's value from hadware path " +
+                        m_vpdFilePath +
+                        ", error: " + std::string(l_exception.what()));
+
+                    // TODO: Log PEL
+
+                    throw std::runtime_error(l_errMsg);
+                }
+            }
+            else
+            {
+                // Input parameter type provided isn't compatible to perform
+                // update.
+                std::string l_errMsg(
+                    "Input parameter type isn't compatible to update keyword's value on DBus for object path: " +
+                    l_inventoryObjPath);
+                throw std::runtime_error(l_errMsg);
+            }
+
+            // Get D-bus name for the given keyword
+            l_propertyName =
+                vpdSpecificUtility::getDbusPropNameForGivenKw(l_propertyName);
+
+            // Create D-bus object map
+            types::ObjectMap l_dbusObjMap = {std::make_pair(
+                l_inventoryObjPath,
+                types::InterfaceMap{std::make_pair(
+                    l_interfaceName, types::PropertyMap{std::make_pair(
+                                         l_propertyName, l_keywordValue)})})};
+
+            // Call PIM's Notify method to perform update
+            if (!dbusUtility::callPIM(std::move(l_dbusObjMap)))
+            {
+                // Call to PIM's Notify method failed.
+                std::string l_errMsg("Notify PIM is failed for object path: " +
+                                     l_inventoryObjPath);
+                throw std::runtime_error(l_errMsg);
+            }
+        }
+
+        // Update keyword's value on redundant hardware if present
+        if (!l_redundantFruPath.empty())
+        {
+            if (updateVpdKeywordOnRedundantPath(l_redundantFruPath,
+                                                i_paramsToWriteData) < 0)
+            {
+                std::string l_errMsg(
+                    "Error while updating keyword's value on redundant path " +
+                    l_redundantFruPath);
+                throw std::runtime_error(l_errMsg);
+            }
+        }
+
+        // TODO: Check if revert is required when any of the writes fails.
+        // TODO: Handle error logging
+    }
+    catch (const std::exception& l_ex)
+    {
+        logging::logMessage("Update VPD Keyword failed for : " +
+                            l_keyWordIdentifier(i_paramsToWriteData) +
+                            " failed due to error: " + l_ex.what());
+
+        // update failed, set return value to failure
+        l_bytesUpdatedOnHardware = constants::FAILURE;
+    }
+
+    // Disable Reboot Guard
+    if (constants::FAILURE == dbusUtility::DisableRebootGuard())
+    {
+        EventLogger::createAsyncPel(
+            types::ErrorType::DbusFailure, types::SeverityType::Critical,
+            __FILE__, __FUNCTION__, 0,
+            std::string("Failed to disable BMC Reboot Guard while updating " +
+                        l_keyWordIdentifier(i_paramsToWriteData)),
+            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+    }
+
+    return l_bytesUpdatedOnHardware;
+}
+
+int Parser::updateVpdKeywordOnRedundantPath(
+    const std::string& i_fruPath,
+    const types::WriteVpdParams& i_paramsToWriteData)
+{
+    try
+    {
+        std::shared_ptr<Parser> l_parserObj =
+            std::make_shared<Parser>(i_fruPath, m_parsedJson);
+
+        std::shared_ptr<ParserInterface> l_vpdParserInstance =
+            l_parserObj->getVpdParserInstance();
+
+        return l_vpdParserInstance->writeKeywordOnHardware(i_paramsToWriteData);
+    }
+    catch (const std::exception& l_exception)
+    {
+        EventLogger::createSyncPel(
+            types::ErrorType::InvalidVpdMessage,
+            types::SeverityType::Informational, __FILE__, __FUNCTION__, 0,
+            "Error while updating keyword's value on redundant path " +
+                i_fruPath + ", error: " + std::string(l_exception.what()),
+            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+        return -1;
+    }
+}
+
+int Parser::updateVpdKeywordOnHardware(
+    const types::WriteVpdParams& i_paramsToWriteData)
+{
+    int l_bytesUpdatedOnHardware = constants::FAILURE;
+
+    // A lambda to extract Record : Keyword string from i_paramsToWriteData
+    auto l_keyWordIdentifier =
+        [](const types::WriteVpdParams& i_paramsToWriteData) -> std::string {
+        std::string l_keywordString{};
+        if (const types::IpzData* l_ipzData =
+                std::get_if<types::IpzData>(&i_paramsToWriteData))
+        {
+            l_keywordString =
+                std::get<0>(*l_ipzData) + ":" + std::get<1>(*l_ipzData);
+        }
+        else if (const types::KwData* l_kwData =
+                     std::get_if<types::KwData>(&i_paramsToWriteData))
+        {
+            l_keywordString = std::get<0>(*l_kwData);
+        }
+        return l_keywordString;
+    };
+
+    try
+    {
+        // Enable Reboot Guard
+        if (constants::FAILURE == dbusUtility::EnableRebootGuard())
+        {
+            EventLogger::createAsyncPel(
+                types::ErrorType::DbusFailure,
+                types::SeverityType::Informational, __FILE__, __FUNCTION__, 0,
+                std::string(
+                    "Failed to enable BMC Reboot Guard while updating " +
+                    l_keyWordIdentifier(i_paramsToWriteData)),
+                std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+
+            return constants::FAILURE;
+        }
+
+        std::shared_ptr<ParserInterface> l_vpdParserInstance =
+            getVpdParserInstance();
+        l_bytesUpdatedOnHardware =
+            l_vpdParserInstance->writeKeywordOnHardware(i_paramsToWriteData);
+    }
+    catch (const std::exception& l_exception)
+    {
+        types::ErrorType l_errorType;
+
+        if (typeid(l_exception) == typeid(EccException))
+        {
+            l_errorType = types::ErrorType::EccCheckFailed;
+        }
+        else
+        {
+            l_errorType = types::ErrorType::InvalidVpdMessage;
+        }
+
+        EventLogger::createAsyncPel(
+            l_errorType, types::SeverityType::Informational, __FILE__,
+            __FUNCTION__, 0,
+            "Error while updating keyword's value on hardware path [" +
+                m_vpdFilePath + "], error: " + std::string(l_exception.what()),
+            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+    }
+
+    // Disable Reboot Guard
+    if (constants::FAILURE == dbusUtility::DisableRebootGuard())
+    {
+        EventLogger::createAsyncPel(
+            types::ErrorType::DbusFailure, types::SeverityType::Critical,
+            __FILE__, __FUNCTION__, 0,
+            std::string("Failed to disable BMC Reboot Guard while updating " +
+                        l_keyWordIdentifier(i_paramsToWriteData)),
+            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+    }
+
+    return l_bytesUpdatedOnHardware;
+}
+
+} // namespace vpd
diff --git a/vpd-manager/src/parser_factory.cpp b/vpd-manager/src/parser_factory.cpp
new file mode 100644
index 0000000..546e67b
--- /dev/null
+++ b/vpd-manager/src/parser_factory.cpp
@@ -0,0 +1,140 @@
+#include "parser_factory.hpp"
+
+#include "constants.hpp"
+#include "ddimm_parser.hpp"
+#include "exceptions.hpp"
+#include "ipz_parser.hpp"
+#include "isdimm_parser.hpp"
+#include "keyword_vpd_parser.hpp"
+
+namespace vpd
+{
+
+/**
+ * @brief Type of VPD formats.
+ */
+enum vpdType
+{
+    IPZ_VPD,                /**< IPZ VPD type */
+    KEYWORD_VPD,            /**< Keyword VPD type */
+    DDR4_DDIMM_MEMORY_VPD,  /**< DDR4 DDIMM Memory VPD type */
+    DDR5_DDIMM_MEMORY_VPD,  /**< DDR5 DDIMM Memory VPD type */
+    DDR4_ISDIMM_MEMORY_VPD, /**< DDR4 ISDIMM Memory VPD type */
+    DDR5_ISDIMM_MEMORY_VPD, /**< DDR5 ISDIMM Memory VPD type */
+    INVALID_VPD_FORMAT      /**< Invalid VPD type */
+};
+
+/**
+ * @brief API to get the type of VPD.
+ *
+ * @param[in] i_vpdVector - VPD file content
+ *
+ * @return Type of VPD data, "INVALID_VPD_FORMAT" in case of unknown type.
+ */
+static vpdType vpdTypeCheck(const types::BinaryVector& i_vpdVector)
+{
+    if (i_vpdVector[constants::IPZ_DATA_START] == constants::IPZ_DATA_START_TAG)
+    {
+        return vpdType::IPZ_VPD;
+    }
+    else if (i_vpdVector[constants::KW_VPD_DATA_START] ==
+             constants::KW_VPD_START_TAG)
+    {
+        return vpdType::KEYWORD_VPD;
+    }
+    else if (((i_vpdVector[constants::SPD_BYTE_3] &
+               constants::SPD_BYTE_BIT_0_3_MASK) ==
+              constants::SPD_MODULE_TYPE_DDIMM))
+    {
+        std::string l_is11SFormat;
+        if (i_vpdVector.size() > (constants::DDIMM_11S_BARCODE_START +
+                                  constants::DDIMM_11S_BARCODE_LEN))
+        {
+            // Read first 3 Bytes to check the 11S bar code format
+            for (uint8_t l_index = 0; l_index < constants::DDIMM_11S_FORMAT_LEN;
+                 l_index++)
+            {
+                l_is11SFormat +=
+                    i_vpdVector[constants::DDIMM_11S_BARCODE_START + l_index];
+            }
+        }
+
+        if (l_is11SFormat.compare(constants::DDIMM_11S_BARCODE_START_TAG) == 0)
+        {
+            // DDIMM memory VPD format
+            if ((i_vpdVector[constants::SPD_BYTE_2] &
+                 constants::SPD_BYTE_MASK) == constants::SPD_DRAM_TYPE_DDR5)
+            {
+                return vpdType::DDR5_DDIMM_MEMORY_VPD;
+            }
+
+            if ((i_vpdVector[constants::SPD_BYTE_2] &
+                 constants::SPD_BYTE_MASK) == constants::SPD_DRAM_TYPE_DDR4)
+            {
+                return vpdType::DDR4_DDIMM_MEMORY_VPD;
+            }
+        }
+
+        logging::logMessage("11S format is not found in the DDIMM VPD.");
+        return vpdType::INVALID_VPD_FORMAT;
+    }
+    else if ((i_vpdVector[constants::SPD_BYTE_2] & constants::SPD_BYTE_MASK) ==
+             constants::SPD_DRAM_TYPE_DDR5)
+    {
+        // ISDIMM memory VPD format
+        return vpdType::DDR5_ISDIMM_MEMORY_VPD;
+    }
+    else if ((i_vpdVector[constants::SPD_BYTE_2] & constants::SPD_BYTE_MASK) ==
+             constants::SPD_DRAM_TYPE_DDR4)
+    {
+        // ISDIMM memory VPD format
+        return vpdType::DDR4_ISDIMM_MEMORY_VPD;
+    }
+
+    return vpdType::INVALID_VPD_FORMAT;
+}
+
+std::shared_ptr<ParserInterface> ParserFactory::getParser(
+    const types::BinaryVector& i_vpdVector, const std::string& i_vpdFilePath,
+    size_t i_vpdStartOffset)
+{
+    if (i_vpdVector.empty())
+    {
+        throw std::runtime_error("Empty VPD vector passed to parser factory");
+    }
+
+    vpdType l_type = vpdTypeCheck(i_vpdVector);
+
+    switch (l_type)
+    {
+        case vpdType::IPZ_VPD:
+        {
+            return std::make_shared<IpzVpdParser>(i_vpdVector, i_vpdFilePath,
+                                                  i_vpdStartOffset);
+        }
+
+        case vpdType::KEYWORD_VPD:
+        {
+            return std::make_shared<KeywordVpdParser>(i_vpdVector);
+        }
+
+        case vpdType::DDR5_DDIMM_MEMORY_VPD:
+        case vpdType::DDR4_DDIMM_MEMORY_VPD:
+        {
+            return std::make_shared<DdimmVpdParser>(i_vpdVector);
+        }
+
+        case vpdType::DDR4_ISDIMM_MEMORY_VPD:
+        case vpdType::DDR5_ISDIMM_MEMORY_VPD:
+        {
+            // return shared pointer to class object.
+            logging::logMessage(
+                "ISDIMM parser selected for VPD path: " + i_vpdFilePath);
+            return std::make_shared<JedecSpdParser>(i_vpdVector);
+        }
+
+        default:
+            throw DataException("Unable to determine VPD format");
+    }
+}
+} // namespace vpd
diff --git a/vpd-manager/src/vpd_parser_main.cpp b/vpd-manager/src/vpd_parser_main.cpp
new file mode 100644
index 0000000..0c434d8
--- /dev/null
+++ b/vpd-manager/src/vpd_parser_main.cpp
@@ -0,0 +1,101 @@
+#include "logger.hpp"
+#include "parser.hpp"
+#include "parser_interface.hpp"
+#include "types.hpp"
+#include "worker.hpp"
+
+#include <CLI/CLI.hpp>
+#include <nlohmann/json.hpp>
+#include <parser_factory.hpp>
+
+#include <filesystem>
+#include <iostream>
+
+/**
+ * @brief This file implements a generic parser APP.
+ *
+ * It recieves path of the VPD file(mandatory) and path to a config
+ * file(optional) as arguments. It will parse the data and return parsed data in
+ * a required format.
+ *
+ * Steps to get parsed VPD.
+ * - Pass VPD file path and config file (if applicable).
+ * - Read VPD file to vector.
+ * - Pass that to parser_factory to get the parser and call parse API on that
+ * parser object to get the Parsed VPD map.
+ * - If VPD format is other than the existing formats. Follow the steps
+ * - a) Add logic in parser_factory.cpp, vpdTypeCheck API to detect the format.
+ * - b) Implement a custom parser class.
+ * - c) Override parse API in the newly added parser class.
+ * - d) Add type of parsed data returned by parse API into types.hpp,
+ * "VPDMapVariant".
+ *
+ */
+
+int main(int argc, char** argv)
+{
+    try
+    {
+        std::string vpdFilePath{};
+        CLI::App app{"VPD-parser-app - APP to parse VPD. "};
+
+        app.add_option("-f, --file", vpdFilePath, "VPD file path")->required();
+
+        std::string configFilePath{};
+
+        app.add_option("-c,--config", configFilePath, "Path to JSON config");
+
+        CLI11_PARSE(app, argc, argv);
+
+        vpd::logging::logMessage("VPD file path recieved" + vpdFilePath);
+
+        // VPD file path is a mandatory parameter to execute any parser.
+        if (vpdFilePath.empty())
+        {
+            throw std::runtime_error("Empty VPD file path");
+        }
+
+        nlohmann::json json;
+        vpd::types::VPDMapVariant parsedVpdDataMap;
+
+        // Below are two different ways of parsing the VPD.
+        if (!configFilePath.empty())
+        {
+            vpd::logging::logMessage(
+                "Processing with config file - " + configFilePath);
+
+            std::shared_ptr<vpd::Worker> objWorker =
+                std::make_shared<vpd::Worker>(configFilePath);
+            parsedVpdDataMap = objWorker->parseVpdFile(vpdFilePath);
+
+            // Based on requirement, call appropriate public API of worker class
+            /*If required to publish the FRU data on Dbus*/
+            // objWorker->publishFruDataOnDbus(parsedVpdDataMap);
+        }
+        else
+        {
+            // Will work with empty JSON
+            std::shared_ptr<vpd::Parser> vpdParser =
+                std::make_shared<vpd::Parser>(vpdFilePath, json);
+            parsedVpdDataMap = vpdParser->parse();
+        }
+
+        // If custom handling is required then custom logic to be implemented
+        // based on the type of variant,
+        //  eg: for IPZ VPD format
+        if (auto ipzVpdMap =
+                std::get_if<vpd::types::IPZVpdMap>(&parsedVpdDataMap))
+        {
+            // get rid of unused variable warning/error
+            (void)ipzVpdMap;
+            // implement code that needs to handle parsed IPZ VPD.
+        }
+    }
+    catch (const std::exception& ex)
+    {
+        vpd::logging::logMessage(ex.what());
+        return -1;
+    }
+
+    return 0;
+}
diff --git a/vpd-manager/src/worker.cpp b/vpd-manager/src/worker.cpp
new file mode 100644
index 0000000..2cf8cb5
--- /dev/null
+++ b/vpd-manager/src/worker.cpp
@@ -0,0 +1,1677 @@
+#include "config.h"
+
+#include "worker.hpp"
+
+#include "backup_restore.hpp"
+#include "configuration.hpp"
+#include "constants.hpp"
+#include "event_logger.hpp"
+#include "exceptions.hpp"
+#include "logger.hpp"
+#include "parser.hpp"
+#include "parser_factory.hpp"
+#include "parser_interface.hpp"
+
+#include <utility/dbus_utility.hpp>
+#include <utility/json_utility.hpp>
+#include <utility/vpd_specific_utility.hpp>
+
+#include <filesystem>
+#include <fstream>
+#include <future>
+#include <typeindex>
+#include <unordered_set>
+
+namespace vpd
+{
+
+Worker::Worker(std::string pathToConfigJson) :
+    m_configJsonPath(pathToConfigJson)
+{
+    // Implies the processing is based on some config JSON
+    if (!m_configJsonPath.empty())
+    {
+        // Check if symlink is already there to confirm fresh boot/factory
+        // reset.
+        if (std::filesystem::exists(INVENTORY_JSON_SYM_LINK))
+        {
+            logging::logMessage("Sym Link already present");
+            m_configJsonPath = INVENTORY_JSON_SYM_LINK;
+            m_isSymlinkPresent = true;
+        }
+
+        try
+        {
+            m_parsedJson = jsonUtility::getParsedJson(m_configJsonPath);
+
+            // check for mandatory fields at this point itself.
+            if (!m_parsedJson.contains("frus"))
+            {
+                throw std::runtime_error("Mandatory tag(s) missing from JSON");
+            }
+        }
+        catch (const std::exception& ex)
+        {
+            throw(JsonException(ex.what(), m_configJsonPath));
+        }
+    }
+    else
+    {
+        logging::logMessage("Processing in not based on any config JSON");
+    }
+}
+
+void Worker::enableMuxChips()
+{
+    if (m_parsedJson.empty())
+    {
+        // config JSON should not be empty at this point of execution.
+        throw std::runtime_error("Config JSON is empty. Can't enable muxes");
+        return;
+    }
+
+    if (!m_parsedJson.contains("muxes"))
+    {
+        logging::logMessage("No mux defined for the system in config JSON");
+        return;
+    }
+
+    // iterate over each MUX detail and enable them.
+    for (const auto& item : m_parsedJson["muxes"])
+    {
+        if (item.contains("holdidlepath"))
+        {
+            std::string cmd = "echo 0 > ";
+            cmd += item["holdidlepath"];
+
+            logging::logMessage("Enabling mux with command = " + cmd);
+
+            commonUtility::executeCmd(cmd);
+            continue;
+        }
+
+        logging::logMessage(
+            "Mux Entry does not have hold idle path. Can't enable the mux");
+    }
+}
+
+#ifdef IBM_SYSTEM
+void Worker::primeSystemBlueprint()
+{
+    if (m_parsedJson.empty())
+    {
+        return;
+    }
+
+    const nlohmann::json& l_listOfFrus =
+        m_parsedJson["frus"].get_ref<const nlohmann::json::object_t&>();
+
+    for (const auto& l_itemFRUS : l_listOfFrus.items())
+    {
+        const std::string& l_vpdFilePath = l_itemFRUS.key();
+
+        if (l_vpdFilePath == SYSTEM_VPD_FILE_PATH)
+        {
+            continue;
+        }
+
+        // Prime the inventry for FRUs which
+        // are not present/processing had some error.
+        if (!primeInventory(l_vpdFilePath))
+        {
+            logging::logMessage(
+                "Priming of inventory failed for FRU " + l_vpdFilePath);
+        }
+    }
+}
+
+void Worker::performInitialSetup()
+{
+    try
+    {
+        if (!dbusUtility::isChassisPowerOn())
+        {
+            logging::logMessage("Chassis is in Off state.");
+            setDeviceTreeAndJson();
+            primeSystemBlueprint();
+        }
+
+        // Enable all mux which are used for connecting to the i2c on the
+        // pcie slots for pcie cards. These are not enabled by kernel due to
+        // an issue seen with Castello cards, where the i2c line hangs on a
+        // probe.
+        enableMuxChips();
+
+        // Nothing needs to be done. Service restarted or BMC re-booted for
+        // some reason at system power on.
+        return;
+    }
+    catch (const std::exception& ex)
+    {
+        if (typeid(ex) == std::type_index(typeid(DataException)))
+        {
+            // TODO:Catch logic to be implemented once PEL code goes in.
+        }
+        else if (typeid(ex) == std::type_index(typeid(EccException)))
+        {
+            // TODO:Catch logic to be implemented once PEL code goes in.
+        }
+        else if (typeid(ex) == std::type_index(typeid(JsonException)))
+        {
+            // TODO:Catch logic to be implemented once PEL code goes in.
+        }
+
+        logging::logMessage(ex.what());
+        throw;
+    }
+}
+#endif
+
+static std::string readFitConfigValue()
+{
+    std::vector<std::string> output =
+        commonUtility::executeCmd("/sbin/fw_printenv");
+    std::string fitConfigValue;
+
+    for (const auto& entry : output)
+    {
+        auto pos = entry.find("=");
+        auto key = entry.substr(0, pos);
+        if (key != "fitconfig")
+        {
+            continue;
+        }
+
+        if (pos + 1 < entry.size())
+        {
+            fitConfigValue = entry.substr(pos + 1);
+        }
+    }
+
+    return fitConfigValue;
+}
+
+bool Worker::isSystemVPDOnDBus() const
+{
+    const std::string& mboardPath =
+        m_parsedJson["frus"][SYSTEM_VPD_FILE_PATH].at(0).value(
+            "inventoryPath", "");
+
+    if (mboardPath.empty())
+    {
+        throw JsonException("System vpd file path missing in JSON",
+                            INVENTORY_JSON_SYM_LINK);
+    }
+
+    std::array<const char*, 1> interfaces = {
+        "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
+
+    const types::MapperGetObject& objectMap =
+        dbusUtility::getObjectMap(mboardPath, interfaces);
+
+    if (objectMap.empty())
+    {
+        return false;
+    }
+    return true;
+}
+
+std::string Worker::getIMValue(const types::IPZVpdMap& parsedVpd) const
+{
+    if (parsedVpd.empty())
+    {
+        throw std::runtime_error("Empty VPD map. Can't Extract IM value");
+    }
+
+    const auto& itrToVSBP = parsedVpd.find("VSBP");
+    if (itrToVSBP == parsedVpd.end())
+    {
+        throw DataException("VSBP record missing.");
+    }
+
+    const auto& itrToIM = (itrToVSBP->second).find("IM");
+    if (itrToIM == (itrToVSBP->second).end())
+    {
+        throw DataException("IM keyword missing.");
+    }
+
+    types::BinaryVector imVal;
+    std::copy(itrToIM->second.begin(), itrToIM->second.end(),
+              back_inserter(imVal));
+
+    std::ostringstream imData;
+    for (auto& aByte : imVal)
+    {
+        imData << std::setw(2) << std::setfill('0') << std::hex
+               << static_cast<int>(aByte);
+    }
+
+    return imData.str();
+}
+
+std::string Worker::getHWVersion(const types::IPZVpdMap& parsedVpd) const
+{
+    if (parsedVpd.empty())
+    {
+        throw std::runtime_error("Empty VPD map. Can't Extract HW value");
+    }
+
+    const auto& itrToVINI = parsedVpd.find("VINI");
+    if (itrToVINI == parsedVpd.end())
+    {
+        throw DataException("VINI record missing.");
+    }
+
+    const auto& itrToHW = (itrToVINI->second).find("HW");
+    if (itrToHW == (itrToVINI->second).end())
+    {
+        throw DataException("HW keyword missing.");
+    }
+
+    types::BinaryVector hwVal;
+    std::copy(itrToHW->second.begin(), itrToHW->second.end(),
+              back_inserter(hwVal));
+
+    // The planar pass only comes from the LSB of the HW keyword,
+    // where as the MSB is used for other purposes such as signifying clock
+    // termination.
+    hwVal[0] = 0x00;
+
+    std::ostringstream hwString;
+    for (auto& aByte : hwVal)
+    {
+        hwString << std::setw(2) << std::setfill('0') << std::hex
+                 << static_cast<int>(aByte);
+    }
+
+    return hwString.str();
+}
+
+void Worker::fillVPDMap(const std::string& vpdFilePath,
+                        types::VPDMapVariant& vpdMap)
+{
+    logging::logMessage(std::string("Parsing file = ") + vpdFilePath);
+
+    if (vpdFilePath.empty())
+    {
+        throw std::runtime_error("Invalid file path passed to fillVPDMap API.");
+    }
+
+    if (!std::filesystem::exists(vpdFilePath))
+    {
+        throw std::runtime_error("Can't Find physical file");
+    }
+
+    try
+    {
+        std::shared_ptr<Parser> vpdParser =
+            std::make_shared<Parser>(vpdFilePath, m_parsedJson);
+        vpdMap = vpdParser->parse();
+    }
+    catch (const std::exception& ex)
+    {
+        if (typeid(ex) == std::type_index(typeid(DataException)))
+        {
+            // TODO: Do what needs to be done in case of Data exception.
+            // Uncomment when PEL implementation goes in.
+            /* string errorMsg =
+                 "VPD file is either empty or invalid. Parser failed for [";
+             errorMsg += m_vpdFilePath;
+             errorMsg += "], with error = " + std::string(ex.what());
+
+             additionalData.emplace("DESCRIPTION", errorMsg);
+             additionalData.emplace("CALLOUT_INVENTORY_PATH",
+                                    INVENTORY_PATH + baseFruInventoryPath);
+             createPEL(additionalData, pelSeverity, errIntfForInvalidVPD,
+             nullptr);*/
+
+            // throw generic error from here to inform main caller about
+            // failure.
+            logging::logMessage(ex.what());
+            throw std::runtime_error(
+                "Data Exception occurred for file path = " + vpdFilePath);
+        }
+
+        if (typeid(ex) == std::type_index(typeid(EccException)))
+        {
+            // TODO: Do what needs to be done in case of ECC exception.
+            // Uncomment when PEL implementation goes in.
+            /* additionalData.emplace("DESCRIPTION", "ECC check failed");
+             additionalData.emplace("CALLOUT_INVENTORY_PATH",
+                                    INVENTORY_PATH + baseFruInventoryPath);
+             createPEL(additionalData, pelSeverity, errIntfForEccCheckFail,
+                       nullptr);
+             */
+
+            logging::logMessage(ex.what());
+            // Need to decide once all error handling is implemented.
+            // vpdSpecificUtility::dumpBadVpd(vpdFilePath,vpdVector);
+
+            // throw generic error from here to inform main caller about
+            // failure.
+            throw std::runtime_error(
+                "Ecc Exception occurred for file path = " + vpdFilePath);
+        }
+    }
+}
+
+void Worker::getSystemJson(std::string& systemJson,
+                           const types::VPDMapVariant& parsedVpdMap)
+{
+    if (auto pVal = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
+    {
+        std::string hwKWdValue = getHWVersion(*pVal);
+        if (hwKWdValue.empty())
+        {
+            throw DataException("HW value fetched is empty.");
+        }
+
+        const std::string& imKwdValue = getIMValue(*pVal);
+        if (imKwdValue.empty())
+        {
+            throw DataException("IM value fetched is empty.");
+        }
+
+        auto itrToIM = config::systemType.find(imKwdValue);
+        if (itrToIM == config::systemType.end())
+        {
+            throw DataException("IM keyword does not map to any system type");
+        }
+
+        const types::HWVerList hwVersionList = itrToIM->second.second;
+        if (!hwVersionList.empty())
+        {
+            transform(hwKWdValue.begin(), hwKWdValue.end(), hwKWdValue.begin(),
+                      ::toupper);
+
+            auto itrToHW =
+                std::find_if(hwVersionList.begin(), hwVersionList.end(),
+                             [&hwKWdValue](const auto& aPair) {
+                                 return aPair.first == hwKWdValue;
+                             });
+
+            if (itrToHW != hwVersionList.end())
+            {
+                if (!(*itrToHW).second.empty())
+                {
+                    systemJson += (*itrToIM).first + "_" + (*itrToHW).second +
+                                  ".json";
+                }
+                else
+                {
+                    systemJson += (*itrToIM).first + ".json";
+                }
+                return;
+            }
+        }
+        systemJson += itrToIM->second.first + ".json";
+        return;
+    }
+
+    throw DataException("Invalid VPD type returned from Parser");
+}
+
+static void setEnvAndReboot(const std::string& key, const std::string& value)
+{
+    // set env and reboot and break.
+    commonUtility::executeCmd("/sbin/fw_setenv", key, value);
+    logging::logMessage("Rebooting BMC to pick up new device tree");
+
+    // make dbus call to reboot
+    auto bus = sdbusplus::bus::new_default_system();
+    auto method = bus.new_method_call(
+        "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
+        "org.freedesktop.systemd1.Manager", "Reboot");
+    bus.call_noreply(method);
+}
+
+void Worker::setJsonSymbolicLink(const std::string& i_systemJson)
+{
+    std::error_code l_ec;
+    l_ec.clear();
+    if (!std::filesystem::exists(VPD_SYMLIMK_PATH, l_ec))
+    {
+        if (l_ec)
+        {
+            throw std::runtime_error(
+                "File system call to exist failed with error = " +
+                l_ec.message());
+        }
+
+        // implies it is a fresh boot/factory reset.
+        // Create the directory for hosting the symlink
+        if (!std::filesystem::create_directories(VPD_SYMLIMK_PATH, l_ec))
+        {
+            if (l_ec)
+            {
+                throw std::runtime_error(
+                    "File system call to create directory failed with error = " +
+                    l_ec.message());
+            }
+        }
+    }
+
+    // create a new symlink based on the system
+    std::filesystem::create_symlink(i_systemJson, INVENTORY_JSON_SYM_LINK,
+                                    l_ec);
+
+    if (l_ec)
+    {
+        throw std::runtime_error(
+            "create_symlink system call failed with error: " + l_ec.message());
+    }
+
+    // If the flow is at this point implies the symlink was not present there.
+    // Considering this as factory reset.
+    m_isFactoryResetDone = true;
+}
+
+void Worker::setDeviceTreeAndJson()
+{
+    // JSON is madatory for processing of this API.
+    if (m_parsedJson.empty())
+    {
+        throw std::runtime_error("JSON is empty");
+    }
+
+    types::VPDMapVariant parsedVpdMap;
+    fillVPDMap(SYSTEM_VPD_FILE_PATH, parsedVpdMap);
+
+    // Implies it is default JSON.
+    std::string systemJson{JSON_ABSOLUTE_PATH_PREFIX};
+
+    // ToDo: Need to check if INVENTORY_JSON_SYM_LINK pointing to correct system
+    // This is required to support movement from rainier to Blue Ridge on the
+    // fly.
+
+    // Do we have the entry for device tree in parsed JSON?
+    if (m_parsedJson.find("devTree") == m_parsedJson.end())
+    {
+        getSystemJson(systemJson, parsedVpdMap);
+
+        if (!systemJson.compare(JSON_ABSOLUTE_PATH_PREFIX))
+        {
+            // TODO: Log a PEL saying that "System type not supported"
+            throw DataException("Error in getting system JSON.");
+        }
+
+        // re-parse the JSON once appropriate JSON has been selected.
+        try
+        {
+            m_parsedJson = jsonUtility::getParsedJson(systemJson);
+        }
+        catch (const nlohmann::json::parse_error& ex)
+        {
+            throw(JsonException("Json parsing failed", systemJson));
+        }
+    }
+
+    std::string devTreeFromJson;
+    if (m_parsedJson.contains("devTree"))
+    {
+        devTreeFromJson = m_parsedJson["devTree"];
+
+        if (devTreeFromJson.empty())
+        {
+            // TODO:: Log a predictive PEL
+            logging::logMessage(
+                "Mandatory value for device tree missing from JSON[" +
+                std::string(INVENTORY_JSON_SYM_LINK) + "]");
+        }
+    }
+
+    auto fitConfigVal = readFitConfigValue();
+
+    if (devTreeFromJson.empty() ||
+        fitConfigVal.find(devTreeFromJson) != std::string::npos)
+    { // Skipping setting device tree as either devtree info is missing from
+      // Json or it is rightly set.
+
+        // avoid setting symlink on every reboot.
+        if (!m_isSymlinkPresent)
+        {
+            setJsonSymbolicLink(systemJson);
+        }
+
+        if (isSystemVPDOnDBus() &&
+            jsonUtility::isBackupAndRestoreRequired(m_parsedJson))
+        {
+            performBackupAndRestore(parsedVpdMap);
+        }
+
+        // proceed to publish system VPD.
+        publishSystemVPD(parsedVpdMap);
+        return;
+    }
+
+    setEnvAndReboot("fitconfig", devTreeFromJson);
+    exit(EXIT_SUCCESS);
+}
+
+void Worker::populateIPZVPDpropertyMap(
+    types::InterfaceMap& interfacePropMap,
+    const types::IPZKwdValueMap& keyordValueMap,
+    const std::string& interfaceName)
+{
+    types::PropertyMap propertyValueMap;
+    for (const auto& kwdVal : keyordValueMap)
+    {
+        auto kwd = kwdVal.first;
+
+        if (kwd[0] == '#')
+        {
+            kwd = std::string("PD_") + kwd[1];
+        }
+        else if (isdigit(kwd[0]))
+        {
+            kwd = std::string("N_") + kwd;
+        }
+
+        types::BinaryVector value(kwdVal.second.begin(), kwdVal.second.end());
+        propertyValueMap.emplace(move(kwd), move(value));
+    }
+
+    if (!propertyValueMap.empty())
+    {
+        interfacePropMap.emplace(interfaceName, propertyValueMap);
+    }
+}
+
+void Worker::populateKwdVPDpropertyMap(const types::KeywordVpdMap& keyordVPDMap,
+                                       types::InterfaceMap& interfaceMap)
+{
+    for (const auto& kwdValMap : keyordVPDMap)
+    {
+        types::PropertyMap propertyValueMap;
+        auto kwd = kwdValMap.first;
+
+        if (kwd[0] == '#')
+        {
+            kwd = std::string("PD_") + kwd[1];
+        }
+        else if (isdigit(kwd[0]))
+        {
+            kwd = std::string("N_") + kwd;
+        }
+
+        if (auto keywordValue = get_if<types::BinaryVector>(&kwdValMap.second))
+        {
+            types::BinaryVector value((*keywordValue).begin(),
+                                      (*keywordValue).end());
+            propertyValueMap.emplace(move(kwd), move(value));
+        }
+        else if (auto keywordValue = get_if<std::string>(&kwdValMap.second))
+        {
+            types::BinaryVector value((*keywordValue).begin(),
+                                      (*keywordValue).end());
+            propertyValueMap.emplace(move(kwd), move(value));
+        }
+        else if (auto keywordValue = get_if<size_t>(&kwdValMap.second))
+        {
+            if (kwd == "MemorySizeInKB")
+            {
+                types::PropertyMap memProp;
+                memProp.emplace(move(kwd), ((*keywordValue)));
+                interfaceMap.emplace("xyz.openbmc_project.Inventory.Item.Dimm",
+                                     move(memProp));
+                continue;
+            }
+            else
+            {
+                logging::logMessage(
+                    "Unknown Keyword =" + kwd + " found in keyword VPD map");
+                continue;
+            }
+        }
+        else
+        {
+            logging::logMessage(
+                "Unknown variant type found in keyword VPD map.");
+            continue;
+        }
+
+        if (!propertyValueMap.empty())
+        {
+            vpdSpecificUtility::insertOrMerge(
+                interfaceMap, constants::kwdVpdInf, move(propertyValueMap));
+        }
+    }
+}
+
+void Worker::populateInterfaces(const nlohmann::json& interfaceJson,
+                                types::InterfaceMap& interfaceMap,
+                                const types::VPDMapVariant& parsedVpdMap)
+{
+    for (const auto& interfacesPropPair : interfaceJson.items())
+    {
+        const std::string& interface = interfacesPropPair.key();
+        types::PropertyMap propertyMap;
+
+        for (const auto& propValuePair : interfacesPropPair.value().items())
+        {
+            const std::string property = propValuePair.key();
+
+            if (propValuePair.value().is_boolean())
+            {
+                propertyMap.emplace(property,
+                                    propValuePair.value().get<bool>());
+            }
+            else if (propValuePair.value().is_string())
+            {
+                if (property.compare("LocationCode") == 0 &&
+                    interface.compare("com.ibm.ipzvpd.Location") == 0)
+                {
+                    std::string value =
+                        vpdSpecificUtility::getExpandedLocationCode(
+                            propValuePair.value().get<std::string>(),
+                            parsedVpdMap);
+                    propertyMap.emplace(property, value);
+
+                    auto l_locCodeProperty = propertyMap;
+                    vpdSpecificUtility::insertOrMerge(
+                        interfaceMap,
+                        std::string(constants::xyzLocationCodeInf),
+                        move(l_locCodeProperty));
+                }
+                else
+                {
+                    propertyMap.emplace(
+                        property, propValuePair.value().get<std::string>());
+                }
+            }
+            else if (propValuePair.value().is_array())
+            {
+                try
+                {
+                    propertyMap.emplace(
+                        property,
+                        propValuePair.value().get<types::BinaryVector>());
+                }
+                catch (const nlohmann::detail::type_error& e)
+                {
+                    std::cerr << "Type exception: " << e.what() << "\n";
+                }
+            }
+            else if (propValuePair.value().is_number())
+            {
+                // For now assume the value is a size_t.  In the future it would
+                // be nice to come up with a way to get the type from the JSON.
+                propertyMap.emplace(property,
+                                    propValuePair.value().get<size_t>());
+            }
+            else if (propValuePair.value().is_object())
+            {
+                const std::string& record =
+                    propValuePair.value().value("recordName", "");
+                const std::string& keyword =
+                    propValuePair.value().value("keywordName", "");
+                const std::string& encoding =
+                    propValuePair.value().value("encoding", "");
+
+                if (auto ipzVpdMap =
+                        std::get_if<types::IPZVpdMap>(&parsedVpdMap))
+                {
+                    if (!record.empty() && !keyword.empty() &&
+                        (*ipzVpdMap).count(record) &&
+                        (*ipzVpdMap).at(record).count(keyword))
+                    {
+                        auto encoded = vpdSpecificUtility::encodeKeyword(
+                            ((*ipzVpdMap).at(record).at(keyword)), encoding);
+                        propertyMap.emplace(property, encoded);
+                    }
+                }
+                else if (auto kwdVpdMap =
+                             std::get_if<types::KeywordVpdMap>(&parsedVpdMap))
+                {
+                    if (!keyword.empty() && (*kwdVpdMap).count(keyword))
+                    {
+                        if (auto kwValue = std::get_if<types::BinaryVector>(
+                                &(*kwdVpdMap).at(keyword)))
+                        {
+                            auto encodedValue =
+                                vpdSpecificUtility::encodeKeyword(
+                                    std::string((*kwValue).begin(),
+                                                (*kwValue).end()),
+                                    encoding);
+
+                            propertyMap.emplace(property, encodedValue);
+                        }
+                        else if (auto kwValue = std::get_if<std::string>(
+                                     &(*kwdVpdMap).at(keyword)))
+                        {
+                            auto encodedValue =
+                                vpdSpecificUtility::encodeKeyword(
+                                    std::string((*kwValue).begin(),
+                                                (*kwValue).end()),
+                                    encoding);
+
+                            propertyMap.emplace(property, encodedValue);
+                        }
+                        else if (auto uintValue = std::get_if<size_t>(
+                                     &(*kwdVpdMap).at(keyword)))
+                        {
+                            propertyMap.emplace(property, *uintValue);
+                        }
+                        else
+                        {
+                            logging::logMessage(
+                                "Unknown keyword found, Keywrod = " + keyword);
+                        }
+                    }
+                }
+            }
+        }
+        vpdSpecificUtility::insertOrMerge(interfaceMap, interface,
+                                          move(propertyMap));
+    }
+}
+
+bool Worker::isCPUIOGoodOnly(const std::string& i_pgKeyword)
+{
+    const unsigned char l_io[] = {
+        0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF,
+        0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF};
+
+    // EQ0 index (in PG keyword) starts at 97 (with offset starting from 0).
+    // Each EQ carries 3 bytes of data. Totally there are 8 EQs. If all EQs'
+    // value equals 0xE7F9FF, then the cpu has no good cores and its treated as
+    // IO.
+    if (memcmp(l_io, i_pgKeyword.data() + constants::INDEX_OF_EQ0_IN_PG,
+               constants::SIZE_OF_8EQ_IN_PG) == 0)
+    {
+        return true;
+    }
+
+    // The CPU is not an IO
+    return false;
+}
+
+bool Worker::primeInventory(const std::string& i_vpdFilePath)
+{
+    if (i_vpdFilePath.empty())
+    {
+        logging::logMessage("Empty VPD file path given");
+        return false;
+    }
+
+    if (m_parsedJson.empty())
+    {
+        logging::logMessage("Empty JSON detected for " + i_vpdFilePath);
+        return false;
+    }
+    else if (!m_parsedJson["frus"].contains(i_vpdFilePath))
+    {
+        logging::logMessage("File " + i_vpdFilePath +
+                            ", is not found in the system config JSON file.");
+        return false;
+    }
+
+    types::ObjectMap l_objectInterfaceMap;
+    for (const auto& l_Fru : m_parsedJson["frus"][i_vpdFilePath])
+    {
+        types::InterfaceMap l_interfaces;
+        sdbusplus::message::object_path l_fruObjectPath(l_Fru["inventoryPath"]);
+
+        if (l_Fru.contains("ccin"))
+        {
+            continue;
+        }
+
+        if (l_Fru.contains("noprime") && l_Fru.value("noprime", false))
+        {
+            continue;
+        }
+
+        // Clear data under PIM if already exists.
+        vpdSpecificUtility::resetDataUnderPIM(
+            std::string(l_Fru["inventoryPath"]), l_interfaces);
+
+        // Add extra interfaces mentioned in the Json config file
+        if (l_Fru.contains("extraInterfaces"))
+        {
+            populateInterfaces(l_Fru["extraInterfaces"], l_interfaces,
+                               std::monostate{});
+        }
+
+        types::PropertyMap l_propertyValueMap;
+        l_propertyValueMap.emplace("Present", false);
+        if (std::filesystem::exists(i_vpdFilePath))
+        {
+            l_propertyValueMap["Present"] = true;
+        }
+
+        vpdSpecificUtility::insertOrMerge(l_interfaces,
+                                          "xyz.openbmc_project.Inventory.Item",
+                                          move(l_propertyValueMap));
+
+        if (l_Fru.value("inherit", true) &&
+            m_parsedJson.contains("commonInterfaces"))
+        {
+            populateInterfaces(m_parsedJson["commonInterfaces"], l_interfaces,
+                               std::monostate{});
+        }
+
+        processFunctionalProperty(l_Fru["inventoryPath"], l_interfaces);
+        processEnabledProperty(l_Fru["inventoryPath"], l_interfaces);
+
+        l_objectInterfaceMap.emplace(std::move(l_fruObjectPath),
+                                     std::move(l_interfaces));
+    }
+
+    // Notify PIM
+    if (!dbusUtility::callPIM(move(l_objectInterfaceMap)))
+    {
+        logging::logMessage("Call to PIM failed for VPD file " + i_vpdFilePath);
+        return false;
+    }
+
+    return true;
+}
+
+void Worker::processEmbeddedAndSynthesizedFrus(const nlohmann::json& singleFru,
+                                               types::InterfaceMap& interfaces)
+{
+    // embedded property(true or false) says whether the subfru is embedded
+    // into the parent fru (or) not. VPD sets Present property only for
+    // embedded frus. If the subfru is not an embedded FRU, the subfru may
+    // or may not be physically present. Those non embedded frus will always
+    // have Present=false irrespective of its physical presence or absence.
+    // Eg: nvme drive in nvme slot is not an embedded FRU. So don't set
+    // Present to true for such sub frus.
+    // Eg: ethernet port is embedded into bmc card. So set Present to true
+    // for such sub frus. Also donot populate present property for embedded
+    // subfru which is synthesized. Currently there is no subfru which are
+    // both embedded and synthesized. But still the case is handled here.
+
+    // Check if its required to handle presence for this FRU.
+    if (singleFru.value("handlePresence", true))
+    {
+        types::PropertyMap presProp;
+        presProp.emplace("Present", true);
+        vpdSpecificUtility::insertOrMerge(
+            interfaces, "xyz.openbmc_project.Inventory.Item", move(presProp));
+    }
+}
+
+void Worker::processExtraInterfaces(const nlohmann::json& singleFru,
+                                    types::InterfaceMap& interfaces,
+                                    const types::VPDMapVariant& parsedVpdMap)
+{
+    populateInterfaces(singleFru["extraInterfaces"], interfaces, parsedVpdMap);
+    if (auto ipzVpdMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
+    {
+        if (singleFru["extraInterfaces"].contains(
+                "xyz.openbmc_project.Inventory.Item.Cpu"))
+        {
+            auto itrToRec = (*ipzVpdMap).find("CP00");
+            if (itrToRec == (*ipzVpdMap).end())
+            {
+                return;
+            }
+
+            std::string pgKeywordValue;
+            vpdSpecificUtility::getKwVal(itrToRec->second, "PG",
+                                         pgKeywordValue);
+            if (!pgKeywordValue.empty())
+            {
+                if (isCPUIOGoodOnly(pgKeywordValue))
+                {
+                    interfaces["xyz.openbmc_project.Inventory.Item"]
+                              ["PrettyName"] = "IO Module";
+                }
+            }
+        }
+    }
+}
+
+void Worker::processCopyRecordFlag(const nlohmann::json& singleFru,
+                                   const types::VPDMapVariant& parsedVpdMap,
+                                   types::InterfaceMap& interfaces)
+{
+    if (auto ipzVpdMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
+    {
+        for (const auto& record : singleFru["copyRecords"])
+        {
+            const std::string& recordName = record;
+            if ((*ipzVpdMap).find(recordName) != (*ipzVpdMap).end())
+            {
+                populateIPZVPDpropertyMap(interfaces,
+                                          (*ipzVpdMap).at(recordName),
+                                          constants::ipzVpdInf + recordName);
+            }
+        }
+    }
+}
+
+void Worker::processInheritFlag(const types::VPDMapVariant& parsedVpdMap,
+                                types::InterfaceMap& interfaces)
+{
+    if (auto ipzVpdMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
+    {
+        for (const auto& [recordName, kwdValueMap] : *ipzVpdMap)
+        {
+            populateIPZVPDpropertyMap(interfaces, kwdValueMap,
+                                      constants::ipzVpdInf + recordName);
+        }
+    }
+    else if (auto kwdVpdMap = std::get_if<types::KeywordVpdMap>(&parsedVpdMap))
+    {
+        populateKwdVPDpropertyMap(*kwdVpdMap, interfaces);
+    }
+
+    if (m_parsedJson.contains("commonInterfaces"))
+    {
+        populateInterfaces(m_parsedJson["commonInterfaces"], interfaces,
+                           parsedVpdMap);
+    }
+}
+
+bool Worker::processFruWithCCIN(const nlohmann::json& singleFru,
+                                const types::VPDMapVariant& parsedVpdMap)
+{
+    if (auto ipzVPDMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
+    {
+        auto itrToRec = (*ipzVPDMap).find("VINI");
+        if (itrToRec == (*ipzVPDMap).end())
+        {
+            return false;
+        }
+
+        std::string ccinFromVpd;
+        vpdSpecificUtility::getKwVal(itrToRec->second, "CC", ccinFromVpd);
+        if (ccinFromVpd.empty())
+        {
+            return false;
+        }
+
+        transform(ccinFromVpd.begin(), ccinFromVpd.end(), ccinFromVpd.begin(),
+                  ::toupper);
+
+        std::vector<std::string> ccinList;
+        for (std::string ccin : singleFru["ccin"])
+        {
+            transform(ccin.begin(), ccin.end(), ccin.begin(), ::toupper);
+            ccinList.push_back(ccin);
+        }
+
+        if (ccinList.empty())
+        {
+            return false;
+        }
+
+        if (find(ccinList.begin(), ccinList.end(), ccinFromVpd) ==
+            ccinList.end())
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+void Worker::processFunctionalProperty(const std::string& i_inventoryObjPath,
+                                       types::InterfaceMap& io_interfaces)
+{
+    if (!dbusUtility::isChassisPowerOn())
+    {
+        std::array<const char*, 1> l_operationalStatusInf = {
+            constants::operationalStatusInf};
+
+        auto mapperObjectMap = dbusUtility::getObjectMap(
+            i_inventoryObjPath, l_operationalStatusInf);
+
+        // If the object has been found. Check if it is under PIM.
+        if (mapperObjectMap.size() != 0)
+        {
+            for (const auto& [l_serviceName, l_interfaceLsit] : mapperObjectMap)
+            {
+                if (l_serviceName == constants::pimServiceName)
+                {
+                    // The object is already under PIM. No need to process
+                    // again. Retain the old value.
+                    return;
+                }
+            }
+        }
+
+        // Implies value is not there in D-Bus. Populate it with default
+        // value "true".
+        types::PropertyMap l_functionalProp;
+        l_functionalProp.emplace("Functional", true);
+        vpdSpecificUtility::insertOrMerge(io_interfaces,
+                                          constants::operationalStatusInf,
+                                          move(l_functionalProp));
+    }
+
+    // if chassis is power on. Functional property should be there on D-Bus.
+    // Don't process.
+    return;
+}
+
+void Worker::processEnabledProperty(const std::string& i_inventoryObjPath,
+                                    types::InterfaceMap& io_interfaces)
+{
+    if (!dbusUtility::isChassisPowerOn())
+    {
+        std::array<const char*, 1> l_enableInf = {constants::enableInf};
+
+        auto mapperObjectMap =
+            dbusUtility::getObjectMap(i_inventoryObjPath, l_enableInf);
+
+        // If the object has been found. Check if it is under PIM.
+        if (mapperObjectMap.size() != 0)
+        {
+            for (const auto& [l_serviceName, l_interfaceLsit] : mapperObjectMap)
+            {
+                if (l_serviceName == constants::pimServiceName)
+                {
+                    // The object is already under PIM. No need to process
+                    // again. Retain the old value.
+                    return;
+                }
+            }
+        }
+
+        // Implies value is not there in D-Bus. Populate it with default
+        // value "true".
+        types::PropertyMap l_enabledProp;
+        l_enabledProp.emplace("Enabled", true);
+        vpdSpecificUtility::insertOrMerge(io_interfaces, constants::enableInf,
+                                          move(l_enabledProp));
+    }
+
+    // if chassis is power on. Enabled property should be there on D-Bus.
+    // Don't process.
+    return;
+}
+
+void Worker::populateDbus(const types::VPDMapVariant& parsedVpdMap,
+                          types::ObjectMap& objectInterfaceMap,
+                          const std::string& vpdFilePath)
+{
+    if (vpdFilePath.empty())
+    {
+        throw std::runtime_error(
+            "Invalid parameter passed to populateDbus API.");
+    }
+
+    // JSON config is mandatory for processing of "if". Add "else" for any
+    // processing without config JSON.
+    if (!m_parsedJson.empty())
+    {
+        types::InterfaceMap interfaces;
+
+        for (const auto& aFru : m_parsedJson["frus"][vpdFilePath])
+        {
+            const auto& inventoryPath = aFru["inventoryPath"];
+            sdbusplus::message::object_path fruObjectPath(inventoryPath);
+            if (aFru.contains("ccin"))
+            {
+                if (!processFruWithCCIN(aFru, parsedVpdMap))
+                {
+                    continue;
+                }
+            }
+
+            if (aFru.value("inherit", true))
+            {
+                processInheritFlag(parsedVpdMap, interfaces);
+            }
+
+            // If specific record needs to be copied.
+            if (aFru.contains("copyRecords"))
+            {
+                processCopyRecordFlag(aFru, parsedVpdMap, interfaces);
+            }
+
+            if (aFru.contains("extraInterfaces"))
+            {
+                // Process extra interfaces w.r.t a FRU.
+                processExtraInterfaces(aFru, interfaces, parsedVpdMap);
+            }
+
+            // Process FRUS which are embedded in the parent FRU and whose VPD
+            // will be synthesized.
+            if ((aFru.value("embedded", true)) &&
+                (!aFru.value("synthesized", false)))
+            {
+                processEmbeddedAndSynthesizedFrus(aFru, interfaces);
+            }
+
+            processFunctionalProperty(inventoryPath, interfaces);
+            processEnabledProperty(inventoryPath, interfaces);
+
+            objectInterfaceMap.emplace(std::move(fruObjectPath),
+                                       std::move(interfaces));
+        }
+    }
+}
+
+std::string
+    Worker::createAssetTagString(const types::VPDMapVariant& i_parsedVpdMap)
+{
+    std::string l_assetTag;
+
+    // system VPD will be in IPZ format.
+    if (auto l_parsedVpdMap = std::get_if<types::IPZVpdMap>(&i_parsedVpdMap))
+    {
+        auto l_itrToVsys = (*l_parsedVpdMap).find(constants::recVSYS);
+        if (l_itrToVsys != (*l_parsedVpdMap).end())
+        {
+            std::string l_tmKwdValue;
+            vpdSpecificUtility::getKwVal(l_itrToVsys->second, constants::kwdTM,
+                                         l_tmKwdValue);
+
+            std::string l_seKwdValue;
+            vpdSpecificUtility::getKwVal(l_itrToVsys->second, constants::kwdSE,
+                                         l_seKwdValue);
+
+            l_assetTag = std::string{"Server-"} + l_tmKwdValue +
+                         std::string{"-"} + l_seKwdValue;
+        }
+        else
+        {
+            throw std::runtime_error(
+                "VSYS record not found in parsed VPD map to create Asset tag.");
+        }
+    }
+    else
+    {
+        throw std::runtime_error(
+            "Invalid VPD type recieved to create Asset tag.");
+    }
+
+    return l_assetTag;
+}
+
+void Worker::publishSystemVPD(const types::VPDMapVariant& parsedVpdMap)
+{
+    types::ObjectMap objectInterfaceMap;
+
+    if (std::get_if<types::IPZVpdMap>(&parsedVpdMap))
+    {
+        populateDbus(parsedVpdMap, objectInterfaceMap, SYSTEM_VPD_FILE_PATH);
+
+        try
+        {
+            if (m_isFactoryResetDone)
+            {
+                const auto& l_assetTag = createAssetTagString(parsedVpdMap);
+
+                auto l_itrToSystemPath = objectInterfaceMap.find(
+                    sdbusplus::message::object_path(constants::systemInvPath));
+                if (l_itrToSystemPath == objectInterfaceMap.end())
+                {
+                    throw std::runtime_error(
+                        "System Path not found in object map.");
+                }
+
+                types::PropertyMap l_assetTagProperty;
+                l_assetTagProperty.emplace("AssetTag", l_assetTag);
+
+                (l_itrToSystemPath->second)
+                    .emplace(constants::assetTagInf,
+                             std::move(l_assetTagProperty));
+            }
+        }
+        catch (const std::exception& l_ex)
+        {
+            EventLogger::createSyncPel(
+                types::ErrorType::InvalidVpdMessage,
+                types::SeverityType::Informational, __FILE__, __FUNCTION__, 0,
+                "Asset tag update failed with following error: " +
+                    std::string(l_ex.what()),
+                std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+        }
+
+        // Notify PIM
+        if (!dbusUtility::callPIM(move(objectInterfaceMap)))
+        {
+            throw std::runtime_error("Call to PIM failed for system VPD");
+        }
+    }
+    else
+    {
+        throw DataException("Invalid format of parsed VPD map.");
+    }
+}
+
+bool Worker::processPreAction(const std::string& i_vpdFilePath,
+                              const std::string& i_flagToProcess)
+{
+    if (i_vpdFilePath.empty() || i_flagToProcess.empty())
+    {
+        logging::logMessage(
+            "Invalid input parameter. Abort processing pre action");
+        return false;
+    }
+
+    if ((!jsonUtility::executeBaseAction(m_parsedJson, "preAction",
+                                         i_vpdFilePath, i_flagToProcess)) &&
+        (i_flagToProcess.compare("collection") == constants::STR_CMP_SUCCESS))
+    {
+        // TODO: Need a way to delete inventory object from Dbus and persisted
+        // data section in case any FRU is not present or there is any
+        // problem in collecting it. Once it has been deleted, it can be
+        // re-created in the flow of priming the inventory. This needs to be
+        // done either here or in the exception section of "parseAndPublishVPD"
+        // API. Any failure in the process of collecting FRU will land up in the
+        // excpetion of "parseAndPublishVPD".
+
+        // If the FRU is not there, clear the VINI/CCIN data.
+        // Enity manager probes for this keyword to look for this
+        // FRU, now if the data is persistent on BMC and FRU is
+        // removed this can lead to ambiguity. Hence clearing this
+        // Keyword if FRU is absent.
+        const auto& inventoryPath =
+            m_parsedJson["frus"][i_vpdFilePath].at(0).value("inventoryPath",
+                                                            "");
+
+        if (!inventoryPath.empty())
+        {
+            types::ObjectMap l_pimObjMap{
+                {inventoryPath,
+                 {{constants::kwdVpdInf,
+                   {{constants::kwdCCIN, types::BinaryVector{}}}}}}};
+
+            if (!dbusUtility::callPIM(std::move(l_pimObjMap)))
+            {
+                logging::logMessage(
+                    "Call to PIM failed for file " + i_vpdFilePath);
+            }
+        }
+        else
+        {
+            logging::logMessage(
+                "Inventory path is empty in Json for file " + i_vpdFilePath);
+        }
+
+        return false;
+    }
+    return true;
+}
+
+bool Worker::processPostAction(
+    const std::string& i_vpdFruPath, const std::string& i_flagToProcess,
+    const std::optional<types::VPDMapVariant> i_parsedVpd)
+{
+    if (i_vpdFruPath.empty() || i_flagToProcess.empty())
+    {
+        logging::logMessage(
+            "Invalid input parameter. Abort processing post action");
+        return false;
+    }
+
+    // Check if post action tag is to be triggered in the flow of collection
+    // based on some CCIN value?
+    if (m_parsedJson["frus"][i_vpdFruPath]
+            .at(0)["postAction"][i_flagToProcess]
+            .contains("ccin"))
+    {
+        if (!i_parsedVpd.has_value())
+        {
+            logging::logMessage("Empty VPD Map");
+            return false;
+        }
+
+        // CCIN match is required to process post action for this FRU as it
+        // contains the flag.
+        if (!vpdSpecificUtility::findCcinInVpd(
+                m_parsedJson["frus"][i_vpdFruPath].at(
+                    0)["postAction"]["collection"],
+                i_parsedVpd.value()))
+        {
+            // If CCIN is not found, implies post action processing is not
+            // required for this FRU. Let the flow continue.
+            return true;
+        }
+    }
+
+    if (!jsonUtility::executeBaseAction(m_parsedJson, "postAction",
+                                        i_vpdFruPath, i_flagToProcess))
+    {
+        logging::logMessage(
+            "Execution of post action failed for path: " + i_vpdFruPath);
+
+        // If post action was required and failed only in that case return
+        // false. In all other case post action is considered passed.
+        return false;
+    }
+
+    return true;
+}
+
+types::VPDMapVariant Worker::parseVpdFile(const std::string& i_vpdFilePath)
+{
+    if (i_vpdFilePath.empty())
+    {
+        throw std::runtime_error(
+            "Empty VPD file path passed to Worker::parseVpdFile. Abort processing");
+    }
+
+    try
+    {
+        if (jsonUtility::isActionRequired(m_parsedJson, i_vpdFilePath,
+                                          "preAction", "collection"))
+        {
+            if (!processPreAction(i_vpdFilePath, "collection"))
+            {
+                throw std::runtime_error("Pre-Action failed");
+            }
+        }
+
+        if (!std::filesystem::exists(i_vpdFilePath))
+        {
+            throw std::runtime_error(
+                "Could not find file path " + i_vpdFilePath +
+                "Skipping parser trigger for the EEPROM");
+        }
+
+        std::shared_ptr<Parser> vpdParser =
+            std::make_shared<Parser>(i_vpdFilePath, m_parsedJson);
+
+        types::VPDMapVariant l_parsedVpd = vpdParser->parse();
+
+        // Before returning, as collection is over, check if FRU qualifies for
+        // any post action in the flow of collection.
+        // Note: Don't change the order, post action needs to be processed only
+        // after collection for FRU is successfully done.
+        if (jsonUtility::isActionRequired(m_parsedJson, i_vpdFilePath,
+                                          "postAction", "collection"))
+        {
+            if (!processPostAction(i_vpdFilePath, "collection", l_parsedVpd))
+            {
+                // TODO: Log PEL
+                logging::logMessage("Required post action failed for path [" +
+                                    i_vpdFilePath + "]");
+            }
+        }
+
+        return l_parsedVpd;
+    }
+    catch (std::exception& l_ex)
+    {
+        // If post fail action is required, execute it.
+        if (jsonUtility::isActionRequired(m_parsedJson, i_vpdFilePath,
+                                          "PostFailAction", "collection"))
+        {
+            if (!jsonUtility::executePostFailAction(m_parsedJson, i_vpdFilePath,
+                                                    "collection"))
+            {
+                // TODO: Log PEL
+                throw std::runtime_error(
+                    "VPD parsing failed for " + i_vpdFilePath +
+                    " due to error: " + l_ex.what() +
+                    ". Post Fail Action also failed, aborting collection for this FRU");
+            }
+        }
+
+        // TODO: Log PEL
+        throw std::runtime_error("VPD parsing failed for " + i_vpdFilePath +
+                                 " due to error: " + l_ex.what());
+    }
+}
+
+std::tuple<bool, std::string>
+    Worker::parseAndPublishVPD(const std::string& i_vpdFilePath)
+{
+    try
+    {
+        m_semaphore.acquire();
+
+        // Thread launched.
+        m_mutex.lock();
+        m_activeCollectionThreadCount++;
+        m_mutex.unlock();
+
+        const types::VPDMapVariant& parsedVpdMap = parseVpdFile(i_vpdFilePath);
+
+        types::ObjectMap objectInterfaceMap;
+        populateDbus(parsedVpdMap, objectInterfaceMap, i_vpdFilePath);
+
+        // logging::logMessage("Dbus sucessfully populated for FRU " +
+        //                     i_vpdFilePath);
+
+        // Notify PIM
+        if (!dbusUtility::callPIM(move(objectInterfaceMap)))
+        {
+            throw std::runtime_error(
+                "Call to PIM failed while publishing VPD.");
+        }
+    }
+    catch (const std::exception& ex)
+    {
+        // handle all the exceptions internally. Return only true/false
+        // based on status of execution.
+        if (typeid(ex) == std::type_index(typeid(DataException)))
+        {
+            // TODO: Add custom handling
+            logging::logMessage(ex.what());
+        }
+        else if (typeid(ex) == std::type_index(typeid(EccException)))
+        {
+            // TODO: Add custom handling
+            logging::logMessage(ex.what());
+        }
+        else if (typeid(ex) == std::type_index(typeid(JsonException)))
+        {
+            // TODO: Add custom handling
+            logging::logMessage(ex.what());
+        }
+        else
+        {
+            logging::logMessage(ex.what());
+        }
+
+        // TODO: Figure out a way to clear data in case of any failure at
+        // runtime.
+        //  Prime the inventry for FRUs which
+        //  are not present/processing had some error.
+        /* if (!primeInventory(i_vpdFilePath))
+         {
+             logging::logMessage("Priming of inventory failed for FRU " +
+                                 i_vpdFilePath);
+         }*/
+        m_semaphore.release();
+        return std::make_tuple(false, i_vpdFilePath);
+    }
+    m_semaphore.release();
+    return std::make_tuple(true, i_vpdFilePath);
+}
+
+void Worker::collectFrusFromJson()
+{
+    // A parsed JSON file should be present to pick FRUs EEPROM paths
+    if (m_parsedJson.empty())
+    {
+        throw std::runtime_error(
+            "A config JSON is required for processing of FRUs");
+    }
+
+    const nlohmann::json& listOfFrus =
+        m_parsedJson["frus"].get_ref<const nlohmann::json::object_t&>();
+
+    for (const auto& itemFRUS : listOfFrus.items())
+    {
+        const std::string& vpdFilePath = itemFRUS.key();
+
+        // skip processing of system VPD again as it has been already collected.
+        // Also, if chassis is powered on, skip collecting FRUs which are
+        // powerOffOnly.
+        // TODO: Need to revisit for P-Future to reduce code update time.
+        if (vpdFilePath == SYSTEM_VPD_FILE_PATH ||
+            (jsonUtility::isFruPowerOffOnly(m_parsedJson, vpdFilePath) &&
+             dbusUtility::isChassisPowerOn()))
+        {
+            continue;
+        }
+
+        std::thread{[vpdFilePath, this]() {
+            auto l_futureObject =
+                std::async(&Worker::parseAndPublishVPD, this, vpdFilePath);
+
+            std::tuple<bool, std::string> l_threadInfo = l_futureObject.get();
+
+            // thread returned.
+            m_mutex.lock();
+            m_activeCollectionThreadCount--;
+            m_mutex.unlock();
+
+            if (!m_activeCollectionThreadCount)
+            {
+                m_isAllFruCollected = true;
+            }
+        }}.detach();
+    }
+}
+
+// ToDo: Move the API under IBM_SYSTEM
+void Worker::performBackupAndRestore(types::VPDMapVariant& io_srcVpdMap)
+{
+    try
+    {
+        std::string l_backupAndRestoreCfgFilePath =
+            m_parsedJson.value("backupRestoreConfigPath", "");
+
+        nlohmann::json l_backupAndRestoreCfgJsonObj =
+            jsonUtility::getParsedJson(l_backupAndRestoreCfgFilePath);
+
+        // check if either of "source" or "destination" has inventory path.
+        // this indicates that this sytem has System VPD on hardware
+        // and other copy on D-Bus (BMC cache).
+        if (!l_backupAndRestoreCfgJsonObj.empty() &&
+            ((l_backupAndRestoreCfgJsonObj.contains("source") &&
+              l_backupAndRestoreCfgJsonObj["source"].contains(
+                  "inventoryPath")) ||
+             (l_backupAndRestoreCfgJsonObj.contains("destination") &&
+              l_backupAndRestoreCfgJsonObj["destination"].contains(
+                  "inventoryPath"))))
+        {
+            BackupAndRestore l_backupAndRestoreObj(m_parsedJson);
+            auto [l_srcVpdVariant,
+                  l_dstVpdVariant] = l_backupAndRestoreObj.backupAndRestore();
+
+            // ToDo: Revisit is this check is required or not.
+            if (auto l_srcVpdMap =
+                    std::get_if<types::IPZVpdMap>(&l_srcVpdVariant);
+                l_srcVpdMap && !(*l_srcVpdMap).empty())
+            {
+                io_srcVpdMap = std::move(l_srcVpdVariant);
+            }
+        }
+    }
+    catch (const std::exception& l_ex)
+    {
+        EventLogger::createSyncPel(
+            types::ErrorType::InvalidVpdMessage,
+            types::SeverityType::Informational, __FILE__, __FUNCTION__, 0,
+            std::string(
+                "Exception caught while backup and restore VPD keyword's.") +
+                l_ex.what(),
+            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+    }
+}
+
+void Worker::deleteFruVpd(const std::string& i_dbusObjPath)
+{
+    if (i_dbusObjPath.empty())
+    {
+        throw std::runtime_error("Given DBus object path is empty.");
+    }
+
+    const std::string& l_fruPath =
+        jsonUtility::getFruPathFromJson(m_parsedJson, i_dbusObjPath);
+
+    try
+    {
+        auto l_presentPropValue = dbusUtility::readDbusProperty(
+            constants::pimServiceName, i_dbusObjPath,
+            constants::inventoryItemInf, "Present");
+
+        if (auto l_value = std::get_if<bool>(&l_presentPropValue))
+        {
+            if (!(*l_value))
+            {
+                throw std::runtime_error("Given FRU is not present");
+            }
+            else
+            {
+                if (jsonUtility::isActionRequired(m_parsedJson, l_fruPath,
+                                                  "preAction", "deletion"))
+                {
+                    if (!processPreAction(l_fruPath, "deletion"))
+                    {
+                        throw std::runtime_error("Pre action failed");
+                    }
+                }
+
+                std::vector<std::string> l_interfaceList{
+                    constants::operationalStatusInf};
+
+                types::MapperGetSubTree l_subTreeMap =
+                    dbusUtility::getObjectSubTree(i_dbusObjPath, 0,
+                                                  l_interfaceList);
+
+                types::ObjectMap l_objectMap;
+
+                // Updates VPD specific interfaces property value under PIM for
+                // sub FRUs.
+                for (const auto& [l_objectPath, l_serviceInterfaceMap] :
+                     l_subTreeMap)
+                {
+                    types::InterfaceMap l_interfaceMap;
+                    vpdSpecificUtility::resetDataUnderPIM(l_objectPath,
+                                                          l_interfaceMap);
+                    l_objectMap.emplace(l_objectPath,
+                                        std::move(l_interfaceMap));
+                }
+
+                types::InterfaceMap l_interfaceMap;
+                vpdSpecificUtility::resetDataUnderPIM(i_dbusObjPath,
+                                                      l_interfaceMap);
+
+                l_objectMap.emplace(i_dbusObjPath, std::move(l_interfaceMap));
+
+                if (!dbusUtility::callPIM(std::move(l_objectMap)))
+                {
+                    throw std::runtime_error("Call to PIM failed.");
+                }
+
+                if (jsonUtility::isActionRequired(m_parsedJson, l_fruPath,
+                                                  "postAction", "deletion"))
+                {
+                    if (!processPostAction(l_fruPath, "deletion"))
+                    {
+                        throw std::runtime_error("Post action failed");
+                    }
+                }
+            }
+        }
+        else
+        {
+            logging::logMessage(
+                "Can't process delete VPD for FRU [" + i_dbusObjPath +
+                "] as unable to read present property");
+            return;
+        }
+
+        logging::logMessage(
+            "Successfully completed deletion of FRU VPD for " + i_dbusObjPath);
+    }
+    catch (const std::exception& l_ex)
+    {
+        if (jsonUtility::isActionRequired(m_parsedJson, l_fruPath,
+                                          "postFailAction", "deletion"))
+        {
+            if (!jsonUtility::executePostFailAction(m_parsedJson, l_fruPath,
+                                                    "deletion"))
+            {
+                logging::logMessage(
+                    "Post fail action failed for: " + i_dbusObjPath);
+            }
+        }
+
+        logging::logMessage("Failed to delete VPD for FRU : " + i_dbusObjPath +
+                            " error: " + std::string(l_ex.what()));
+    }
+}
+} // namespace vpd
