#include "config.h"

#include "common_utility.hpp"
#include "defines.hpp"
#include "editor_impl.hpp"
#include "ibm_vpd_utils.hpp"
#include "ipz_parser.hpp"
#include "keyword_vpd_parser.hpp"
#include "memory_vpd_parser.hpp"
#include "parser_factory.hpp"
#include "vpd_exceptions.hpp"

#include <assert.h>
#include <ctype.h>

#include <CLI/CLI.hpp>
#include <boost/algorithm/string.hpp>
#include <gpiod.hpp>
#include <phosphor-logging/log.hpp>

#include <algorithm>
#include <cstdarg>
#include <exception>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <iterator>
#include <regex>
#include <thread>

using namespace std;
using namespace openpower::vpd;
using namespace CLI;
using namespace vpd::keyword::parser;
using namespace openpower::vpd::constants;
namespace fs = filesystem;
using json = nlohmann::json;
using namespace openpower::vpd::parser::factory;
using namespace openpower::vpd::inventory;
using namespace openpower::vpd::memory::parser;
using namespace openpower::vpd::parser::interface;
using namespace openpower::vpd::exceptions;
using namespace phosphor::logging;
using namespace openpower::vpd::manager::editor;

/**
 * @brief API declaration, Populate Dbus.
 *
 * This method invokes all the populateInterface functions
 * and notifies PIM about dbus object.
 *
 * @param[in] vpdMap - Either IPZ vpd map or Keyword vpd map based on the
 * input.
 * @param[in] js - Inventory json object
 * @param[in] filePath - Path of the vpd file
 * @param[in] preIntrStr - Interface string
 */
template <typename T>
static void populateDbus(T& vpdMap, nlohmann::json& js, const string& filePath);

/**
 * @brief Returns the BMC state
 */
static auto getBMCState()
{
    std::string bmcState;
    try
    {
        auto bus = sdbusplus::bus::new_default();
        auto properties = bus.new_method_call(
            "xyz.openbmc_project.State.BMC", "/xyz/openbmc_project/state/bmc0",
            "org.freedesktop.DBus.Properties", "Get");
        properties.append("xyz.openbmc_project.State.BMC");
        properties.append("CurrentBMCState");
        auto result = bus.call(properties);
        std::variant<std::string> val;
        result.read(val);
        if (auto pVal = std::get_if<std::string>(&val))
        {
            bmcState = *pVal;
        }
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        // Ignore any error
        std::cerr << "Failed to get BMC state: " << e.what() << "\n";
        // Since we failed set to not ready state
        bmcState = "xyz.openbmc_project.State.BMC.BMCState.NotReady";
    }
    return bmcState;
}

/**
 * @brief Check if the FRU is in the cache
 *
 * Checks if the FRU associated with the supplied D-Bus object path is already
 * on D-Bus. This can be used to test if a VPD collection is required for this
 * FRU. It uses the "xyz.openbmc_project.Inventory.Item, Present" property to
 * determine the presence of a FRU in the cache.
 *
 * @param objectPath - The D-Bus object path without the PIM prefix.
 * @return true if the object exists on D-Bus, false otherwise.
 */
static auto isFruInVpdCache(const std::string& objectPath)
{
    try
    {
        auto bus = sdbusplus::bus::new_default();
        auto invPath = std::string{pimPath} + objectPath;
        auto props = bus.new_method_call(
            "xyz.openbmc_project.Inventory.Manager", invPath.c_str(),
            "org.freedesktop.DBus.Properties", "Get");
        props.append("xyz.openbmc_project.Inventory.Item");
        props.append("Present");
        auto result = bus.call(props);
        std::variant<bool> present;
        result.read(present);
        if (auto pVal = std::get_if<bool>(&present))
        {
            return *pVal;
        }
        return false;
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        std::cout << "FRU: " << objectPath << " not in D-Bus\n";
        // Assume not present in case of an error
        return false;
    }
}

/**
 * @brief Check if VPD recollection is needed for the given EEPROM
 *
 * Not all FRUs can be swapped at BMC ready state. This function does the
 * following:
 * -- Check if the FRU is marked as "pluggableAtStandby" OR
 *    "concurrentlyMaintainable". If so, return true.
 * -- Check if we are at BMC NotReady state. If we are, then return true.
 * -- Else check if the FRU is not present in the VPD cache (to cover for VPD
 *    force collection). If not found in the cache, return true.
 * -- Else return false.
 *
 * @param js - JSON Object.
 * @param filePath - The EEPROM file.
 * @return true if collection should be attempted, false otherwise.
 */
static auto needsRecollection(const nlohmann::json& js, const string& filePath)
{
    if (js["frus"][filePath].at(0).value("pluggableAtStandby", false) ||
        js["frus"][filePath].at(0).value("concurrentlyMaintainable", false))
    {
        return true;
    }
    if (getBMCState() == "xyz.openbmc_project.State.BMC.BMCState.NotReady")
    {
        return true;
    }
    if (!isFruInVpdCache(js["frus"][filePath].at(0).value("inventoryPath", "")))
    {
        return true;
    }
    return false;
}

/**
 * @brief Expands location codes
 */
static auto expandLocationCode(const string& unexpanded, const Parsed& vpdMap,
                               bool isSystemVpd)
{
    auto expanded{unexpanded};
    static constexpr auto SYSTEM_OBJECT = "/system/chassis/motherboard";
    static constexpr auto VCEN_IF = "com.ibm.ipzvpd.VCEN";
    static constexpr auto VSYS_IF = "com.ibm.ipzvpd.VSYS";
    size_t idx = expanded.find("fcs");
    try
    {
        if (idx != string::npos)
        {
            string fc{};
            string se{};
            if (isSystemVpd)
            {
                const auto& fcData = vpdMap.at("VCEN").at("FC");
                const auto& seData = vpdMap.at("VCEN").at("SE");
                fc = string(fcData.data(), fcData.size());
                se = string(seData.data(), seData.size());
            }
            else
            {
                fc = readBusProperty(SYSTEM_OBJECT, VCEN_IF, "FC");
                se = readBusProperty(SYSTEM_OBJECT, VCEN_IF, "SE");
            }

            // TODO: See if ND0 can be placed in the JSON
            expanded.replace(idx, 3, fc.substr(0, 4) + ".ND0." + se);
        }
        else
        {
            idx = expanded.find("mts");
            if (idx != string::npos)
            {
                string mt{};
                string se{};
                if (isSystemVpd)
                {
                    const auto& mtData = vpdMap.at("VSYS").at("TM");
                    const auto& seData = vpdMap.at("VSYS").at("SE");
                    mt = string(mtData.data(), mtData.size());
                    se = string(seData.data(), seData.size());
                }
                else
                {
                    mt = readBusProperty(SYSTEM_OBJECT, VSYS_IF, "TM");
                    se = readBusProperty(SYSTEM_OBJECT, VSYS_IF, "SE");
                }

                replace(mt.begin(), mt.end(), '-', '.');
                expanded.replace(idx, 3, mt + "." + se);
            }
        }
    }
    catch (const exception& e)
    {
        std::cerr << "Failed to expand location code with exception: "
                  << e.what() << "\n";
    }
    return expanded;
}

/**
 * @brief Populate FRU specific interfaces.
 *
 * This is a common method which handles both
 * ipz and keyword specific interfaces thus,
 * reducing the code redundancy.
 * @param[in] map - Reference to the innermost keyword-value map.
 * @param[in] preIntrStr - Reference to the interface string.
 * @param[out] interfaces - Reference to interface map.
 */
