diff --git a/vpd-manager/include/utility/common_utility.hpp b/vpd-manager/include/utility/common_utility.hpp
new file mode 100644
index 0000000..15b33a2
--- /dev/null
+++ b/vpd-manager/include/utility/common_utility.hpp
@@ -0,0 +1,117 @@
+#pragma once
+
+#include "constants.hpp"
+#include "logger.hpp"
+
+#include <algorithm>
+#include <cstdio>
+#include <cstdlib>
+#include <vector>
+
+/**
+ * @brief Namespace to host common utility methods.
+ *
+ * A method qualifies as a common utility function if,
+ * A)It is being used by the utility namespace at the same level as well as
+ * other files directly.
+ * B) The utility should be a leaf node and should not be dependent on any other
+ * utility.
+ *                  *******************
+ *                  | Commmon Utility | - - - - - - -
+ *                  *******************              |
+ *                          /\                       |
+ *                         /  \                      |
+ *         ****************    ****************      |
+ *         | json utility |    | dbus utility |      |
+ *         ****************    ****************      |
+ *                 \                 /               |
+ *                  \               /                |
+ *               ************************            |
+ *               | Vpd specific Utility | - - - - - - -
+ *               ************************
+ */
+
+namespace vpd
+{
+
+namespace commonUtility
+{
+/** @brief Return the hex representation of the incoming byte.
+ *
+ * @param [in] i_aByte - The input byte.
+ * @returns Hex representation of the byte as a character.
+ */
+constexpr auto toHex(size_t i_aByte)
+{
+    constexpr auto l_map = "0123456789abcdef";
+    return l_map[i_aByte];
+}
+
+/**
+ * @brief API to return null at the end of variadic template args.
+ *
+ * @return empty string.
+ */
+inline std::string getCommand()
+{
+    return "";
+}
+
+/**
+ * @brief API to arrange create command.
+ *
+ * @param[in] arguments to create the command
+ * @return Command string
+ */
+template <typename T, typename... Types>
+inline std::string getCommand(T i_arg1, Types... i_args)
+{
+    std::string l_cmd = " " + i_arg1 + getCommand(i_args...);
+
+    return l_cmd;
+}
+
+/**
+ * @brief API to create shell command and execute.
+ *
+ * @throw std::runtime_error.
+ *
+ * @param[in] arguments for command
+ * @returns output of that command
+ */
+template <typename T, typename... Types>
+inline std::vector<std::string> executeCmd(T&& i_path, Types... i_args)
+{
+    std::vector<std::string> l_cmdOutput;
+    std::array<char, constants::CMD_BUFFER_LENGTH> l_buffer;
+
+    std::string l_cmd = i_path + getCommand(i_args...);
+
+    std::unique_ptr<FILE, decltype(&pclose)> l_cmdPipe(
+        popen(l_cmd.c_str(), "r"), pclose);
+
+    if (!l_cmdPipe)
+    {
+        logging::logMessage(
+            "popen failed with error " + std::string(strerror(errno)));
+        throw std::runtime_error("popen failed!");
+    }
+    while (fgets(l_buffer.data(), l_buffer.size(), l_cmdPipe.get()) != nullptr)
+    {
+        l_cmdOutput.emplace_back(l_buffer.data());
+    }
+
+    return l_cmdOutput;
+}
+
+/** @brief Converts string to lower case.
+ *
+ * @param [in] i_string - Input string.
+ */
+inline void toLower(std::string& i_string)
+{
+    std::transform(i_string.begin(), i_string.end(), i_string.begin(),
+                   [](unsigned char l_char) { return std::tolower(l_char); });
+}
+} // namespace commonUtility
+} // namespace vpd
diff --git a/vpd-manager/include/utility/dbus_utility.hpp b/vpd-manager/include/utility/dbus_utility.hpp
new file mode 100644
index 0000000..4c81815
--- /dev/null
+++ b/vpd-manager/include/utility/dbus_utility.hpp
@@ -0,0 +1,567 @@
+#pragma once
+
+#include "constants.hpp"
+#include "logger.hpp"
+#include "types.hpp"
+
+#include <chrono>
+
+namespace vpd
+{
+/**
+ * @brief The namespace defines utlity methods for generic D-Bus operations.
+ */
+namespace dbusUtility
+{
+
+/**
+ * @brief An API to get Map of service and interfaces for an object path.
+ *
+ * The API returns a Map of service name and interfaces for a given pair of
+ * object path and interface list. It can be used to determine service name
+ * which implemets a particular object path and interface.
+ *
+ * Note: It will be caller's responsibility to check for empty map returned and
+ * generate appropriate error.
+ *
+ * @param [in] objectPath - Object path under the service.
+ * @param [in] interfaces - Array of interface(s).
+ * @return - A Map of service name to object to interface(s), if success.
+ *           If failed,  empty map.
+ */
+inline types::MapperGetObject getObjectMap(const std::string& objectPath,
+                                           std::span<const char*> interfaces)
+{
+    types::MapperGetObject getObjectMap;
+
+    // interface list is optional argument, hence no check required.
+    if (objectPath.empty())
+    {
+        logging::logMessage("Path value is empty, invalid call to GetObject");
+        return getObjectMap;
+    }
+
+    try
+    {
+        auto bus = sdbusplus::bus::new_default();
+        auto method = bus.new_method_call(
+            "xyz.openbmc_project.ObjectMapper",
+            "/xyz/openbmc_project/object_mapper",
+            "xyz.openbmc_project.ObjectMapper", "GetObject");
+
+        method.append(objectPath, interfaces);
+        auto result = bus.call(method);
+        result.read(getObjectMap);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        // logging::logMessage(e.what());
+        return getObjectMap;
+    }
+
+    return getObjectMap;
+}
+
+/**
+ * @brief An API to get property map for an interface.
+ *
+ * This API returns a map of property and its value with respect to a particular
+ * interface.
+ *
+ * Note: It will be caller's responsibility to check for empty map returned and
+ * generate appropriate error.
+ *
+ * @param[in] i_service - Service name.
+ * @param[in] i_objectPath - object path.
+ * @param[in] i_interface - Interface, for the properties to be listed.
+ *
+ * @return - A map of property and value of an interface, if success.
+ *           if failed, empty map.
+ */
+inline types::PropertyMap getPropertyMap(const std::string& i_service,
+                                         const std::string& i_objectPath,
+                                         const std::string& i_interface)
+{
+    types::PropertyMap l_propertyValueMap;
+    if (i_service.empty() || i_objectPath.empty() || i_interface.empty())
+    {
+        logging::logMessage("Invalid parameters to get property map");
+        return l_propertyValueMap;
+    }
+
+    try
+    {
+        auto l_bus = sdbusplus::bus::new_default();
+        auto l_method =
+            l_bus.new_method_call(i_service.c_str(), i_objectPath.c_str(),
+                                  "org.freedesktop.DBus.Properties", "GetAll");
+        l_method.append(i_interface);
+        auto l_result = l_bus.call(l_method);
+        l_result.read(l_propertyValueMap);
+    }
+    catch (const sdbusplus::exception::SdBusError& l_ex)
+    {
+        logging::logMessage(l_ex.what());
+    }
+
+    return l_propertyValueMap;
+}
+
+/**
+ * @brief API to get object subtree from D-bus.
+ *
+ * The API returns the map of object, services and interfaces in the
+ * subtree that implement a certain interface. If no interfaces are provided
+ * then all the objects, services and interfaces under the subtree will
+ * be returned.
+ *
+ * Note: Depth can be 0 and interfaces can be null.
+ * It will be caller's responsibility to check for empty vector returned
+ * and generate appropriate error.
+ *
+ * @param[in] i_objectPath - Path to search for an interface.
+ * @param[in] i_depth - Maximum depth of the tree to search.
+ * @param[in] i_interfaces - List of interfaces to search.
+ *
+ * @return - A map of object and its related services and interfaces, if
+ *           success. If failed, empty map.
+ */
+
+inline types::MapperGetSubTree
+    getObjectSubTree(const std::string& i_objectPath, const int& i_depth,
+                     const std::vector<std::string>& i_interfaces)
+{
+    types::MapperGetSubTree l_subTreeMap;
+
+    if (i_objectPath.empty())
+    {
+        logging::logMessage("Object path is empty.");
+        return l_subTreeMap;
+    }
+
+    try
+    {
+        auto l_bus = sdbusplus::bus::new_default();
+        auto l_method = l_bus.new_method_call(
+            constants::objectMapperService, constants::objectMapperPath,
+            constants::objectMapperInf, "GetSubTree");
+        l_method.append(i_objectPath, i_depth, i_interfaces);
+        auto l_result = l_bus.call(l_method);
+        l_result.read(l_subTreeMap);
+    }
+    catch (const sdbusplus::exception::SdBusError& l_ex)
+    {
+        logging::logMessage(l_ex.what());
+    }
+
+    return l_subTreeMap;
+}
+
+/**
+ * @brief An API to read property from Dbus.
+ *
+ * The caller of the API needs to validate the validatity and correctness of the
+ * type and value of data returned. The API will just fetch and retun the data
+ * without any data validation.
+ *
+ * Note: It will be caller's responsibility to check for empty value returned
+ * and generate appropriate error if required.
+ *
+ * @param [in] serviceName - Name of the Dbus service.
+ * @param [in] objectPath - Object path under the service.
+ * @param [in] interface - Interface under which property exist.
+ * @param [in] property - Property whose value is to be read.
+ * @return - Value read from Dbus, if success.
+ *           If failed, empty variant.
+ */
+inline types::DbusVariantType readDbusProperty(
+    const std::string& serviceName, const std::string& objectPath,
+    const std::string& interface, const std::string& property)
+{
+    types::DbusVariantType propertyValue;
+
+    // Mandatory fields to make a read dbus call.
+    if (serviceName.empty() || objectPath.empty() || interface.empty() ||
+        property.empty())
+    {
+        logging::logMessage(
+            "One of the parameter to make Dbus read call is empty.");
+        return propertyValue;
+    }
+
+    try
+    {
+        auto bus = sdbusplus::bus::new_default();
+        auto method =
+            bus.new_method_call(serviceName.c_str(), objectPath.c_str(),
+                                "org.freedesktop.DBus.Properties", "Get");
+        method.append(interface, property);
+
+        auto result = bus.call(method);
+        result.read(propertyValue);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        return propertyValue;
+    }
+    return propertyValue;
+}
+
+/**
+ * @brief An API to write property on Dbus.
+ *
+ * The caller of this API needs to handle exception thrown by this method to
+ * identify any write failure. The API in no other way indicate write  failure
+ * to the caller.
+ *
+ * Note: It will be caller's responsibility ho handle the exception thrown in
+ * case of write failure and generate appropriate error.
+ *
+ * @param [in] serviceName - Name of the Dbus service.
+ * @param [in] objectPath - Object path under the service.
+ * @param [in] interface - Interface under which property exist.
+ * @param [in] property - Property whose value is to be written.
+ * @param [in] propertyValue - The value to be written.
+ */
+inline void writeDbusProperty(
+    const std::string& serviceName, const std::string& objectPath,
+    const std::string& interface, const std::string& property,
+    const types::DbusVariantType& propertyValue)
+{
+    // Mandatory fields to make a write dbus call.
+    if (serviceName.empty() || objectPath.empty() || interface.empty() ||
+        property.empty())
+    {
+        logging::logMessage(
+            "One of the parameter to make Dbus read call is empty.");
+
+        // caller need to handle the throw to ensure Dbus write success.
+        throw std::runtime_error("Dbus write failed, Parameter empty");
+    }
+
+    try
+    {
+        auto bus = sdbusplus::bus::new_default();
+        auto method =
+            bus.new_method_call(serviceName.c_str(), objectPath.c_str(),
+                                "org.freedesktop.DBus.Properties", "Set");
+        method.append(interface, property, propertyValue);
+        bus.call(method);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        logging::logMessage(e.what());
+
+        // caller needs to handle this throw to handle error in writing Dbus.
+        throw std::runtime_error("Dbus write failed");
+    }
+}
+
+/**
+ * @brief API to publish data on PIM
+ *
+ * The API calls notify on PIM object to publlish VPD.
+ *
+ * @param[in] objectMap - Object, its interface and data.
+ * @return bool - Status of call to PIM notify.
+ */
+inline bool callPIM(types::ObjectMap&& objectMap)
+{
+    try
+    {
+        for (const auto& l_objectKeyValue : objectMap)
+        {
+            auto l_nodeHandle = objectMap.extract(l_objectKeyValue.first);
+
+            if (l_nodeHandle.key().str.find(constants::pimPath, 0) !=
+                std::string::npos)
+            {
+                l_nodeHandle.key() = l_nodeHandle.key().str.replace(
+                    0, std::strlen(constants::pimPath), "");
+                objectMap.insert(std::move(l_nodeHandle));
+            }
+        }
+
+        auto bus = sdbusplus::bus::new_default();
+        auto pimMsg =
+            bus.new_method_call(constants::pimServiceName, constants::pimPath,
+                                constants::pimIntf, "Notify");
+        pimMsg.append(std::move(objectMap));
+        bus.call(pimMsg);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        return false;
+    }
+    return true;
+}
+
+/**
+ * @brief API to check if a D-Bus service is running or not.
+ *
+ * Any failure in calling the method "NameHasOwner" implies that the service is
+ * not in a running state. Hence the API returns false in case of any exception
+ * as well.
+ *
+ * @param[in] i_serviceName - D-Bus service name whose status is to be checked.
+ * @return bool - True if the service is running, false otherwise.
+ */
+inline bool isServiceRunning(const std::string& i_serviceName)
+{
+    bool l_retVal = false;
+
+    try
+    {
+        auto l_bus = sdbusplus::bus::new_default();
+        auto l_method = l_bus.new_method_call(
+            "org.freedesktop.DBus", "/org/freedesktop/DBus",
+            "org.freedesktop.DBus", "NameHasOwner");
+        l_method.append(i_serviceName);
+
+        l_bus.call(l_method).read(l_retVal);
+    }
+    catch (const sdbusplus::exception::SdBusError& l_ex)
+    {
+        logging::logMessage(
+            "Call to check service status failed with exception: " +
+            std::string(l_ex.what()));
+    }
+
+    return l_retVal;
+}
+
+/**
+ * @brief API to call "GetAttribute" method uner BIOS manager.
+ *
+ * The API reads the given attribuute from BIOS and returns a tuple of both
+ * current as well as pending value for that attribute.
+ * The API return only the current attribute value if found.
+ * API returns an empty variant of type BiosAttributeCurrentValue in case of any
+ * error.
+ *
+ * @param[in] i_attributeName - Attribute to be read.
+ * @return Tuple of PLDM attribute Type, current attribute value and pending
+ * attribute value.
+ */
+inline types::BiosAttributeCurrentValue
+    biosGetAttributeMethodCall(const std::string& i_attributeName)
+{
+    auto l_bus = sdbusplus::bus::new_default();
+    auto l_method = l_bus.new_method_call(
+        constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
+        constants::biosConfigMgrInterface, "GetAttribute");
+    l_method.append(i_attributeName);
+
+    types::BiosGetAttrRetType l_attributeVal;
+    try
+    {
+        auto l_result = l_bus.call(l_method);
+        l_result.read(std::get<0>(l_attributeVal), std::get<1>(l_attributeVal),
+                      std::get<2>(l_attributeVal));
+    }
+    catch (const sdbusplus::exception::SdBusError& l_ex)
+    {
+        logging::logMessage(
+            "Failed to read BIOS Attribute: " + i_attributeName +
+            " due to error " + std::string(l_ex.what()));
+
+        // TODO: Log an informational PEL here.
+    }
+
+    return std::get<1>(l_attributeVal);
+}
+
+/**
+ * @brief API to check if Chassis is powered on.
+ *
+ * This API queries Phosphor Chassis State Manager to know whether
+ * Chassis is powered on.
+ *
+ * @return true if chassis is powered on, false otherwise
+ */
+inline bool isChassisPowerOn()
+{
+    auto powerState = dbusUtility::readDbusProperty(
+        "xyz.openbmc_project.State.Chassis",
+        "/xyz/openbmc_project/state/chassis0",
+        "xyz.openbmc_project.State.Chassis", "CurrentPowerState");
+
+    if (auto curPowerState = std::get_if<std::string>(&powerState))
+    {
+        if ("xyz.openbmc_project.State.Chassis.PowerState.On" == *curPowerState)
+        {
+            return true;
+        }
+        return false;
+    }
+
+    /*
+        TODO: Add PEL.
+        Callout: Firmware callout
+        Type: Informational
+        Description: Chassis state can't be determined, defaulting to chassis
+        off. : e.what()
+    */
+    return false;
+}
+
+/**
+ * @brief API to check if host is in running state.
+ *
+ * This API reads the current host state from D-bus and returns true if the host
+ * is running.
+ *
+ * @return true if host is in running state. false otherwise.
+ */
+inline bool isHostRunning()
+{
+    const auto l_hostState = dbusUtility::readDbusProperty(
+        constants::hostService, constants::hostObjectPath,
+        constants::hostInterface, "CurrentHostState");
+
+    if (const auto l_currHostState = std::get_if<std::string>(&l_hostState))
+    {
+        if (*l_currHostState == constants::hostRunningState)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+/**
+ * @brief API to check if BMC is in ready state.
+ *
+ * This API reads the current state of BMC from D-bus and returns true if BMC is
+ * in ready state.
+ *
+ * @return true if BMC is ready, false otherwise.
+ */
+inline bool isBMCReady()
+{
+    const auto l_bmcState = dbusUtility::readDbusProperty(
+        constants::bmcStateService, constants::bmcZeroStateObject,
+        constants::bmcStateInterface, constants::currentBMCStateProperty);
+
+    if (const auto l_currBMCState = std::get_if<std::string>(&l_bmcState))
+    {
+        if (*l_currBMCState == constants::bmcReadyState)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+/**
+ * @brief An API to enable BMC reboot guard
+ *
+ * This API does a D-Bus method call to enable BMC reboot guard.
+ *
+ * @return On success, returns 0, otherwise returns -1.
+ */
+inline int EnableRebootGuard() noexcept
+{
+    int l_rc{constants::FAILURE};
+    try
+    {
+        auto l_bus = sdbusplus::bus::new_default();
+        auto l_method = l_bus.new_method_call(
+            constants::systemdService, constants::systemdObjectPath,
+            constants::systemdManagerInterface, "StartUnit");
+        l_method.append("reboot-guard-enable.service", "replace");
+        l_bus.call_noreply(l_method);
+        l_rc = constants::SUCCESS;
+    }
+    catch (const sdbusplus::exception::SdBusError& l_ex)
+    {
+        std::string l_errMsg =
+            "D-Bus call to enable BMC reboot guard failed for reason: ";
+        l_errMsg += l_ex.what();
+
+        logging::logMessage(l_errMsg);
+    }
+    return l_rc;
+}
+
+/**
+ * @brief An API to disable BMC reboot guard
+ *
+ * This API disables BMC reboot guard. This API has an inbuilt re-try mechanism.
+ * If Disable Reboot Guard fails, this API attempts to Disable Reboot Guard for
+ * 3 more times at an interval of 333ms.
+ *
+ * @return On success, returns 0, otherwise returns -1.
+ */
+inline int DisableRebootGuard() noexcept
+{
+    int l_rc{constants::FAILURE};
+
+    // A lambda which executes the DBus call to disable BMC reboot guard.
+    auto l_executeDisableRebootGuard = []() -> int {
+        int l_dBusCallRc{constants::FAILURE};
+        try
+        {
+            auto l_bus = sdbusplus::bus::new_default();
+            auto l_method = l_bus.new_method_call(
+                constants::systemdService, constants::systemdObjectPath,
+                constants::systemdManagerInterface, "StartUnit");
+            l_method.append("reboot-guard-disable.service", "replace");
+            l_bus.call_noreply(l_method);
+            l_dBusCallRc = constants::SUCCESS;
+        }
+        catch (const sdbusplus::exception::SdBusError& l_ex)
+        {}
+        return l_dBusCallRc;
+    };
+
+    if (constants::FAILURE == l_executeDisableRebootGuard())
+    {
+        std::function<void()> l_retryDisableRebootGuard;
+
+        // A lambda which tries to disable BMC reboot guard for 3 times at an
+        // interval of 333 ms.
+        l_retryDisableRebootGuard = [&]() {
+            constexpr int MAX_RETRIES{3};
+            static int l_numRetries{0};
+
+            if (l_numRetries < MAX_RETRIES)
+            {
+                l_numRetries++;
+                if (constants::FAILURE == l_executeDisableRebootGuard())
+                {
+                    // sleep for 333ms before next retry. This is just a random
+                    // value so that 3 re-tries * 333ms takes ~1 second in the
+                    // worst case.
+                    const std::chrono::milliseconds l_sleepTime{333};
+                    std::this_thread::sleep_for(l_sleepTime);
+                    l_retryDisableRebootGuard();
+                }
+                else
+                {
+                    l_numRetries = 0;
+                    l_rc = constants::SUCCESS;
+                }
+            }
+            else
+            {
+                // Failed to Disable Reboot Guard even after 3 retries.
+                logging::logMessage("Failed to Disable Reboot Guard after " +
+                                    std::to_string(MAX_RETRIES) + " re-tries");
+                l_numRetries = 0;
+            }
+        };
+
+        l_retryDisableRebootGuard();
+    }
+    else
+    {
+        l_rc = constants::SUCCESS;
+    }
+    return l_rc;
+}
+
+} // namespace dbusUtility
+} // namespace vpd
diff --git a/vpd-manager/include/utility/json_utility.hpp b/vpd-manager/include/utility/json_utility.hpp
new file mode 100644
index 0000000..3dab105
--- /dev/null
+++ b/vpd-manager/include/utility/json_utility.hpp
@@ -0,0 +1,1043 @@
+#pragma once
+
+#include "event_logger.hpp"
+#include "exceptions.hpp"
+#include "logger.hpp"
+#include "types.hpp"
+
+#include <gpiod.hpp>
+#include <nlohmann/json.hpp>
+#include <utility/common_utility.hpp>
+
+#include <fstream>
+#include <type_traits>
+#include <unordered_map>
+
+namespace vpd
+{
+namespace jsonUtility
+{
+
+// forward declaration of API for function map.
+bool processSystemCmdTag(const nlohmann::json& i_parsedConfigJson,
+                         const std::string& i_vpdFilePath,
+                         const std::string& i_baseAction,
+                         const std::string& i_flagToProcess);
+
+// forward declaration of API for function map.
+bool processGpioPresenceTag(
+    const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
+    const std::string& i_baseAction, const std::string& i_flagToProcess);
+
+// forward declaration of API for function map.
+bool procesSetGpioTag(const nlohmann::json& i_parsedConfigJson,
+                      const std::string& i_vpdFilePath,
+                      const std::string& i_baseAction,
+                      const std::string& i_flagToProcess);
+
+// Function pointers to process tags from config JSON.
+typedef bool (*functionPtr)(
+    const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
+    const std::string& i_baseAction, const std::string& i_flagToProcess);
+
+inline std::unordered_map<std::string, functionPtr> funcionMap{
+    {"gpioPresence", processGpioPresenceTag},
+    {"setGpio", procesSetGpioTag},
+    {"systemCmd", processSystemCmdTag}};
+
+/**
+ * @brief API to read VPD offset from JSON file.
+ *
+ * @param[in] i_sysCfgJsonObj - Parsed system config JSON object.
+ * @param[in] i_vpdFilePath - VPD file path.
+ * @return VPD offset if found in JSON, 0 otherwise.
+ */
+inline size_t getVPDOffset(const nlohmann::json& i_sysCfgJsonObj,
+                           const std::string& i_vpdFilePath)
+{
+    if (i_vpdFilePath.empty() || (i_sysCfgJsonObj.empty()) ||
+        (!i_sysCfgJsonObj.contains("frus")))
+    {
+        return 0;
+    }
+
+    if (i_sysCfgJsonObj["frus"].contains(i_vpdFilePath))
+    {
+        return i_sysCfgJsonObj["frus"][i_vpdFilePath].at(0).value("offset", 0);
+    }
+
+    const nlohmann::json& l_fruList =
+        i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+    for (const auto& l_fru : l_fruList.items())
+    {
+        const auto l_fruPath = l_fru.key();
+
+        // check if given path is redundant FRU path
+        if (i_vpdFilePath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
+                                 "redundantEeprom", ""))
+        {
+            // Return the offset of redundant EEPROM taken from JSON.
+            return i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("offset", 0);
+        }
+    }
+
+    return 0;
+}
+
+/**
+ * @brief API to parse respective JSON.
+ *
+ * Exception is thrown in case of JSON parse error.
+ *
+ * @param[in] pathToJson - Path to JSON.
+ * @return Parsed JSON.
+ */
+inline nlohmann::json getParsedJson(const std::string& pathToJson)
+{
+    if (pathToJson.empty())
+    {
+        throw std::runtime_error("Path to JSON is missing");
+    }
+
+    if (!std::filesystem::exists(pathToJson) ||
+        std::filesystem::is_empty(pathToJson))
+    {
+        throw std::runtime_error("Incorrect File Path or empty file");
+    }
+
+    std::ifstream jsonFile(pathToJson);
+    if (!jsonFile)
+    {
+        throw std::runtime_error("Failed to access Json path = " + pathToJson);
+    }
+
+    try
+    {
+        return nlohmann::json::parse(jsonFile);
+    }
+    catch (const nlohmann::json::parse_error& e)
+    {
+        throw std::runtime_error("Failed to parse JSON file");
+    }
+}
+
+/**
+ * @brief Get inventory object path from system config JSON.
+ *
+ * Given either D-bus inventory path/FRU EEPROM path/redundant EEPROM path,
+ * this API returns D-bus inventory path if present in JSON.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object
+ * @param[in] i_vpdPath - Path to where VPD is stored.
+ *
+ * @throw std::runtime_error.
+ *
+ * @return On success a valid path is returned, on failure an empty string is
+ * returned or an exception is thrown.
+ */
+inline std::string getInventoryObjPathFromJson(
+    const nlohmann::json& i_sysCfgJsonObj, const std::string& i_vpdPath)
+{
+    if (i_vpdPath.empty())
+    {
+        throw std::runtime_error("Path parameter is empty.");
+    }
+
+    if (!i_sysCfgJsonObj.contains("frus"))
+    {
+        throw std::runtime_error("Missing frus tag in system config JSON.");
+    }
+
+    // check if given path is FRU path
+    if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
+    {
+        return i_sysCfgJsonObj["frus"][i_vpdPath].at(0).value(
+            "inventoryPath", "");
+    }
+
+    const nlohmann::json& l_fruList =
+        i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+    for (const auto& l_fru : l_fruList.items())
+    {
+        const auto l_fruPath = l_fru.key();
+        const auto l_invObjPath =
+            i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("inventoryPath", "");
+
+        // check if given path is redundant FRU path or inventory path
+        if (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
+                             "redundantEeprom", "") ||
+            (i_vpdPath == l_invObjPath))
+        {
+            return l_invObjPath;
+        }
+    }
+    return std::string();
+}
+
+/**
+ * @brief Process "PostFailAction" defined in config JSON.
+ *
+ * In case there is some error in the processing of "preAction" execution and a
+ * set of procedure needs to be done as a part of post fail action. This base
+ * action can be defined in the config JSON for that FRU and it will be handled
+ * under this API.
+ *
+ * @param[in] i_parsedConfigJson - config JSON
+ * @param[in] i_vpdFilePath - EEPROM file path
+ * @param[in] i_flagToProcess - To identify which flag(s) needs to be processed
+ * under PostFailAction tag of config JSON.
+ * @return - success or failure
+ */
+inline bool executePostFailAction(const nlohmann::json& i_parsedConfigJson,
+                                  const std::string& i_vpdFilePath,
+                                  const std::string& i_flagToProcess)
+{
+    if (i_parsedConfigJson.empty() || i_vpdFilePath.empty() ||
+        i_flagToProcess.empty())
+    {
+        logging::logMessage(
+            "Invalid parameters. Abort processing for post fail action");
+
+        return false;
+    }
+
+    if (!(i_parsedConfigJson["frus"][i_vpdFilePath].at(0))["PostFailAction"]
+             .contains(i_flagToProcess))
+    {
+        logging::logMessage(
+            "Config JSON missing flag " + i_flagToProcess +
+            " to execute post fail action for path = " + i_vpdFilePath);
+
+        return false;
+    }
+
+    for (const auto& l_tags : (i_parsedConfigJson["frus"][i_vpdFilePath].at(
+             0))["PostFailAction"][i_flagToProcess]
+                                  .items())
+    {
+        auto itrToFunction = funcionMap.find(l_tags.key());
+        if (itrToFunction != funcionMap.end())
+        {
+            if (!itrToFunction->second(i_parsedConfigJson, i_vpdFilePath,
+                                       "PostFailAction", i_flagToProcess))
+            {
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+/**
+ * @brief Process "systemCmd" tag for a given FRU.
+ *
+ * The API will process "systemCmd" tag if it is defined in the config
+ * JSON for the given FRU.
+ *
+ * @param[in] i_parsedConfigJson - config JSON
+ * @param[in] i_vpdFilePath - EEPROM file path
+ * @param[in] i_baseAction - Base action for which this tag has been called.
+ * @param[in] i_flagToProcess - Flag nested under the base action for which this
+ * tag has been called.
+ * @return Execution status.
+ */
+inline bool processSystemCmdTag(
+    const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
+    const std::string& i_baseAction, const std::string& i_flagToProcess)
+{
+    if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
+        i_baseAction.empty() || i_flagToProcess.empty())
+    {
+        logging::logMessage(
+            "Invalid parameter. Abort processing of processSystemCmd.");
+        return false;
+    }
+
+    if (!((i_parsedConfigJson["frus"][i_vpdFilePath].at(
+               0)[i_baseAction][i_flagToProcess]["systemCmd"])
+              .contains("cmd")))
+    {
+        logging::logMessage(
+            "Config JSON missing required information to execute system command for EEPROM " +
+            i_vpdFilePath);
+
+        return false;
+    }
+
+    try
+    {
+        const std::string& l_systemCommand =
+            i_parsedConfigJson["frus"][i_vpdFilePath].at(
+                0)[i_baseAction][i_flagToProcess]["systemCmd"]["cmd"];
+
+        commonUtility::executeCmd(l_systemCommand);
+        return true;
+    }
+    catch (const std::exception& e)
+    {
+        std::string l_errMsg = "Process system tag failed for exception: ";
+        l_errMsg += e.what();
+
+        logging::logMessage(l_errMsg);
+        return false;
+    }
+}
+
+/**
+ * @brief Checks for presence of a given FRU using GPIO line.
+ *
+ * This API returns the presence information of the FRU corresponding to the
+ * given VPD file path by setting the presence pin.
+ *
+ * @param[in] i_parsedConfigJson - config JSON
+ * @param[in] i_vpdFilePath - EEPROM file path
+ * @param[in] i_baseAction - Base action for which this tag has been called.
+ * @param[in] i_flagToProcess - Flag nested under the base action for which this
+ * tag has been called.
+ * @return Execution status.
+ */
+inline bool processGpioPresenceTag(
+    const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
+    const std::string& i_baseAction, const std::string& i_flagToProcess)
+{
+    if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
+        i_baseAction.empty() || i_flagToProcess.empty())
+    {
+        logging::logMessage(
+            "Invalid parameter. Abort processing of processGpioPresence tag");
+        return false;
+    }
+
+    if (!(((i_parsedConfigJson["frus"][i_vpdFilePath].at(
+                0)[i_baseAction][i_flagToProcess]["gpioPresence"])
+               .contains("pin")) &&
+          ((i_parsedConfigJson["frus"][i_vpdFilePath].at(
+                0)[i_baseAction][i_flagToProcess]["gpioPresence"])
+               .contains("value"))))
+    {
+        logging::logMessage(
+            "Config JSON missing required information to detect presence for EEPROM " +
+            i_vpdFilePath);
+
+        return false;
+    }
+
+    // get the pin name
+    const std::string& l_presencePinName =
+        i_parsedConfigJson["frus"][i_vpdFilePath].at(
+            0)[i_baseAction][i_flagToProcess]["gpioPresence"]["pin"];
+
+    // get the pin value
+    uint8_t l_presencePinValue = i_parsedConfigJson["frus"][i_vpdFilePath].at(
+        0)[i_baseAction][i_flagToProcess]["gpioPresence"]["value"];
+
+    try
+    {
+        gpiod::line l_presenceLine = gpiod::find_line(l_presencePinName);
+
+        if (!l_presenceLine)
+        {
+            throw GpioException("Couldn't find the GPIO line.");
+        }
+
+        l_presenceLine.request({"Read the presence line",
+                                gpiod::line_request::DIRECTION_INPUT, 0});
+
+        return (l_presencePinValue == l_presenceLine.get_value());
+    }
+    catch (const std::exception& ex)
+    {
+        std::string l_errMsg = "Exception on GPIO line: ";
+        l_errMsg += l_presencePinName;
+        l_errMsg += " Reason: ";
+        l_errMsg += ex.what();
+        l_errMsg += " File: " + i_vpdFilePath + " Pel Logged";
+
+        // ToDo -- Update Internal Rc code.
+        EventLogger::createAsyncPelWithInventoryCallout(
+            types::ErrorType::GpioError, types::SeverityType::Informational,
+            {{getInventoryObjPathFromJson(i_parsedConfigJson, i_vpdFilePath),
+              types::CalloutPriority::High}},
+            std::source_location::current().file_name(),
+            std::source_location::current().function_name(), 0, l_errMsg,
+            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+
+        logging::logMessage(l_errMsg);
+
+        // Except when GPIO pin value is false, we go and try collecting the
+        // FRU VPD as we couldn't able to read GPIO pin value due to some
+        // error/exception. So returning true in error scenario.
+        return true;
+    }
+}
+
+/**
+ * @brief Process "setGpio" tag for a given FRU.
+ *
+ * This API enables the GPIO line.
+ *
+ * @param[in] i_parsedConfigJson - config JSON
+ * @param[in] i_vpdFilePath - EEPROM file path
+ * @param[in] i_baseAction - Base action for which this tag has been called.
+ * @param[in] i_flagToProcess - Flag nested under the base action for which this
+ * tag has been called.
+ * @return Execution status.
+ */
+inline bool procesSetGpioTag(
+    const nlohmann::json& i_parsedConfigJson, const std::string& i_vpdFilePath,
+    const std::string& i_baseAction, const std::string& i_flagToProcess)
+{
+    if (i_vpdFilePath.empty() || i_parsedConfigJson.empty() ||
+        i_baseAction.empty() || i_flagToProcess.empty())
+    {
+        logging::logMessage(
+            "Invalid parameter. Abort processing of procesSetGpio.");
+        return false;
+    }
+
+    if (!(((i_parsedConfigJson["frus"][i_vpdFilePath].at(
+                0)[i_baseAction][i_flagToProcess]["setGpio"])
+               .contains("pin")) &&
+          ((i_parsedConfigJson["frus"][i_vpdFilePath].at(
+                0)[i_baseAction][i_flagToProcess]["setGpio"])
+               .contains("value"))))
+    {
+        logging::logMessage(
+            "Config JSON missing required information to set gpio line for EEPROM " +
+            i_vpdFilePath);
+
+        return false;
+    }
+
+    const std::string& l_pinName = i_parsedConfigJson["frus"][i_vpdFilePath].at(
+        0)[i_baseAction][i_flagToProcess]["setGpio"]["pin"];
+
+    // Get the value to set
+    uint8_t l_pinValue = i_parsedConfigJson["frus"][i_vpdFilePath].at(
+        0)[i_baseAction][i_flagToProcess]["setGpio"]["value"];
+
+    logging::logMessage(
+        "Setting GPIO: " + l_pinName + " to " + std::to_string(l_pinValue));
+    try
+    {
+        gpiod::line l_outputLine = gpiod::find_line(l_pinName);
+
+        if (!l_outputLine)
+        {
+            throw GpioException("Couldn't find GPIO line.");
+        }
+
+        l_outputLine.request(
+            {"FRU Action", ::gpiod::line_request::DIRECTION_OUTPUT, 0},
+            l_pinValue);
+        return true;
+    }
+    catch (const std::exception& ex)
+    {
+        std::string l_errMsg = "Exception on GPIO line: ";
+        l_errMsg += l_pinName;
+        l_errMsg += " Reason: ";
+        l_errMsg += ex.what();
+        l_errMsg += " File: " + i_vpdFilePath + " Pel Logged";
+
+        // ToDo -- Update Internal RC code
+        EventLogger::createAsyncPelWithInventoryCallout(
+            types::ErrorType::GpioError, types::SeverityType::Informational,
+            {{getInventoryObjPathFromJson(i_parsedConfigJson, i_vpdFilePath),
+              types::CalloutPriority::High}},
+            std::source_location::current().file_name(),
+            std::source_location::current().function_name(), 0, l_errMsg,
+            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
+
+        logging::logMessage(l_errMsg);
+
+        return false;
+    }
+}
+
+/**
+ * @brief Process any action, if defined in config JSON.
+ *
+ * If any FRU(s) requires any special handling, then this base action can be
+ * defined for that FRU in the config JSON, processing of which will be handled
+ * in this API.
+ * Examples of action - preAction, PostAction etc.
+ *
+ * @param[in] i_parsedConfigJson - config JSON
+ * @param[in] i_action - Base action to be performed.
+ * @param[in] i_vpdFilePath - EEPROM file path
+ * @param[in] i_flagToProcess - To identify which flag(s) needs to be processed
+ * under PreAction tag of config JSON.
+ * @return - success or failure
+ */
+inline bool executeBaseAction(
+    const nlohmann::json& i_parsedConfigJson, const std::string& i_action,
+    const std::string& i_vpdFilePath, const std::string& i_flagToProcess)
+{
+    if (i_flagToProcess.empty() || i_action.empty() || i_vpdFilePath.empty() ||
+        !i_parsedConfigJson.contains("frus"))
+    {
+        logging::logMessage("Invalid parameter");
+        return false;
+    }
+
+    if (!i_parsedConfigJson["frus"].contains(i_vpdFilePath))
+    {
+        logging::logMessage(
+            "File path: " + i_vpdFilePath + " not found in JSON");
+        return false;
+    }
+
+    if (!i_parsedConfigJson["frus"][i_vpdFilePath].at(0).contains(i_action))
+    {
+        logging::logMessage("Action [" + i_action +
+                            "] not defined for file path:" + i_vpdFilePath);
+        return false;
+    }
+
+    if (!(i_parsedConfigJson["frus"][i_vpdFilePath].at(0))[i_action].contains(
+            i_flagToProcess))
+    {
+        logging::logMessage("Config JSON missing flag [" + i_flagToProcess +
+                            "] to execute action for path = " + i_vpdFilePath);
+
+        return false;
+    }
+
+    const nlohmann::json& l_tagsJson =
+        (i_parsedConfigJson["frus"][i_vpdFilePath].at(
+            0))[i_action][i_flagToProcess];
+
+    for (const auto& l_tag : l_tagsJson.items())
+    {
+        auto itrToFunction = funcionMap.find(l_tag.key());
+        if (itrToFunction != funcionMap.end())
+        {
+            if (!itrToFunction->second(i_parsedConfigJson, i_vpdFilePath,
+                                       i_action, i_flagToProcess))
+            {
+                // In case any of the tag fails to execute. Mark action
+                // as failed for that flag.
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+/**
+ * @brief Get redundant FRU path from system config JSON
+ *
+ * Given either D-bus inventory path/FRU path/redundant FRU path, this
+ * API returns the redundant FRU path taken from "redundantEeprom" tag from
+ * system config JSON.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ * @param[in] i_vpdPath - Path to where VPD is stored.
+ *
+ * @throw std::runtime_error.
+ * @return On success return valid path, on failure return empty string.
+ */
+inline std::string getRedundantEepromPathFromJson(
+    const nlohmann::json& i_sysCfgJsonObj, const std::string& i_vpdPath)
+{
+    if (i_vpdPath.empty())
+    {
+        throw std::runtime_error("Path parameter is empty.");
+    }
+
+    if (!i_sysCfgJsonObj.contains("frus"))
+    {
+        throw std::runtime_error("Missing frus tag in system config JSON.");
+    }
+
+    // check if given path is FRU path
+    if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
+    {
+        return i_sysCfgJsonObj["frus"][i_vpdPath].at(0).value(
+            "redundantEeprom", "");
+    }
+
+    const nlohmann::json& l_fruList =
+        i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+    for (const auto& l_fru : l_fruList.items())
+    {
+        const std::string& l_fruPath = l_fru.key();
+        const std::string& l_redundantFruPath =
+            i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("redundantEeprom",
+                                                           "");
+
+        // check if given path is inventory path or redundant FRU path
+        if ((i_sysCfgJsonObj["frus"][l_fruPath].at(0).value("inventoryPath",
+                                                            "") == i_vpdPath) ||
+            (l_redundantFruPath == i_vpdPath))
+        {
+            return l_redundantFruPath;
+        }
+    }
+    return std::string();
+}
+
+/**
+ * @brief Get FRU EEPROM path from system config JSON
+ *
+ * Given either D-bus inventory path/FRU EEPROM path/redundant EEPROM path,
+ * this API returns FRU EEPROM path if present in JSON.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object
+ * @param[in] i_vpdPath - Path to where VPD is stored.
+ *
+ * @throw std::runtime_error.
+ *
+ * @return On success return valid path, on failure return empty string.
+ */
+inline std::string getFruPathFromJson(const nlohmann::json& i_sysCfgJsonObj,
+                                      const std::string& i_vpdPath)
+{
+    if (i_vpdPath.empty())
+    {
+        throw std::runtime_error("Path parameter is empty.");
+    }
+
+    if (!i_sysCfgJsonObj.contains("frus"))
+    {
+        throw std::runtime_error("Missing frus tag in system config JSON.");
+    }
+
+    // check if given path is FRU path
+    if (i_sysCfgJsonObj["frus"].contains(i_vpdPath))
+    {
+        return i_vpdPath;
+    }
+
+    const nlohmann::json& l_fruList =
+        i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+    for (const auto& l_fru : l_fruList.items())
+    {
+        const auto l_fruPath = l_fru.key();
+
+        // check if given path is redundant FRU path or inventory path
+        if (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
+                             "redundantEeprom", "") ||
+            (i_vpdPath == i_sysCfgJsonObj["frus"][l_fruPath].at(0).value(
+                              "inventoryPath", "")))
+        {
+            return l_fruPath;
+        }
+    }
+    return std::string();
+}
+
+/**
+ * @brief An API to check backup and restore VPD is required.
+ *
+ * The API checks if there is provision for backup and restore mentioned in the
+ * system config JSON, by looking "backupRestoreConfigPath" tag.
+ * Checks if the path mentioned is a hardware path, by checking if the file path
+ * exists and size of contents in the path.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ *
+ * @return true if backup and restore is required, false otherwise.
+ */
+inline bool isBackupAndRestoreRequired(const nlohmann::json& i_sysCfgJsonObj)
+{
+    try
+    {
+        const std::string& l_backupAndRestoreCfgFilePath =
+            i_sysCfgJsonObj.value("backupRestoreConfigPath", "");
+        if (!l_backupAndRestoreCfgFilePath.empty() &&
+            std::filesystem::exists(l_backupAndRestoreCfgFilePath) &&
+            !std::filesystem::is_empty(l_backupAndRestoreCfgFilePath))
+        {
+            return true;
+        }
+    }
+    catch (std::exception& ex)
+    {
+        logging::logMessage(ex.what());
+    }
+    return false;
+}
+
+/** @brief API to check if an action is required for given EEPROM path.
+ *
+ * System config JSON can contain pre-action, post-action etc. like actions
+ * defined for an EEPROM path. The API will check if any such action is defined
+ * for the EEPROM.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ * @param[in] i_vpdFruPath - EEPROM path.
+ * @param[in] i_action - Action to be checked.
+ * @param[in] i_flowFlag - Denotes the flow w.r.t which the action should be
+ * triggered.
+ * @return - True if action is defined for the flow, false otherwise.
+ */
+inline bool isActionRequired(
+    const nlohmann::json& i_sysCfgJsonObj, const std::string& i_vpdFruPath,
+    const std::string& i_action, const std::string& i_flowFlag)
+{
+    if (i_vpdFruPath.empty() || i_action.empty() || i_flowFlag.empty())
+    {
+        logging::logMessage("Invalid parameters recieved.");
+        return false;
+    }
+
+    if (!i_sysCfgJsonObj.contains("frus"))
+    {
+        logging::logMessage("Invalid JSON object recieved.");
+        return false;
+    }
+
+    if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
+    {
+        logging::logMessage(
+            "JSON object does not contain EEPROM path " + i_vpdFruPath);
+        return false;
+    }
+
+    if ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)).contains(i_action))
+    {
+        if ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))[i_action].contains(
+                i_flowFlag))
+        {
+            return true;
+        }
+
+        logging::logMessage("Flow flag: [" + i_flowFlag +
+                            "], not found in JSON for path: " + i_vpdFruPath);
+        return false;
+    }
+    return false;
+}
+
+/**
+ * @brief An API to return list of FRUs that needs GPIO polling.
+ *
+ * An API that checks for the FRUs that requires GPIO polling and returns
+ * a list of FRUs that needs polling. Returns an empty list if there are
+ * no FRUs that requires polling.
+ *
+ * @throw std::runtime_error
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ *
+ * @return list of FRUs parameters that needs polling.
+ */
+inline std::vector<std::string>
+    getListOfGpioPollingFrus(const nlohmann::json& i_sysCfgJsonObj)
+{
+    if (i_sysCfgJsonObj.empty())
+    {
+        throw std::runtime_error("Invalid Parameters");
+    }
+
+    if (!i_sysCfgJsonObj.contains("frus"))
+    {
+        throw std::runtime_error("Missing frus section in system config JSON");
+    }
+
+    std::vector<std::string> l_gpioPollingRequiredFrusList;
+
+    for (const auto& l_fru : i_sysCfgJsonObj["frus"].items())
+    {
+        const auto l_fruPath = l_fru.key();
+
+        try
+        {
+            if (isActionRequired(i_sysCfgJsonObj, l_fruPath, "pollingRequired",
+                                 "hotPlugging"))
+            {
+                if (i_sysCfgJsonObj["frus"][l_fruPath]
+                        .at(0)["pollingRequired"]["hotPlugging"]
+                        .contains("gpioPresence"))
+                {
+                    l_gpioPollingRequiredFrusList.push_back(l_fruPath);
+                }
+            }
+        }
+        catch (const std::exception& l_ex)
+        {
+            logging::logMessage(l_ex.what());
+        }
+    }
+
+    return l_gpioPollingRequiredFrusList;
+}
+
+/**
+ * @brief Get all related path(s) to update keyword value.
+ *
+ * Given FRU EEPROM path/Inventory path needs keyword's value update, this API
+ * returns tuple of FRU EEPROM path, inventory path and redundant EEPROM path if
+ * exists in the system config JSON.
+ *
+ * Note: If the inventory object path or redundant EEPROM path(s) are not found
+ * in the system config JSON, corresponding fields will have empty value in the
+ * returning tuple.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ * @param[in,out] io_vpdPath - Inventory object path or FRU EEPROM path.
+ *
+ * @return On success returns tuple of EEPROM path, inventory path & redundant
+ * path, on failure returns tuple with given input path alone.
+ */
+inline std::tuple<std::string, std::string, std::string>
+    getAllPathsToUpdateKeyword(const nlohmann::json& i_sysCfgJsonObj,
+                               std::string io_vpdPath)
+{
+    types::Path l_inventoryObjPath;
+    types::Path l_redundantFruPath;
+    try
+    {
+        if (!i_sysCfgJsonObj.empty())
+        {
+            // Get hardware path from system config JSON.
+            const types::Path l_fruPath =
+                jsonUtility::getFruPathFromJson(i_sysCfgJsonObj, io_vpdPath);
+
+            if (!l_fruPath.empty())
+            {
+                io_vpdPath = l_fruPath;
+
+                // Get inventory object path from system config JSON
+                l_inventoryObjPath = jsonUtility::getInventoryObjPathFromJson(
+                    i_sysCfgJsonObj, l_fruPath);
+
+                // Get redundant hardware path if present in system config JSON
+                l_redundantFruPath =
+                    jsonUtility::getRedundantEepromPathFromJson(i_sysCfgJsonObj,
+                                                                l_fruPath);
+            }
+        }
+    }
+    catch (const std::exception& l_exception)
+    {
+        logging::logMessage(
+            "Failed to get all paths to update keyword value, error " +
+            std::string(l_exception.what()));
+    }
+    return std::make_tuple(io_vpdPath, l_inventoryObjPath, l_redundantFruPath);
+}
+
+/**
+ * @brief An API to get DBus service name.
+ *
+ * Given DBus inventory path, this API returns DBus service name if present in
+ * the JSON.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ * @param[in] l_inventoryPath - DBus inventory path.
+ *
+ * @return On success returns the service name present in the system config
+ * JSON, otherwise empty string.
+ *
+ * Note: Caller has to handle in case of empty string received.
+ */
+inline std::string getServiceName(const nlohmann::json& i_sysCfgJsonObj,
+                                  const std::string& l_inventoryPath)
+{
+    try
+    {
+        if (l_inventoryPath.empty())
+        {
+            throw std::runtime_error("Path parameter is empty.");
+        }
+
+        if (!i_sysCfgJsonObj.contains("frus"))
+        {
+            throw std::runtime_error("Missing frus tag in system config JSON.");
+        }
+
+        const nlohmann::json& l_listOfFrus =
+            i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+        for (const auto& l_frus : l_listOfFrus.items())
+        {
+            for (const auto& l_inventoryItem : l_frus.value())
+            {
+                if (l_inventoryPath.compare(l_inventoryItem["inventoryPath"]) ==
+                    constants::STR_CMP_SUCCESS)
+                {
+                    return l_inventoryItem["serviceName"];
+                }
+            }
+        }
+        throw std::runtime_error(
+            "Inventory path not found in the system config JSON");
+    }
+    catch (const std::exception& l_exception)
+    {
+        logging::logMessage(
+            "Error while getting DBus service name for given path " +
+            l_inventoryPath + ", error: " + std::string(l_exception.what()));
+        // TODO:log PEL
+    }
+    return std::string{};
+}
+
+/**
+ * @brief An API to check if a FRU is tagged as "powerOffOnly"
+ *
+ * Given the system config JSON and VPD FRU path, this API checks if the FRU
+ * VPD can be collected at Chassis Power Off state only.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ * @param[in] i_vpdFruPath - EEPROM path.
+ * @return - True if FRU VPD can be collected at Chassis Power Off state only.
+ *           False otherwise
+ */
+inline bool isFruPowerOffOnly(const nlohmann::json& i_sysCfgJsonObj,
+                              const std::string& i_vpdFruPath)
+{
+    if (i_vpdFruPath.empty())
+    {
+        logging::logMessage("FRU path is empty.");
+        return false;
+    }
+
+    if (!i_sysCfgJsonObj.contains("frus"))
+    {
+        logging::logMessage("Missing frus tag in system config JSON.");
+        return false;
+    }
+
+    if (!i_sysCfgJsonObj["frus"].contains(i_vpdFruPath))
+    {
+        logging::logMessage("JSON object does not contain EEPROM path \'" +
+                            i_vpdFruPath + "\'");
+        return false;
+    }
+
+    return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
+                .contains("powerOffOnly") &&
+            (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0)["powerOffOnly"]));
+}
+
+/**
+ * @brief API which tells if the FRU is replaceable at runtime
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ * @param[in] i_vpdFruPath - EEPROM path.
+ *
+ * @return true if FRU is replaceable at runtime. false otherwise.
+ */
+inline bool isFruReplaceableAtRuntime(const nlohmann::json& i_sysCfgJsonObj,
+                                      const std::string& i_vpdFruPath)
+{
+    try
+    {
+        if (i_vpdFruPath.empty())
+        {
+            throw std::runtime_error("Given FRU path is empty.");
+        }
+
+        if (i_sysCfgJsonObj.empty() || (!i_sysCfgJsonObj.contains("frus")))
+        {
+            throw std::runtime_error("Invalid system config JSON object.");
+        }
+
+        return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
+                    .contains("replaceableAtRuntime") &&
+                (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(
+                    0)["replaceableAtRuntime"]));
+    }
+    catch (const std::exception& l_error)
+    {
+        // TODO: Log PEL
+        logging::logMessage(l_error.what());
+    }
+
+    return false;
+}
+
+/**
+ * @brief API which tells if the FRU is replaceable at standby
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ * @param[in] i_vpdFruPath - EEPROM path.
+ *
+ * @return true if FRU is replaceable at standby. false otherwise.
+ */
+inline bool isFruReplaceableAtStandby(const nlohmann::json& i_sysCfgJsonObj,
+                                      const std::string& i_vpdFruPath)
+{
+    try
+    {
+        if (i_vpdFruPath.empty())
+        {
+            throw std::runtime_error("Given FRU path is empty.");
+        }
+
+        if (i_sysCfgJsonObj.empty() || (!i_sysCfgJsonObj.contains("frus")))
+        {
+            throw std::runtime_error("Invalid system config JSON object.");
+        }
+
+        return ((i_sysCfgJsonObj["frus"][i_vpdFruPath].at(0))
+                    .contains("replaceableAtStandby") &&
+                (i_sysCfgJsonObj["frus"][i_vpdFruPath].at(
+                    0)["replaceableAtStandby"]));
+    }
+    catch (const std::exception& l_error)
+    {
+        // TODO: Log PEL
+        logging::logMessage(l_error.what());
+    }
+
+    return false;
+}
+
+/**
+ * @brief API to get list of FRUs replaceable at standby from JSON.
+ *
+ * The API will return a vector of FRUs inventory path which are replaceable at
+ * standby.
+ * The API can throw exception in case of error scenarios. Caller's
+ * responsibility to handle those exceptions.
+ *
+ * @param[in] i_sysCfgJsonObj - System config JSON object.
+ *
+ * @return - List of FRUs replaceable at standby.
+ */
+inline std::vector<std::string>
+    getListOfFrusReplaceableAtStandby(const nlohmann::json& i_sysCfgJsonObj)
+{
+    std::vector<std::string> l_frusReplaceableAtStandby;
+
+    if (!i_sysCfgJsonObj.contains("frus"))
+    {
+        logging::logMessage("Missing frus tag in system config JSON.");
+        return l_frusReplaceableAtStandby;
+    }
+
+    const nlohmann::json& l_fruList =
+        i_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
+
+    for (const auto& l_fru : l_fruList.items())
+    {
+        if (i_sysCfgJsonObj["frus"][l_fru.key()].at(0).value(
+                "replaceableAtStandby", false))
+        {
+            const std::string& l_inventoryObjectPath =
+                i_sysCfgJsonObj["frus"][l_fru.key()].at(0).value(
+                    "inventoryPath", "");
+
+            if (!l_inventoryObjectPath.empty())
+            {
+                l_frusReplaceableAtStandby.emplace_back(l_inventoryObjectPath);
+            }
+        }
+    }
+
+    return l_frusReplaceableAtStandby;
+}
+
+} // namespace jsonUtility
+} // namespace vpd
diff --git a/vpd-manager/include/utility/vpd_specific_utility.hpp b/vpd-manager/include/utility/vpd_specific_utility.hpp
new file mode 100644
index 0000000..d6b92fd
--- /dev/null
+++ b/vpd-manager/include/utility/vpd_specific_utility.hpp
@@ -0,0 +1,556 @@
+#pragma once
+
+#include "config.h"
+
+#include "constants.hpp"
+#include "exceptions.hpp"
+#include "logger.hpp"
+#include "types.hpp"
+
+#include <nlohmann/json.hpp>
+#include <utility/common_utility.hpp>
+#include <utility/dbus_utility.hpp>
+
+#include <filesystem>
+#include <fstream>
+#include <regex>
+
+namespace vpd
+{
+namespace vpdSpecificUtility
+{
+/**
+ * @brief API to generate file name for bad VPD.
+ *
+ * For i2c eeproms - the pattern of the vpd-name will be
+ * i2c-<bus-number>-<eeprom-address>.
+ * For spi eeproms - the pattern of the vpd-name will be spi-<spi-number>.
+ *
+ * @param[in] vpdFilePath - file path of the vpd.
+ * @return Generated file name.
+ */
+inline std::string generateBadVPDFileName(const std::string& vpdFilePath)
+{
+    std::string badVpdFileName = BAD_VPD_DIR;
+    if (vpdFilePath.find("i2c") != std::string::npos)
+    {
+        badVpdFileName += "i2c-";
+        std::regex i2cPattern("(at24/)([0-9]+-[0-9]+)\\/");
+        std::smatch match;
+        if (std::regex_search(vpdFilePath, match, i2cPattern))
+        {
+            badVpdFileName += match.str(2);
+        }
+    }
+    else if (vpdFilePath.find("spi") != std::string::npos)
+    {
+        std::regex spiPattern("((spi)[0-9]+)(.0)");
+        std::smatch match;
+        if (std::regex_search(vpdFilePath, match, spiPattern))
+        {
+            badVpdFileName += match.str(1);
+        }
+    }
+    return badVpdFileName;
+}
+
+/**
+ * @brief API which dumps the broken/bad vpd in a directory.
+ * When the vpd is bad, this API places  the bad vpd file inside
+ * "/tmp/bad-vpd" in BMC, in order to collect bad VPD data as a part of user
+ * initiated BMC dump.
+ *
+ * Note: Throws exception in case of any failure.
+ *
+ * @param[in] vpdFilePath - vpd file path
+ * @param[in] vpdVector - vpd vector
+ */
+inline void dumpBadVpd(const std::string& vpdFilePath,
+                       const types::BinaryVector& vpdVector)
+{
+    std::filesystem::create_directory(BAD_VPD_DIR);
+    auto badVpdPath = generateBadVPDFileName(vpdFilePath);
+
+    if (std::filesystem::exists(badVpdPath))
+    {
+        std::error_code ec;
+        std::filesystem::remove(badVpdPath, ec);
+        if (ec) // error code
+        {
+            std::string error = "Error removing the existing broken vpd in ";
+            error += badVpdPath;
+            error += ". Error code : ";
+            error += ec.value();
+            error += ". Error message : ";
+            error += ec.message();
+            throw std::runtime_error(error);
+        }
+    }
+
+    std::ofstream badVpdFileStream(badVpdPath, std::ofstream::binary);
+    if (badVpdFileStream.is_open())
+    {
+        throw std::runtime_error(
+            "Failed to open bad vpd file path in /tmp/bad-vpd. "
+            "Unable to dump the broken/bad vpd file.");
+    }
+
+    badVpdFileStream.write(reinterpret_cast<const char*>(vpdVector.data()),
+                           vpdVector.size());
+}
+
+/**
+ * @brief An API to read value of a keyword.
+ *
+ * Note: Throws exception. Caller needs to handle.
+ *
+ * @param[in] kwdValueMap - A map having Kwd value pair.
+ * @param[in] kwd - keyword name.
+ * @param[out] kwdValue - Value of the keyword read from map.
+ */
+inline void getKwVal(const types::IPZKwdValueMap& kwdValueMap,
+                     const std::string& kwd, std::string& kwdValue)
+{
+    if (kwd.empty())
+    {
+        logging::logMessage("Invalid parameters");
+        throw std::runtime_error("Invalid parameters");
+    }
+
+    auto itrToKwd = kwdValueMap.find(kwd);
+    if (itrToKwd != kwdValueMap.end())
+    {
+        kwdValue = itrToKwd->second;
+        return;
+    }
+
+    throw std::runtime_error("Keyword not found");
+}
+
+/**
+ * @brief An API to process encoding of a keyword.
+ *
+ * @param[in] keyword - Keyword to be processed.
+ * @param[in] encoding - Type of encoding.
+ * @return Value after being processed for encoded type.
+ */
+inline std::string encodeKeyword(const std::string& keyword,
+                                 const std::string& encoding)
+{
+    // Default value is keyword value
+    std::string result(keyword.begin(), keyword.end());
+
+    if (encoding == "MAC")
+    {
+        result.clear();
+        size_t firstByte = keyword[0];
+        result += commonUtility::toHex(firstByte >> 4);
+        result += commonUtility::toHex(firstByte & 0x0f);
+        for (size_t i = 1; i < keyword.size(); ++i)
+        {
+            result += ":";
+            result += commonUtility::toHex(keyword[i] >> 4);
+            result += commonUtility::toHex(keyword[i] & 0x0f);
+        }
+    }
+    else if (encoding == "DATE")
+    {
+        // Date, represent as
+        // <year>-<month>-<day> <hour>:<min>
+        result.clear();
+        static constexpr uint8_t skipPrefix = 3;
+
+        auto strItr = keyword.begin();
+        advance(strItr, skipPrefix);
+        for_each(strItr, keyword.end(), [&result](size_t c) { result += c; });
+
+        result.insert(constants::BD_YEAR_END, 1, '-');
+        result.insert(constants::BD_MONTH_END, 1, '-');
+        result.insert(constants::BD_DAY_END, 1, ' ');
+        result.insert(constants::BD_HOUR_END, 1, ':');
+    }
+
+    return result;
+}
+
+/**
+ * @brief Helper function to insert or merge in map.
+ *
+ * This method checks in an interface if the given interface exists. If the
+ * interface key already exists, property map is inserted corresponding to it.
+ * If the key does'nt exist then given interface and property map pair is newly
+ * created. If the property present in propertymap already exist in the
+ * InterfaceMap, then the new property value is ignored.
+ *
+ * @param[in,out] map - Interface map.
+ * @param[in] interface - Interface to be processed.
+ * @param[in] propertyMap - new property map that needs to be emplaced.
+ */
+inline void insertOrMerge(types::InterfaceMap& map,
+                          const std::string& interface,
+                          types::PropertyMap&& propertyMap)
+{
+    if (map.find(interface) != map.end())
+    {
+        try
+        {
+            auto& prop = map.at(interface);
+            std::for_each(propertyMap.begin(), propertyMap.end(),
+                          [&prop](auto l_keyValue) {
+                              prop[l_keyValue.first] = l_keyValue.second;
+                          });
+        }
+        catch (const std::exception& l_ex)
+        {
+            // ToDo:: Log PEL
+            logging::logMessage(
+                "Inserting properties into interface[" + interface +
+                "] map is failed, reason: " + std::string(l_ex.what()));
+        }
+    }
+    else
+    {
+        map.emplace(interface, propertyMap);
+    }
+}
+
+/**
+ * @brief API to expand unpanded location code.
+ *
+ * Note: The API handles all the exception internally, in case of any error
+ * unexpanded location code will be returned as it is.
+ *
+ * @param[in] unexpandedLocationCode - Unexpanded location code.
+ * @param[in] parsedVpdMap - Parsed VPD map.
+ * @return Expanded location code. In case of any error, unexpanded is returned
+ * as it is.
+ */
+inline std::string
+    getExpandedLocationCode(const std::string& unexpandedLocationCode,
+                            const types::VPDMapVariant& parsedVpdMap)
+{
+    auto expanded{unexpandedLocationCode};
+
+    try
+    {
+        // Expanded location code is formed by combining two keywords
+        // depending on type in unexpanded one. Second one is always "SE".
+        std::string kwd1, kwd2{constants::kwdSE};
+
+        // interface to search for required keywords;
+        std::string kwdInterface;
+
+        // record which holds the required keywords.
+        std::string recordName;
+
+        auto pos = unexpandedLocationCode.find("fcs");
+        if (pos != std::string::npos)
+        {
+            kwd1 = constants::kwdFC;
+            kwdInterface = constants::vcenInf;
+            recordName = constants::recVCEN;
+        }
+        else
+        {
+            pos = unexpandedLocationCode.find("mts");
+            if (pos != std::string::npos)
+            {
+                kwd1 = constants::kwdTM;
+                kwdInterface = constants::vsysInf;
+                recordName = constants::recVSYS;
+            }
+            else
+            {
+                throw std::runtime_error(
+                    "Error detecting type of unexpanded location code.");
+            }
+        }
+
+        std::string firstKwdValue, secondKwdValue;
+
+        if (auto ipzVpdMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap);
+            ipzVpdMap && (*ipzVpdMap).find(recordName) != (*ipzVpdMap).end())
+        {
+            auto itrToVCEN = (*ipzVpdMap).find(recordName);
+            // The exceptions will be cautght at end.
+            getKwVal(itrToVCEN->second, kwd1, firstKwdValue);
+            getKwVal(itrToVCEN->second, kwd2, secondKwdValue);
+        }
+        else
+        {
+            std::array<const char*, 1> interfaceList = {kwdInterface.c_str()};
+
+            types::MapperGetObject mapperRetValue = dbusUtility::getObjectMap(
+                std::string(constants::systemVpdInvPath), interfaceList);
+
+            if (mapperRetValue.empty())
+            {
+                throw std::runtime_error("Mapper failed to get service");
+            }
+
+            const std::string& serviceName = std::get<0>(mapperRetValue.at(0));
+
+            auto retVal = dbusUtility::readDbusProperty(
+                serviceName, std::string(constants::systemVpdInvPath),
+                kwdInterface, kwd1);
+
+            if (auto kwdVal = std::get_if<types::BinaryVector>(&retVal))
+            {
+                firstKwdValue.assign(
+                    reinterpret_cast<const char*>(kwdVal->data()),
+                    kwdVal->size());
+            }
+            else
+            {
+                throw std::runtime_error(
+                    "Failed to read value of " + kwd1 + " from Bus");
+            }
+
+            retVal = dbusUtility::readDbusProperty(
+                serviceName, std::string(constants::systemVpdInvPath),
+                kwdInterface, kwd2);
+
+            if (auto kwdVal = std::get_if<types::BinaryVector>(&retVal))
+            {
+                secondKwdValue.assign(
+                    reinterpret_cast<const char*>(kwdVal->data()),
+                    kwdVal->size());
+            }
+            else
+            {
+                throw std::runtime_error(
+                    "Failed to read value of " + kwd2 + " from Bus");
+            }
+        }
+
+        if (unexpandedLocationCode.find("fcs") != std::string::npos)
+        {
+            // TODO: See if ND0 can be placed in the JSON
+            expanded.replace(
+                pos, 3, firstKwdValue.substr(0, 4) + ".ND0." + secondKwdValue);
+        }
+        else
+        {
+            replace(firstKwdValue.begin(), firstKwdValue.end(), '-', '.');
+            expanded.replace(pos, 3, firstKwdValue + "." + secondKwdValue);
+        }
+    }
+    catch (const std::exception& ex)
+    {
+        logging::logMessage("Failed to expand location code with exception: " +
+                            std::string(ex.what()));
+    }
+
+    return expanded;
+}
+
+/**
+ * @brief An API to get VPD in a vector.
+ *
+ * The vector is required by the respective parser to fill the VPD map.
+ * Note: API throws exception in case of failure. Caller needs to handle.
+ *
+ * @param[in] vpdFilePath - EEPROM path of the FRU.
+ * @param[out] vpdVector - VPD in vector form.
+ * @param[in] vpdStartOffset - Offset of VPD data in EEPROM.
+ */
+inline void getVpdDataInVector(const std::string& vpdFilePath,
+                               types::BinaryVector& vpdVector,
+                               size_t& vpdStartOffset)
+{
+    try
+    {
+        std::fstream vpdFileStream;
+        vpdFileStream.exceptions(
+            std::ifstream::badbit | std::ifstream::failbit);
+        vpdFileStream.open(vpdFilePath, std::ios::in | std::ios::binary);
+        auto vpdSizeToRead = std::min(std::filesystem::file_size(vpdFilePath),
+                                      static_cast<uintmax_t>(65504));
+        vpdVector.resize(vpdSizeToRead);
+
+        vpdFileStream.seekg(vpdStartOffset, std::ios_base::beg);
+        vpdFileStream.read(reinterpret_cast<char*>(&vpdVector[0]),
+                           vpdSizeToRead);
+
+        vpdVector.resize(vpdFileStream.gcount());
+        vpdFileStream.clear(std::ios_base::eofbit);
+    }
+    catch (const std::ifstream::failure& fail)
+    {
+        std::cerr << "Exception in file handling [" << vpdFilePath
+                  << "] error : " << fail.what();
+        throw;
+    }
+}
+
+/**
+ * @brief An API to get D-bus representation of given VPD keyword.
+ *
+ * @param[in] i_keywordName - VPD keyword name.
+ *
+ * @return D-bus representation of given keyword.
+ */
+inline std::string getDbusPropNameForGivenKw(const std::string& i_keywordName)
+{
+    // Check for "#" prefixed VPD keyword.
+    if ((i_keywordName.size() == vpd::constants::TWO_BYTES) &&
+        (i_keywordName.at(0) == constants::POUND_KW))
+    {
+        // D-bus doesn't support "#". Replace "#" with "PD_" for those "#"
+        // prefixed keywords.
+        return (std::string(constants::POUND_KW_PREFIX) +
+                i_keywordName.substr(1));
+    }
+
+    // Return the keyword name back, if D-bus representation is same as the VPD
+    // keyword name.
+    return i_keywordName;
+}
+
+/**
+ * @brief API to find CCIN in parsed VPD map.
+ *
+ * Few FRUs need some special handling. To identify those FRUs CCIN are used.
+ * The API will check from parsed VPD map if the FRU is the one with desired
+ * CCIN.
+ *
+ * @throw std::runtime_error
+ * @throw DataException
+ *
+ * @param[in] i_JsonObject - Any JSON which contains CCIN tag to match.
+ * @param[in] i_parsedVpdMap - Parsed VPD map.
+ * @return True if found, false otherwise.
+ */
+inline bool findCcinInVpd(const nlohmann::json& i_JsonObject,
+                          const types::VPDMapVariant& i_parsedVpdMap)
+{
+    if (i_JsonObject.empty())
+    {
+        throw std::runtime_error("Json object is empty. Can't find CCIN");
+    }
+
+    if (auto l_ipzVPDMap = std::get_if<types::IPZVpdMap>(&i_parsedVpdMap))
+    {
+        auto l_itrToRec = (*l_ipzVPDMap).find("VINI");
+        if (l_itrToRec == (*l_ipzVPDMap).end())
+        {
+            throw DataException(
+                "VINI record not found in parsed VPD. Can't find CCIN");
+        }
+
+        std::string l_ccinFromVpd;
+        vpdSpecificUtility::getKwVal(l_itrToRec->second, "CC", l_ccinFromVpd);
+        if (l_ccinFromVpd.empty())
+        {
+            throw DataException("Empty CCIN value in VPD map. Can't find CCIN");
+        }
+
+        transform(l_ccinFromVpd.begin(), l_ccinFromVpd.end(),
+                  l_ccinFromVpd.begin(), ::toupper);
+
+        for (std::string l_ccinValue : i_JsonObject["ccin"])
+        {
+            transform(l_ccinValue.begin(), l_ccinValue.end(),
+                      l_ccinValue.begin(), ::toupper);
+
+            if (l_ccinValue.compare(l_ccinFromVpd) ==
+                constants::STR_CMP_SUCCESS)
+            {
+                // CCIN found
+                return true;
+            }
+        }
+
+        logging::logMessage("No match found for CCIN");
+        return false;
+    }
+
+    logging::logMessage("VPD type not supported. Can't find CCIN");
+    return false;
+}
+
+/**
+ * @brief API to reset data of a FRU populated under PIM.
+ *
+ * This API resets the data for particular interfaces of a FRU under PIM.
+ *
+ * @param[in] i_objectPath - DBus object path of the FRU.
+ * @param[in] io_interfaceMap - Interface and its properties map.
+ */
+inline void resetDataUnderPIM(const std::string& i_objectPath,
+                              types::InterfaceMap& io_interfaceMap)
+{
+    try
+    {
+        std::array<const char*, 0> l_interfaces;
+        const types::MapperGetObject& l_getObjectMap =
+            dbusUtility::getObjectMap(i_objectPath, l_interfaces);
+
+        const std::vector<std::string>& l_vpdRelatedInterfaces{
+            constants::operationalStatusInf, constants::inventoryItemInf,
+            constants::assetInf};
+
+        for (const auto& [l_service, l_interfaceList] : l_getObjectMap)
+        {
+            if (l_service.compare(constants::pimServiceName) !=
+                constants::STR_CMP_SUCCESS)
+            {
+                continue;
+            }
+
+            for (const auto& l_interface : l_interfaceList)
+            {
+                if ((l_interface.find(constants::ipzVpdInf) !=
+                     std::string::npos) ||
+                    ((std::find(l_vpdRelatedInterfaces.begin(),
+                                l_vpdRelatedInterfaces.end(), l_interface)) !=
+                     l_vpdRelatedInterfaces.end()))
+                {
+                    const types::PropertyMap& l_propertyValueMap =
+                        dbusUtility::getPropertyMap(l_service, i_objectPath,
+                                                    l_interface);
+
+                    types::PropertyMap l_propertyMap;
+
+                    for (const auto& l_aProperty : l_propertyValueMap)
+                    {
+                        const std::string& l_propertyName = l_aProperty.first;
+                        const auto& l_propertyValue = l_aProperty.second;
+
+                        if (std::holds_alternative<types::BinaryVector>(
+                                l_propertyValue))
+                        {
+                            l_propertyMap.emplace(l_propertyName,
+                                                  types::BinaryVector{});
+                        }
+                        else if (std::holds_alternative<std::string>(
+                                     l_propertyValue))
+                        {
+                            l_propertyMap.emplace(l_propertyName,
+                                                  std::string{});
+                        }
+                        else if (std::holds_alternative<bool>(l_propertyValue))
+                        {
+                            // ToDo -- Update the functional status property
+                            // to true.
+                            if (l_propertyName.compare("Present") ==
+                                constants::STR_CMP_SUCCESS)
+                            {
+                                l_propertyMap.emplace(l_propertyName, false);
+                            }
+                        }
+                    }
+                    io_interfaceMap.emplace(l_interface,
+                                            std::move(l_propertyMap));
+                }
+            }
+        }
+    }
+    catch (const std::exception& l_ex)
+    {
+        logging::logMessage("Failed to remove VPD for FRU: " + i_objectPath +
+                            " with error: " + std::string(l_ex.what()));
+    }
+}
+} // namespace vpdSpecificUtility
+} // namespace vpd
