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