template <typename T>
static void populateFruSpecificInterfaces(
    const T& map, const string& preIntrStr, inventory::InterfaceMap& interfaces)
{
    inventory::PropertyMap prop;

    for (const auto& kwVal : map)
    {
        auto kw = kwVal.first;

        if (kw[0] == '#')
        {
            kw = string("PD_") + kw[1];
        }
        else if (isdigit(kw[0]))
        {
            kw = string("N_") + kw;
        }
        if constexpr (is_same<T, KeywordVpdMap>::value)
        {
            if (auto keywordValue = get_if<Binary>(&kwVal.second))
            {
                Binary vec((*keywordValue).begin(), (*keywordValue).end());
                prop.emplace(move(kw), move(vec));
            }
            else if (auto keywordValue = get_if<std::string>(&kwVal.second))
            {
                Binary vec((*keywordValue).begin(), (*keywordValue).end());
                prop.emplace(move(kw), move(vec));
            }
            else if (auto keywordValue = get_if<size_t>(&kwVal.second))
            {
                if (kw == "MemorySizeInKB")
                {
                    inventory::PropertyMap memProp;
                    memProp.emplace(move(kw), ((*keywordValue)));
                    interfaces.emplace(
                        "xyz.openbmc_project.Inventory.Item.Dimm",
                        move(memProp));
                }
                else
                {
                    std::cerr << "Unknown Keyword[" << kw << "] found ";
                }
            }
            else
            {
                std::cerr << "Unknown Variant found ";
            }
        }
        else
        {
            Binary vec(kwVal.second.begin(), kwVal.second.end());
            prop.emplace(move(kw), move(vec));
        }
    }

    interfaces.emplace(preIntrStr, move(prop));
}

/**
 * @brief Populate Interfaces.
 *
 * This method populates common and extra interfaces to dbus.
 * @param[in] js - json object
 * @param[out] interfaces - Reference to interface map
 * @param[in] vpdMap - Reference to the parsed vpd map.
 * @param[in] isSystemVpd - Denotes whether we are collecting the system VPD.
 */
template <typename T>
static void populateInterfaces(const nlohmann::json& js,
                               inventory::InterfaceMap& interfaces,
                               const T& vpdMap, bool isSystemVpd)
{
    for (const auto& ifs : js.items())
    {
        string inf = ifs.key();
        inventory::PropertyMap props;

        for (const auto& itr : ifs.value().items())
        {
            const string& busProp = itr.key();

            if (itr.value().is_boolean())
            {
                props.emplace(busProp, itr.value().get<bool>());
            }
            else if (itr.value().is_string())
            {
                if (busProp == "LocationCode" && inf == IBM_LOCATION_CODE_INF)
                {
                    std::string prop;
                    if constexpr (is_same<T, Parsed>::value)
                    {
                        // TODO deprecate the com.ibm interface later
                        prop = expandLocationCode(itr.value().get<string>(),
                                                  vpdMap, isSystemVpd);
                    }
                    else if constexpr (is_same<T, KeywordVpdMap>::value)
                    {
                        // Send empty Parsed object to expandLocationCode api.
                        prop = expandLocationCode(itr.value().get<string>(),
                                                  Parsed{}, false);
                    }
                    props.emplace(busProp, prop);
                    interfaces.emplace(XYZ_LOCATION_CODE_INF, props);
                    interfaces.emplace(IBM_LOCATION_CODE_INF, props);
                }
                else
                {
                    props.emplace(busProp, itr.value().get<string>());
                }
            }
            else if (itr.value().is_array())
            {
                try
                {
                    props.emplace(busProp, itr.value().get<Binary>());
                }
                catch (const nlohmann::detail::type_error& e)
                {
                    std::cerr << "Type exception: " << e.what() << "\n";
                    // Ignore any type errors
                }
            }
            else if (itr.value().is_object())
            {
                const string& rec = itr.value().value("recordName", "");
                const string& kw = itr.value().value("keywordName", "");
                const string& encoding = itr.value().value("encoding", "");

                if constexpr (is_same<T, Parsed>::value)
                {
                    if (!rec.empty() && !kw.empty() && vpdMap.count(rec) &&
                        vpdMap.at(rec).count(kw))
                    {
                        auto encoded =
                            encodeKeyword(vpdMap.at(rec).at(kw), encoding);
                        props.emplace(busProp, encoded);
                    }
                }
                else if constexpr (is_same<T, KeywordVpdMap>::value)
                {
                    if (!kw.empty() && vpdMap.count(kw))
                    {
                        if (auto kwValue = get_if<Binary>(&vpdMap.at(kw)))
                        {
                            auto prop =
                                string((*kwValue).begin(), (*kwValue).end());

                            auto encoded = encodeKeyword(prop, encoding);

                            props.emplace(busProp, encoded);
                        }
                        else if (auto kwValue =
                                     get_if<std::string>(&vpdMap.at(kw)))
                        {
                            auto prop =
                                string((*kwValue).begin(), (*kwValue).end());

                            auto encoded = encodeKeyword(prop, encoding);

                            props.emplace(busProp, encoded);
                        }
                        else if (auto uintValue =
                                     get_if<size_t>(&vpdMap.at(kw)))
                        {
                            props.emplace(busProp, *uintValue);
                        }
                        else
                        {
                            std::cerr << " Unknown Keyword [" << kw
                                      << "] Encountered";
                        }
                    }
                }
            }
            else if (itr.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.
                props.emplace(busProp, itr.value().get<size_t>());
            }
        }
        insertOrMerge(interfaces, inf, move(props));
    }
}

/**
 * @brief This API checks if this FRU is pcie_devices. If yes then it further
 *        checks whether it is PASS1 planar.
 */
static bool isThisPcieOnPass1planar(const nlohmann::json& js,
                                    const string& file)
{
    auto isThisPCIeDev = false;
    auto isPASS1 = false;

    // Check if it is a PCIE device
    if (js["frus"].find(file) != js["frus"].end())
    {
        if ((js["frus"][file].at(0).find("extraInterfaces") !=
             js["frus"][file].at(0).end()))
        {
            if (js["frus"][file].at(0)["extraInterfaces"].find(
                    "xyz.openbmc_project.Inventory.Item.PCIeDevice") !=
                js["frus"][file].at(0)["extraInterfaces"].end())
            {
                isThisPCIeDev = true;
            }
        }
    }

    if (isThisPCIeDev)
    {
        // Collect HW version and SystemType to know if it is PASS1 planar.
        auto bus = sdbusplus::bus::new_default();
        auto property1 = bus.new_method_call(
            INVENTORY_MANAGER_SERVICE,
            "/xyz/openbmc_project/inventory/system/chassis/motherboard",
            "org.freedesktop.DBus.Properties", "Get");
        property1.append("com.ibm.ipzvpd.VINI");
        property1.append("HW");
        auto result1 = bus.call(property1);
        inventory::Value hwVal;
        result1.read(hwVal);

        // SystemType
        auto property2 = bus.new_method_call(
            INVENTORY_MANAGER_SERVICE,
            "/xyz/openbmc_project/inventory/system/chassis/motherboard",
            "org.freedesktop.DBus.Properties", "Get");
        property2.append("com.ibm.ipzvpd.VSBP");
        property2.append("IM");
        auto result2 = bus.call(property2);
        inventory::Value imVal;
        result2.read(imVal);

        auto pVal1 = get_if<Binary>(&hwVal);
        auto pVal2 = get_if<Binary>(&imVal);

        if (pVal1 && pVal2)
        {
            auto hwVersion = *pVal1;
            auto systemType = *pVal2;

            // IM kw for Everest
            Binary everestSystem{80, 00, 48, 00};

            if (systemType == everestSystem)
            {
                if (hwVersion[1] < 21)
                {
                    isPASS1 = true;
                }
            }
            else if (hwVersion[1] < 2)
            {
                isPASS1 = true;
            }
        }
    }

    return (isThisPCIeDev && isPASS1);
}

/** Performs any pre-action needed to get the FRU setup for collection.
 *
 * @param[in] json - json object
 * @param[in] file - eeprom file path
 */
static void preAction(const nlohmann::json& json, const string& file)
{
    if ((json["frus"][file].at(0)).find("preAction") ==
        json["frus"][file].at(0).end())
    {
        return;
    }

    try
    {
        if (executePreAction(json, file))
        {
            if (json["frus"][file].at(0).find("devAddress") !=
                json["frus"][file].at(0).end())
            {
                // Now bind the device
                string bind = json["frus"][file].at(0).value("devAddress", "");
                std::cout << "Binding device " << bind << std::endl;
                string bindCmd = string("echo \"") + bind +
                                 string("\" > /sys/bus/i2c/drivers/at24/bind");
                std::cout << bindCmd << std::endl;
                executeCmd(bindCmd);

                // Check if device showed up (test for file)
                if (!fs::exists(file))
                {
                    std::cerr
                        << "EEPROM " << file
                        << " does not exist. Take failure action" << std::endl;
                    // If not, then take failure postAction
                    executePostFailAction(json, file);
                }
            }
            else
            {
                // missing required information
                std::cerr << "VPD inventory JSON missing basic information of "
                             "preAction "
                             "for this FRU : ["
                          << file << "]. Executing executePostFailAction."
                          << std::endl;

                // Take failure postAction
                executePostFailAction(json, file);
                return;
            }
        }
        else
        {
            // If the FRU is not there, clear the VINI/CCIN data.
            // Entity 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& invPath =
                json["frus"][file].at(0).value("inventoryPath", "");

            if (!invPath.empty())
            {
                inventory::ObjectMap pimObjMap{
                    {invPath, {{"com.ibm.ipzvpd.VINI", {{"CC", Binary{}}}}}}};

                common::utility::callPIM(move(pimObjMap));
            }
            else
            {
                throw std::runtime_error("Path empty in Json");
            }
        }
    }
    catch (const GpioException& e)
    {
        PelAdditionalData additionalData{};
        additionalData.emplace("DESCRIPTION", e.what());
        createPEL(additionalData, PelSeverity::WARNING, errIntfForGpioError,
                  nullptr);
    }
}

/**
 * @brief Fills the Decorator.AssetTag property into the interfaces map
 *
 * This function should only be called in cases where we did not find a JSON
 * symlink. A missing symlink in /var/lib will be considered as a factory reset
 * and this function will be used to default the AssetTag property.
 *
 * @param interfaces A possibly pre-populated map of inetrfaces to properties.
 * @param vpdMap A VPD map of the system VPD data.
 */
static void fillAssetTag(inventory::InterfaceMap& interfaces,
                         const Parsed& vpdMap)
{
    // Read the system serial number and MTM
    // Default asset tag is Server-MTM-System Serial
    inventory::Interface assetIntf{
        "xyz.openbmc_project.Inventory.Decorator.AssetTag"};
    inventory::PropertyMap assetTagProps;
    std::string defaultAssetTag =
        std::string{"Server-"} + getKwVal(vpdMap, "VSYS", "TM") +
        std::string{"-"} + getKwVal(vpdMap, "VSYS", "SE");
    assetTagProps.emplace("AssetTag", defaultAssetTag);
    insertOrMerge(interfaces, assetIntf, std::move(assetTagProps));
}

/**
 * @brief Set certain one time properties in the inventory
 * Use this function to insert the Functional and Enabled properties into the
 * inventory map. This function first checks if the object in question already
 * has these properties hosted on D-Bus, if the property is already there, it is
 * not modified, hence the name "one time". If the property is not already
 * present, it will be added to the map with a suitable default value (true for
 * Functional and Enabled)
 *
 * @param[in] object - The inventory D-Bus object without the inventory prefix.
 * @param[in,out] interfaces - Reference to a map of inventory interfaces to
 * which the properties will be attached.
 */
static void setOneTimeProperties(const std::string& object,
                                 inventory::InterfaceMap& interfaces)
{
    auto bus = sdbusplus::bus::new_default();
    auto objectPath = INVENTORY_PATH + object;
    auto prop = bus.new_method_call("xyz.openbmc_project.Inventory.Manager",
                                    objectPath.c_str(),
                                    "org.freedesktop.DBus.Properties", "Get");
    prop.append("xyz.openbmc_project.State.Decorator.OperationalStatus");
    prop.append("Functional");
    try
    {
        auto result = bus.call(prop);
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        // Treat as property unavailable
        inventory::PropertyMap prop;
        prop.emplace("Functional", true);
        interfaces.emplace(
            "xyz.openbmc_project.State.Decorator.OperationalStatus",
            move(prop));
    }
    prop = bus.new_method_call("xyz.openbmc_project.Inventory.Manager",
                               objectPath.c_str(),
                               "org.freedesktop.DBus.Properties", "Get");
    prop.append("xyz.openbmc_project.Object.Enable");
    prop.append("Enabled");
    try
    {
        auto result = bus.call(prop);
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        // Treat as property unavailable
        inventory::PropertyMap prop;
        prop.emplace("Enabled", true);
        interfaces.emplace("xyz.openbmc_project.Object.Enable", move(prop));
    }
}

/**
 * @brief Prime the Inventory
 * Prime the inventory by populating only the location code,
 * type interface and the inventory object for the frus
 * which are not system vpd fru.
 *
 * @param[in] jsObject - Reference to vpd inventory json object
 * @param[in] vpdMap -  Reference to the parsed vpd map
 *
 * @returns Map of items in extraInterface.
 */
template <typename T>
inventory::ObjectMap
    primeInventory(const nlohmann::json& jsObject, const T& vpdMap)
{
    inventory::ObjectMap objects;

    for (auto& itemFRUS : jsObject["frus"].items())
    {
        for (auto& itemEEPROM : itemFRUS.value())
        {
            // Take pre actions if needed
            if (itemEEPROM.find("preAction") != itemEEPROM.end())
            {
                preAction(jsObject, itemFRUS.key());
            }

            inventory::InterfaceMap interfaces;
            inventory::Object object(itemEEPROM.at("inventoryPath"));

            if ((itemFRUS.key() != systemVpdFilePath) &&
                !itemEEPROM.value("noprime", false))
            {
                inventory::PropertyMap presProp;

                // Do not populate Present property for frus whose
                // synthesized=true. synthesized=true says the fru VPD is
                // synthesized and owned by a separate component.
                // In some cases, the FRU has its own VPD, but still a separate
                // application handles the FRU's presence. So VPD parser skips
                // populating Present property by checking the JSON flag,
                // "handlePresence".
                if (!itemEEPROM.value("synthesized", false))
                {
                    if (itemEEPROM.value("handlePresence", true))
                    {
                        presProp.emplace("Present", false);
                        interfaces.emplace("xyz.openbmc_project.Inventory.Item",
                                           presProp);

                        if ((jsObject["frus"][itemFRUS.key()].at(0).contains(
                                "extraInterfaces")) &&
                            (jsObject["frus"][itemFRUS.key()]
                                 .at(0)["extraInterfaces"]
                                 .contains("xyz.openbmc_project.Inventory."
                                           "Item.PCIeDevice")))
                        {
                            // check if any subtree exist under the parent
                            // path.
                            std::vector<std::string> interfaceList{
                                "xyz.openbmc_project.Inventory.Item"};
                            MapperResponse subTree =
                                getObjectSubtreeForInterfaces(
                                    INVENTORY_PATH + std::string(object), 0,
                                    interfaceList);

                            for (auto [objectPath, serviceInterfaceMap] :
                                 subTree)
                            {
                                std::string subTreeObjPath{objectPath};
                                // Strip any inventory prefix in path
                                if (subTreeObjPath.find(INVENTORY_PATH) == 0)
                                {
                                    subTreeObjPath = subTreeObjPath.substr(
                                        sizeof(INVENTORY_PATH) - 1);
                                }

                                // If subtree present, set its presence to
                                // false and functional to true.
                                inventory::ObjectMap objectMap{
                                    {subTreeObjPath,
                                     {{"xyz.openbmc_project.State."
                                       "Decorator."
                                       "OperationalStatus",
                                       {{"Functional", true}}},
                                      {"xyz.openbmc_project.Inventory.Item",
                                       {{"Present", false}}}}}};

                                common::utility::callPIM(move(objectMap));
                            }
                        }
                    }
                }

                setOneTimeProperties(object, interfaces);
                if (itemEEPROM.find("extraInterfaces") != itemEEPROM.end())
                {
                    for (const auto& eI : itemEEPROM["extraInterfaces"].items())
                    {
                        inventory::PropertyMap props;
                        if (eI.key() == IBM_LOCATION_CODE_INF)
                        {
                            if constexpr (std::is_same<T, Parsed>::value)
                            {
                                for (auto& lC : eI.value().items())
                                {
                                    auto propVal = expandLocationCode(
                                        lC.value().get<string>(), vpdMap, true);

                                    props.emplace(move(lC.key()),
                                                  move(propVal));
                                    interfaces.emplace(XYZ_LOCATION_CODE_INF,
                                                       props);
                                    interfaces.emplace(move(eI.key()),
                                                       move(props));
                                }
                            }
                        }
                        else if (eI.key() ==
                                 "xyz.openbmc_project.Inventory.Item")
                        {
                            for (auto& val : eI.value().items())
                            {
                                if (val.key() == "PrettyName")
                                {
                                    presProp.emplace(val.key(),
                                                     val.value().get<string>());
                                }
                            }
                            // Use insert_or_assign here as we may already have
                            // inserted the present property only earlier in
                            // this function under this same interface.
                            interfaces.insert_or_assign(eI.key(),
                                                        move(presProp));
                        }
                        else
                        {
                            interfaces.emplace(move(eI.key()), move(props));
                        }
                    }
                }
                objects.emplace(move(object), move(interfaces));
            }
        }
    }
    return objects;
}

/**
 * @brief This API executes command to set environment variable
 *        And then reboot the system
 * @param[in] key   -env key to set new value
 * @param[in] value -value to set.
 */
void setEnvAndReboot(const string& key, const string& value)
{
    // set env and reboot and break.
    executeCmd("/sbin/fw_setenv", key, value);
    log<level::INFO>("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);
}

/*
 * @brief This API checks for env var fitconfig.
 *        If not initialised OR updated as per the current system type,
 *        update this env var and reboot the system.
 *
 * @param[in] systemType IM kwd in vpd tells about which system type it is.
 * */
void setDevTreeEnv(const string& systemType)
{
    // Init with default dtb
    string newDeviceTree = "conf-aspeed-bmc-ibm-rainier-p1.dtb";
    static const deviceTreeMap deviceTreeSystemTypeMap = {
        {RAINIER_2U, "conf-aspeed-bmc-ibm-rainier-p1.dtb"},
        {RAINIER_2U_V2, "conf-aspeed-bmc-ibm-rainier.dtb"},
        {RAINIER_4U, "conf-aspeed-bmc-ibm-rainier-4u-p1.dtb"},
        {RAINIER_4U_V2, "conf-aspeed-bmc-ibm-rainier-4u.dtb"},
        {RAINIER_1S4U, "conf-aspeed-bmc-ibm-rainier-1s4u.dtb"},
        {EVEREST, "conf-aspeed-bmc-ibm-everest.dtb"},
        {EVEREST_V2, "conf-aspeed-bmc-ibm-everest.dtb"},
        {BONNELL, "conf-aspeed-bmc-ibm-bonnell.dtb"},
        {BLUERIDGE_2U, "conf-aspeed-bmc-ibm-blueridge-p1.dtb"},
        {BLUERIDGE_2U_V2, "conf-aspeed-bmc-ibm-blueridge.dtb"},
        {BLUERIDGE_4U, "conf-aspeed-bmc-ibm-blueridge-4u-p1.dtb"},
        {BLUERIDGE_4U_V2, "conf-aspeed-bmc-ibm-blueridge-4u.dtb"},
        {BLUERIDGE_1S4U, "conf-aspeed-bmc-ibm-blueridge-1s4u.dtb"},
        {FUJI, "conf-aspeed-bmc-ibm-fuji.dtb"},
        {HUYGENS, "conf-aspeed-bmc-ibm-huygens.dtb"},
        {FUJI_V2, "conf-aspeed-bmc-ibm-fuji.dtb"}};

    if (deviceTreeSystemTypeMap.find(systemType) !=
        deviceTreeSystemTypeMap.end())
    {
        newDeviceTree = deviceTreeSystemTypeMap.at(systemType);
    }
    else
    {
        // System type not supported
        string err = "This System type not found/supported in dtb table " +
                     systemType +
                     ".Please check the HW and IM keywords in the system "
                     "VPD.Breaking...";

        // map to hold additional data in case of logging pel
        PelAdditionalData additionalData{};
        additionalData.emplace("DESCRIPTION", err);
        createPEL(additionalData, PelSeverity::WARNING,
                  errIntfForInvalidSystemType, nullptr);
        exit(-1);
    }

    string readVarValue;
    bool envVarFound = false;

    vector<string> output = executeCmd("/sbin/fw_printenv");
    for (const auto& entry : output)
    {
        size_t pos = entry.find("=");
        string key = entry.substr(0, pos);
        if (key != "fitconfig")
        {
            continue;
        }

        envVarFound = true;
        if (pos + 1 < entry.size())
        {
            readVarValue = entry.substr(pos + 1);
            if (readVarValue.find(newDeviceTree) != string::npos)
            {
                // fitconfig is Updated. No action needed
                break;
            }
        }
        // set env and reboot and break.
        setEnvAndReboot(key, newDeviceTree);
        exit(0);
    }

    // check If env var Not found
    if (!envVarFound)
    {
        setEnvAndReboot("fitconfig", newDeviceTree);
    }
}

/**
 * @brief Parse the given EEPROM file.
 *
 * @param[in] vpdFilePath - Path of EEPROM file
 * @param[in] js- Reference to vpd inventory json object
 * @return Parsed VPD map
 */
std::variant<KeywordVpdMap, openpower::vpd::Store>
    parseVpdFile(const std::string& vpdFilePath, const nlohmann::json& js)
{
    uint32_t vpdStartOffset = 0;
    for (const auto& item : js["frus"][vpdFilePath])
    {
        if (item.find("offset") != item.end())
        {
            vpdStartOffset = item["offset"];
            break;
        }
    }

    Binary vpdVector = getVpdDataInVector(js, vpdFilePath);

    ParserInterface* parser = ParserFactory::getParser(
        vpdVector,
        (pimPath + js["frus"][vpdFilePath][0]["inventoryPath"]
                       .get_ref<const nlohmann::json::string_t&>()),
        vpdFilePath, vpdStartOffset);

    auto parseResult = parser->parse();

    // release the parser object
    ParserFactory::freeParser(parser);

    return parseResult;
}

/*
 * @brief This API retrieves the hardware backup in map
 *
 * @param[in] systemVpdBackupPath - The path that backs up the system VPD.
 * @param[in] backupVpdInvPath - FRU inventory path.
 * @param[in] js - JSON object.
 * @param[out] backupVpdMap - An IPZ VPD map containing the parsed backup VPD.
 *
 * */
void getBackupVpdInMap(const string& systemVpdBackupPath,
                       const string& backupVpdInvPath, const nlohmann::json& js,
                       Parsed& backupVpdMap)
{
    PelAdditionalData additionalData{};

    if (!fs::exists(systemVpdBackupPath))
    {
        string errorMsg = "Device path ";
        errorMsg += systemVpdBackupPath;
        errorMsg += " does not exist";

        additionalData.emplace("DESCRIPTION", errorMsg);

        additionalData.emplace("CALLOUT_INVENTORY_PATH",
                               INVENTORY_PATH + backupVpdInvPath);

        createPEL(additionalData, PelSeverity::ERROR, errIntfForStreamFail,
                  nullptr);
    }
    else
    {
        auto backupVpdParsedResult = parseVpdFile(systemVpdBackupPath, js);

        if (auto pVal = get_if<Store>(&backupVpdParsedResult))
        {
            backupVpdMap = pVal->getVpdMap();
        }
        else
        {
            std::cerr << "Invalid format of VPD in back up. Restore aborted."
                      << std::endl;
        }
    }
}

void updateVpdDataOnHw(const std::string& vpdFilePath, nlohmann::json& js,
                       const std::string& recName, const std::string& kwName,
                       const Binary& kwdData)
{
    const std::string& fruInvPath =
        js["frus"][vpdFilePath][0]["inventoryPath"]
            .get_ref<const nlohmann::json::string_t&>();

    EditorImpl edit(vpdFilePath, js, recName, kwName, fruInvPath);

    uint32_t offset = 0;
    // Setup offset, if any
    for (const auto& item : js["frus"][vpdFilePath])
    {
        if (item.find("offset") != item.end())
        {
            offset = item["offset"];
            break;
        }
    }

    // update keyword data on to EEPROM file
    // Note: Updating keyword data on cache is
    // handled via PIM Notify call hence passing
    // the updCache flag value as false here.
    edit.updateKeyword(kwdData, offset, false);
}

/**
 * @brief API to check if we need to restore system VPD
 * This functionality is only applicable for IPZ VPD data.

 * @param[in] vpdMap - IPZ vpd map
 * @param[in] objectPath - Object path for the FRU
 * @param[in] js - JSON Object
 * @param[in] isBackupOnCache - Denotes whether the backup is on cache/hardware
 */
void restoreSystemVPD(Parsed& vpdMap, const string& objectPath,
                      nlohmann::json& js, bool isBackupOnCache = true)
{
    std::string systemVpdBackupPath{};
    std::string backupVpdInvPath{};
    Parsed backupVpdMap{};

    if (!isBackupOnCache)
    {
        // Get the value of systemvpdBackupPath field from json
        systemVpdBackupPath = js["frus"][systemVpdFilePath].at(0).value(
            "systemVpdBackupPath", "");

        backupVpdInvPath = js["frus"][systemVpdBackupPath][0]["inventoryPath"]
                               .get_ref<const nlohmann::json::string_t&>();

        getBackupVpdInMap(systemVpdBackupPath, backupVpdInvPath, js,
                          backupVpdMap);

        if (backupVpdMap.empty())
        {
            std::cerr << "Backup VPD map is empty" << std::endl;
            return;
        }
    }

    for (const auto& systemRecKwdPair : svpdKwdMap)
    {
        const string& recordName = systemRecKwdPair.first;
        auto it = vpdMap.find(recordName);

        // check if record is found in map we got by parser
        if (it != vpdMap.end())
        {
            const auto& kwdListForRecord = systemRecKwdPair.second;
            for (const auto& keywordInfo : kwdListForRecord)
            {
                const auto keywordName = get<0>(keywordInfo);

                DbusPropertyMap& kwdValMap = it->second;
                auto iterator = kwdValMap.find(keywordName);

                if (iterator != kwdValMap.end())
                {
                    string& kwdValue = iterator->second;

                    std::string backupValue{};
                    const auto& defaultValue = get<1>(keywordInfo);
                    const auto& backupVpdRecName = get<4>(keywordInfo);
                    const auto& backupVpdKwName = get<5>(keywordInfo);

                    // If the 'isBackupOnCache' flag is false, we need
                    // to backup the systemVPD on the specified fru's eeprom
                    // path or restore it from the specified fru's eeprom path.
                    if (isBackupOnCache)
                    {
                        // check bus data
                        backupValue = readBusProperty(
                            objectPath, ipzVpdInf + recordName, keywordName);
                    }
                    else
                    {
                        backupValue = getKwVal(backupVpdMap, backupVpdRecName,
                                               backupVpdKwName);

                        if (backupValue.empty())
                        {
                            string errorMsg{};
                            if (backupVpdMap.find(backupVpdRecName) ==
                                backupVpdMap.end())
                            {
                                errorMsg = backupVpdRecName +
                                           " Record does not exist in "
                                           "the EEPROM file ";
                            }
                            else
                            {
                                errorMsg = backupVpdKwName +
                                           " Keyword not found or empty.";
                            }

                            errorMsg += systemVpdBackupPath;

                            PelAdditionalData additionalData;
                            additionalData.emplace("DESCRIPTION", errorMsg);

                            createPEL(additionalData, PelSeverity::ERROR,
                                      errIntfForInvalidVPD, nullptr);

                            continue;
                        }
                    }

                    Binary backupDataInBinary(backupValue.begin(),
                                              backupValue.end());

                    Binary kwdDataInBinary(kwdValue.begin(), kwdValue.end());

                    if (backupDataInBinary != defaultValue)
                    {
                        if (kwdDataInBinary != defaultValue)
                        {
                            // both the data are present, check for mismatch
                            if (backupValue != kwdValue)
                            {
                                string errMsg = "Mismatch found between backup "
                                                "and primary VPD for record: ";
                                errMsg += (*it).first;
                                errMsg += " and keyword: ";
                                errMsg += keywordName;

                                std::ostringstream busStream;
                                for (uint16_t byte : backupValue)
                                {
                                    busStream
                                        << std::setfill('0') << std::setw(2)
                                        << std::hex << "0x" << byte << " ";
                                }

                                std::ostringstream vpdStream;
                                for (uint16_t byte : kwdValue)
                                {
                                    vpdStream
                                        << std::setfill('0') << std::setw(2)
                                        << std::hex << "0x" << byte << " ";
                                }

                                // data mismatch
                                PelAdditionalData additionalData;

                                additionalData.emplace("DESCRIPTION", errMsg);
                                additionalData.emplace(
                                    "Value read from Backup: ",
                                    busStream.str());
                                additionalData.emplace(
                                    "Value read from Primary: ",
                                    vpdStream.str());

                                createPEL(additionalData, PelSeverity::WARNING,
                                          errIntfForVPDMismatch, nullptr);

                                if (!isBackupOnCache)
                                {
                                    // Backing up or restoring from a hardware
                                    // path does not requires copying the backup
                                    // data to the VPD map, as this will result
                                    // in a mismatch between the primary VPD and
                                    // its cache.
                                    continue;
                                }
                            }
                            else
                            {
                                // both the backup and primary data is
                                // non-default and same. Nothing needs to be
                                // done.
                                continue;
                            }
                        }

                        // If the backup is on the cache we need to copy the
                        // backup data to the VPD map to ensure there is no
                        // mismatch b/n them. So if backup data is not default,
                        // then irrespective of primary data(default or other
                        // than backup), copy the backup data to vpd map as we
                        // don't need to change the backup data in either case
                        // in the process of restoring system vpd.
                        kwdValue = backupValue;

                        // If the backup data is on the base panel the restoring
                        // of Backup VPD on to the system backplane VPD
                        // file is done here not through the VPD manager code
                        // path. This is to have the logic of restoring data on
                        // to the cache & hardware in the same code path.
                        if (!isBackupOnCache)
                        {
                            // copy backup VPD on to system backplane
                            // EEPROM  file.
                            updateVpdDataOnHw(systemVpdFilePath, js, recordName,
                                              keywordName, backupDataInBinary);
                        }
                    }
                    else if (kwdDataInBinary == defaultValue &&
                             get<2>(keywordInfo)) // Check isPELRequired is true
                    {
                        string errMsg = "Found default value on both backup "
                                        "and primary VPD for record: ";
                        errMsg += (*it).first;
                        errMsg += " and keyword: ";
                        errMsg += keywordName;
                        errMsg += ". Update primary VPD.";

                        // mfg default on both backup and primary, log PEL
                        PelAdditionalData additionalData;
                        additionalData.emplace("DESCRIPTION", errMsg);

                        createPEL(additionalData, PelSeverity::ERROR,
                                  errIntfForVPDDefault, nullptr);

                        continue;
                    }
                    else if ((kwdDataInBinary != defaultValue) &&
                             (!isBackupOnCache))
                    {
                        // update primary VPD on to backup VPD file
                        updateVpdDataOnHw(systemVpdBackupPath, js,
                                          backupVpdRecName, backupVpdKwName,
                                          kwdDataInBinary);

                        // copy primary VPD to backup VPD to publish on
                        // DBus
                        backupVpdMap.find(backupVpdRecName)
                            ->second.find(backupVpdKwName)
                            ->second = kwdValue;
                    }
                }
            }
        }
    }
}

/**
 * @brief This checks for is this FRU a processor
 *        And if yes, then checks for is this primary
 *
 * @param[in] js- vpd json to get the information about this FRU
 * @param[in] filePath- FRU vpd
 *
 * @return true/false
 */
bool isThisPrimaryProcessor(nlohmann::json& js, const string& filePath)
{
    bool isProcessor = false;
    bool isPrimary = false;

    for (const auto& item : js["frus"][filePath])
    {
        if (item.find("extraInterfaces") != item.end())
        {
            for (const auto& eI : item["extraInterfaces"].items())
            {
                if (eI.key().find("Inventory.Item.Cpu") != string::npos)
                {
                    isProcessor = true;
                }
            }
        }

        if (isProcessor)
        {
            string cpuType = item.value("cpuType", "");
            if (cpuType == "primary")
            {
                isPrimary = true;
            }
        }
    }

    return (isProcessor && isPrimary);
}

/**
 * @brief This finds DIMM vpd in vpd json and enables them by binding the device
 *        driver
 * @param[in] js- vpd json to iterate through and take action if it is DIMM
 */
void doEnableAllDimms(nlohmann::json& js)
{
    // iterate over each fru
    for (const auto& eachFru : js["frus"].items())
    {
        // skip the driver binding if eeprom already exists
        if (fs::exists(eachFru.key()))
        {
            continue;
        }

        for (const auto& eachInventory : eachFru.value())
        {
            if (eachInventory.find("extraInterfaces") != eachInventory.end())
            {
                for (const auto& eI : eachInventory["extraInterfaces"].items())
                {
                    if (eI.key().find("Inventory.Item.Dimm") != string::npos)
                    {
                        string dimmVpd = eachFru.key();
                        // fetch it from
                        // "/sys/bus/i2c/drivers/at24/414-0050/eeprom"

                        regex matchPatern("([0-9]+-[0-9]{4})");
                        smatch matchFound;
                        if (regex_search(dimmVpd, matchFound, matchPatern))
                        {
                            vector<string> i2cReg;
                            boost::split(i2cReg, matchFound.str(0),
                                         boost::is_any_of("-"));

                            // remove 0s from beginning
                            const regex pattern("^0+(?!$)");
                            for (auto& i : i2cReg)
                            {
                                i = regex_replace(i, pattern, "");
                            }

                            // For ISDIMM which uses ee1004 driver
                            // the below is done
                            size_t stringFound = dimmVpd.find("ee1004");
                            if (stringFound != string::npos)
                            {
                                // echo ee1004 0x50 >
                                // /sys/bus/i2c/devices/i2c-110/new_device
                                string cmnd = "echo ee1004 0x" + i2cReg[1] +
                                              " > /sys/bus/i2c/devices/i2c-" +
                                              i2cReg[0] + "/new_device";
                                executeCmd(cmnd);
                            }
                            else if (i2cReg.size() == 2)
                            {
                                // echo 24c32 0x50 >
                                // /sys/bus/i2c/devices/i2c-16/new_device
                                string cmnd = "echo 24c32 0x" + i2cReg[1] +
                                              " > /sys/bus/i2c/devices/i2c-" +
                                              i2cReg[0] + "/new_device";
                                executeCmd(cmnd);
                            }
                        }
                    }
                }
            }
        }
    }
}

/**
 * @brief Check if the given CPU is an IO only chip.
 * The CPU is termed as IO, whose all of the cores are bad and can never be
 * used. Those CPU chips can be used for IO purpose like connecting PCIe devices
 * etc., The CPU whose every cores are bad, can be identified from the CP00
 * record's PG keyword, only if all of the 8 EQs' value equals 0xE7F9FF. (1EQ
 * has 4 cores grouped together by sharing its cache memory.)
 * @param [in] pgKeyword - PG Keyword of CPU.
 * @return true if the given cpu is an IO, false otherwise.
 */
static bool isCPUIOGoodOnly(const string& pgKeyword)
{
    const unsigned char 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(io, pgKeyword.data() + 97, 24) == 0)
    {
        return true;
    }

    // The CPU is not an IO
    return false;
}

/**
 * @brief Function to bring MUX out of idle state
 *
 *        This finds All the MUX defined in the system json and enables
 *        them by setting the holdidle parameter to 0.
 * @param[in] js- system json to iterate through and take action
 */
void doEnableAllMuxChips(const nlohmann::json& js)
{
    // Do we have the mandatory "muxes" section?
    if (js.find("muxes") != js.end())
    {
        std::cout << "Enabling all the MUX on the system " << std::endl;
        // iterate over each MUX detail and enable them
        for (const auto& item : js["muxes"])
        {
            if (item.find("holdidlepath") != item.end())
            {
                const std::string& holdidle = item["holdidlepath"];
                std::cout << "Setting holdidle state for " << holdidle
                          << "to 0 " << std::endl;
                string cmd = "echo 0 > " + holdidle;
                executeCmd(cmd);
            }
        }
        std::cout << "Completed enabling all the MUX on the system "
                  << std::endl;
    }
    else
    {
        std::cout << "No MUX was defined for the system" << std::endl;
    }
}

/**
 * @brief Populate Dbus.
 * This method invokes all the populateInterface functions
 * and notifies PIM about dbus object.
 * @param[in] vpdMap - Either IPZ vpd map or Keyword vpd map based on the
 * input.
 * @param[in] js - Inventory json object
 * @param[in] filePath - Path of the vpd file
 * @param[in] preIntrStr - Interface string
 */
template <typename T>
static void populateDbus(T& vpdMap, nlohmann::json& js, const string& filePath)
{
    inventory::InterfaceMap interfaces;
    inventory::ObjectMap objects;
    inventory::PropertyMap prop;
    string ccinFromVpd;

    bool isSystemVpd = (filePath == systemVpdFilePath);
    if constexpr (is_same<T, Parsed>::value)
    {
        ccinFromVpd = getKwVal(vpdMap, "VINI", "CC");
        transform(ccinFromVpd.begin(), ccinFromVpd.end(), ccinFromVpd.begin(),
                  ::toupper);

        if (isSystemVpd)
        {
            string mboardPath =
                js["frus"][filePath].at(0).value("inventoryPath", "");

            // Get the value of systemvpdBackupPath field from json
            const std::string& systemVpdBackupPath =
                js["frus"][filePath].at(0).value("systemVpdBackupPath", "");

            if (systemVpdBackupPath.empty())
            {
                std::vector<std::string> interfaces = {motherBoardInterface};
                // call mapper to check for object path creation
                MapperResponse subTree =
                    getObjectSubtreeForInterfaces(pimPath, 0, interfaces);

                // Attempt system VPD restore if we have a motherboard
                // object in the inventory.
                if ((subTree.size() != 0) &&
                    (subTree.find(pimPath + mboardPath) != subTree.end()))
                {
                    restoreSystemVPD(vpdMap, mboardPath, js);
                }
                else
                {
                    log<level::ERR>("No object path found");
                }
            }
            else
            {
                restoreSystemVPD(vpdMap, mboardPath, js, false);
            }
        }
        else
        {
            // check if it is processor vpd.
            auto isPrimaryCpu = isThisPrimaryProcessor(js, filePath);

            if (isPrimaryCpu)
            {
                auto ddVersion = getKwVal(vpdMap, "CRP0", "DD");

                auto chipVersion = atoi(ddVersion.substr(1, 2).c_str());

                if (chipVersion >= 2)
                {
                    doEnableAllDimms(js);
                    // Sleep for a few seconds to let the DIMM parses start
                    using namespace std::chrono_literals;
                    std::this_thread::sleep_for(5s);
                }
            }
        }
    }

    auto processFactoryReset = false;

    if (isSystemVpd)
    {
        string systemJsonName{};
        if constexpr (is_same<T, Parsed>::value)
        {
            // pick the right system json
            systemJsonName = getSystemsJson(vpdMap);
        }

        fs::path target = systemJsonName;
        fs::path link = INVENTORY_JSON_SYM_LINK;

        // If the symlink does not exist, we treat that as a factory reset
        processFactoryReset = !fs::exists(INVENTORY_JSON_SYM_LINK);

        // Create the directory for hosting the symlink
        fs::create_directories(VPD_FILES_PATH);
        // unlink the symlink previously created (if any)
        remove(INVENTORY_JSON_SYM_LINK);
        // create a new symlink based on the system
        fs::create_symlink(target, link);

        // Reloading the json
        ifstream inventoryJson(link);
        js = json::parse(inventoryJson);
        inventoryJson.close();

        // enable the muxes again here to cover the case where during first boot
        // after reset, system would have come up with default JSON
        // configuration and have skipped enabling mux at the beginning.
        // Default config JSON does not have mux entries.
        doEnableAllMuxChips(js);
    }

    for (const auto& item : js["frus"][filePath])
    {
        const auto& objectPath = item["inventoryPath"];
        sdbusplus::message::object_path object(objectPath);

        vector<string> ccinList;
        if (item.find("ccin") != item.end())
        {
            for (const auto& cc : item["ccin"])
            {
                string ccin = cc;
                transform(ccin.begin(), ccin.end(), ccin.begin(), ::toupper);
                ccinList.push_back(ccin);
            }
        }

        if (!ccinFromVpd.empty() && !ccinList.empty() &&
            (find(ccinList.begin(), ccinList.end(), ccinFromVpd) ==
             ccinList.end()))
        {
            continue;
        }

        if ((isSystemVpd) || (item.value("noprime", false)))
        {
            // Populate one time properties for the system VPD and its sub-frus
            // and for other non-primeable frus.
            // For the remaining FRUs, this will get handled as a part of
            // priming the inventory.
            setOneTimeProperties(objectPath, interfaces);
        }

        // Populate the VPD keywords and the common interfaces only if we
        // are asked to inherit that data from the VPD, else only add the
        // extraInterfaces.
        if (item.value("inherit", true))
        {
            if constexpr (is_same<T, Parsed>::value)
            {
                // Each record in the VPD becomes an interface and all
                // keyword within the record are properties under that
                // interface.
                for (const auto& record : vpdMap)
                {
                    populateFruSpecificInterfaces(
                        record.second, ipzVpdInf + record.first, interfaces);
                }
            }
            else if constexpr (is_same<T, KeywordVpdMap>::value)
            {
                populateFruSpecificInterfaces(vpdMap, kwdVpdInf, interfaces);
            }
            if (js.find("commonInterfaces") != js.end())
            {
                populateInterfaces(js["commonInterfaces"], interfaces, vpdMap,
                                   isSystemVpd);
            }
        }
        else
        {
            // Check if we have been asked to inherit specific record(s)
            if constexpr (is_same<T, Parsed>::value)
            {
                if (item.find("copyRecords") != item.end())
                {
                    for (const auto& record : item["copyRecords"])
                    {
                        const string& recordName = record;
                        if (vpdMap.find(recordName) != vpdMap.end())
                        {
                            populateFruSpecificInterfaces(
                                vpdMap.at(recordName), ipzVpdInf + recordName,
                                interfaces);
                        }
                    }
                }
            }
        }
        // Populate interfaces and properties that are common to every FRU
        // and additional interface that might be defined on a per-FRU
        // basis.
        if (item.find("extraInterfaces") != item.end())
        {
            populateInterfaces(item["extraInterfaces"], interfaces, vpdMap,
                               isSystemVpd);
            if constexpr (is_same<T, Parsed>::value)
            {
                if (item["extraInterfaces"].find(
                        "xyz.openbmc_project.Inventory.Item.Cpu") !=
                    item["extraInterfaces"].end())
                {
                    if (isCPUIOGoodOnly(getKwVal(vpdMap, "CP00", "PG")))
                    {
                        interfaces[invItemIntf]["PrettyName"] = "IO Module";
                    }
                }
            }
        }

        // 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 do not 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.
        if ((item.value("embedded", true)) &&
            (!item.value("synthesized", false)))
        {
            // Check if its required to handle presence for this FRU.
            if (item.value("handlePresence", true))
            {
                inventory::PropertyMap presProp;
                presProp.emplace("Present", true);
                insertOrMerge(interfaces, invItemIntf, move(presProp));
            }
        }

        if constexpr (is_same<T, Parsed>::value)
        {
            // Restore asset tag, if needed
            if (processFactoryReset && objectPath == "/system")
            {
                fillAssetTag(interfaces, vpdMap);
            }
        }

        objects.emplace(move(object), move(interfaces));
    }

    if (isSystemVpd)
    {
        inventory::ObjectMap primeObject = primeInventory(js, vpdMap);
        objects.insert(primeObject.begin(), primeObject.end());

        // set the U-boot environment variable for device-tree
        if constexpr (is_same<T, Parsed>::value)
        {
            setDevTreeEnv(fs::path(getSystemsJson(vpdMap)).filename());
        }
    }

    // Notify PIM
    common::utility::callPIM(move(objects));
}

int main(int argc, char** argv)
{
    int rc = 0;
    json js{};
    Binary vpdVector{};
    string file{};
    string driver{};
    // map to hold additional data in case of logging pel
    PelAdditionalData additionalData{};

    // this is needed to hold base fru inventory path in case there is ECC or
    // vpd exception while parsing the file
    std::string baseFruInventoryPath = {};

    // It holds the backup EEPROM file path for the system backplane's critical
    // data
    std::string systemVpdBackupPath{};

    // It holds the inventory path of backup EEPROM file
    std::string backupVpdInvPath{};

    bool isSystemVpd = false;

    // severity for PEL
    PelSeverity pelSeverity = PelSeverity::WARNING;

    try
    {
        App app{"ibm-read-vpd - App to read IPZ/Jedec format VPD, parse it and "
                "store it in DBUS"};

        app.add_option("-f, --file", file, "File containing VPD (IPZ/KEYWORD)")
            ->required();

        app.add_option("--driver", driver,
                       "Driver used by kernel (at24,at25,ee1004)")
            ->required();

        CLI11_PARSE(app, argc, argv);

        // PEL severity should be ERROR in case of any system VPD failure
        if (file == systemVpdFilePath)
        {
            pelSeverity = PelSeverity::ERROR;
            isSystemVpd = true;
        }

        // Check if input file is not empty.
        if ((file.empty()) || (driver.empty()))
        {
            std::cerr << "Encountered empty input parameter file [" << file
                      << "] driver [" << driver << "]" << std::endl;
            return 0;
        }

        // Check if currently supported driver or not
        if ((driver != at24driver) && (driver != at25driver) &&
            (driver != ee1004driver))
        {
            std::cerr << "The driver [" << driver << "] is not supported."
                      << std::endl;
            return 0;
        }

        auto jsonToParse = INVENTORY_JSON_DEFAULT;

        // If the symlink exists, it means it has been setup for us, switch the
        // path
        if (fs::exists(INVENTORY_JSON_SYM_LINK))
        {
            jsonToParse = INVENTORY_JSON_SYM_LINK;
        }

        // Make sure that the file path we get is for a supported EEPROM
        ifstream inventoryJson(jsonToParse);
        if (!inventoryJson)
        {
            throw(VpdJsonException("Failed to access Json path", jsonToParse));
        }

        try
        {
            js = json::parse(inventoryJson);
        }
        catch (const json::parse_error& ex)
        {
            throw(VpdJsonException("Json parsing failed", jsonToParse));
        }

        // Do we have the mandatory "frus" section?
        if (js.find("frus") == js.end())
        {
            throw(VpdJsonException("FRUs section not found in JSON",
                                   jsonToParse));
        }

        // Check if it's a udev path - patterned as(/ahb/1e780000.apb/ for I2C
        // or /ahb/1e790000.apb/ for FSI)
        if (file.find("/ahb:apb") != string::npos ||
            file.find("/ahb/1e780000.apb") != string::npos ||
            file.find("/ahb/1e790000.apb") != string::npos)
        {
            // Translate udev path to a generic /sys/bus/.. file path.
            udevToGenericPath(file, driver);

            if ((js["frus"].find(file) != js["frus"].end()) &&
                (file == systemVpdFilePath))
            {
                std::cout << "We have already collected system VPD, skipping."
                          << std::endl;
                return 0;
            }
        }

        // 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.
        // To run it only once have kept it under System vpd check.
        // we need to run this on all BMC reboots so kept here
        if (file == systemVpdFilePath)
        {
            doEnableAllMuxChips(js);
        }

        if (file.empty())
        {
            std::cerr << "The EEPROM path <" << file << "> is not valid.";
            return 0;
        }
        if (js["frus"].find(file) == js["frus"].end())
        {
            std::cerr << "The EEPROM path [" << file
                      << "] is not found in the json." << std::endl;
            return 0;
        }

        if (!fs::exists(file))
        {
            std::cout << "Device path: " << file
                      << " does not exist. Spurious udev event? Exiting."
                      << std::endl;
            return 0;
        }

        // In case of system VPD it will already be filled, Don't have to
        // overwrite that.
        if (baseFruInventoryPath.empty())
        {
            baseFruInventoryPath = js["frus"][file][0]["inventoryPath"];
        }

        // Check if we can read the VPD file based on the power state
        // We skip reading VPD when the power is ON in two scenarios:
        // 1) The eeprom we are trying to read is that of the system VPD and the
        // JSON symlink is already setup (the symlink's existence tells us we
        // are not coming out of a factory reset)
        // 2) The JSON tells us that the FRU EEPROM cannot be
        // read when we are powered ON.
        if (js["frus"][file].at(0).value("powerOffOnly", false) ||
            (file == systemVpdFilePath && fs::exists(INVENTORY_JSON_SYM_LINK)))
        {
            if ("xyz.openbmc_project.State.Chassis.PowerState.On" ==
                getPowerState())
            {
                std::cout << "This VPD cannot be read when power is ON"
                          << std::endl;
                return 0;
            }
        }

        // Check if this VPD should be recollected at all
        if (!needsRecollection(js, file))
        {
            std::cout << "Skip VPD recollection for: " << file << std::endl;
            return 0;
        }

        try
        {
            variant<KeywordVpdMap, Store> parseResult;
            parseResult = parseVpdFile(file, js);

            if (isSystemVpd)
            {
                // Get the value of systemVpdBackupPath field from json
                systemVpdBackupPath = js["frus"][systemVpdFilePath].at(0).value(
                    "systemVpdBackupPath", "");

                if (!systemVpdBackupPath.empty())
                {
                    backupVpdInvPath =
                        js["frus"][systemVpdBackupPath][0]["inventoryPath"]
                            .get_ref<const nlohmann::json::string_t&>();
                }
            }

            if (auto pVal = get_if<Store>(&parseResult))
            {
                populateDbus(pVal->getVpdMap(), js, file);
            }
            else if (auto pVal = get_if<KeywordVpdMap>(&parseResult))
            {
                populateDbus(*pVal, js, file);
            }
        }
        catch (const exception& e)
        {
            if (!systemVpdBackupPath.empty())
            {
                file = systemVpdBackupPath;
                baseFruInventoryPath = backupVpdInvPath;
            }

            executePostFailAction(js, file);
            throw;
        }
    }
    catch (const VpdJsonException& ex)
    {
        additionalData.emplace("JSON_PATH", ex.getJsonPath());
        additionalData.emplace("DESCRIPTION", ex.what());
        createPEL(additionalData, pelSeverity, errIntfForJsonFailure, nullptr);

        std::cerr << ex.what() << "\n";
        rc = -1;
    }
    catch (const VpdEccException& ex)
    {
        additionalData.emplace("DESCRIPTION", "ECC check failed");
        additionalData.emplace("CALLOUT_INVENTORY_PATH",
                               INVENTORY_PATH + baseFruInventoryPath);
        createPEL(additionalData, pelSeverity, errIntfForEccCheckFail, nullptr);

        if (systemVpdBackupPath.empty())
        {
            dumpBadVpd(file, vpdVector);
        }

        std::cerr << ex.what() << "\n";
        rc = -1;
    }
    catch (const VpdDataException& ex)
    {
        if (isThisPcieOnPass1planar(js, file))
        {
            std::cout << "Pcie_device  [" << file
                      << "]'s VPD is not valid on PASS1 planar.Ignoring.\n";
            rc = 0;
        }
        else if (!(isPresent(js, file).value_or(true)))
        {
            std::cout << "FRU at: " << file
                      << " is not detected present. Ignore parser error.\n";
            rc = 0;
        }
        else
        {
            string errorMsg =
                "VPD file is either empty or invalid. Parser failed for [";
            errorMsg += file;
            errorMsg += "], with error = " + std::string(ex.what());

            additionalData.emplace("DESCRIPTION", errorMsg);
            additionalData.emplace("CALLOUT_INVENTORY_PATH",
                                   INVENTORY_PATH + baseFruInventoryPath);
            createPEL(additionalData, pelSeverity, errIntfForInvalidVPD,
                      nullptr);

            rc = -1;
        }
    }
    catch (const exception& e)
    {
        dumpBadVpd(file, vpdVector);
        std::cerr << e.what() << "\n";
        rc = -1;
    }

    return rc;
}
