/**
 * Copyright © 2019 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "config.h"

#include "data_interface.hpp"

#include "util.hpp"

#include <fmt/format.h>

#include <fstream>
#include <iterator>
#include <phosphor-logging/log.hpp>
#include <xyz/openbmc_project/State/Boot/Progress/server.hpp>

// Use a timeout of 10s for D-Bus calls so if there are
// timeouts the callers of the PEL creation method won't
// also timeout.
constexpr auto dbusTimeout = 10000000;

namespace openpower
{
namespace pels
{

namespace service_name
{
constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper";
constexpr auto vpdManager = "com.ibm.VPD.Manager";
constexpr auto ledGroupManager = "xyz.openbmc_project.LED.GroupManager";
constexpr auto logSetting = "xyz.openbmc_project.Settings";
constexpr auto hwIsolation = "org.open_power.HardwareIsolation";
constexpr auto bootRawProgress = "xyz.openbmc_project.State.Boot.Raw";
constexpr auto biosConfigMgr = "xyz.openbmc_project.BIOSConfigManager";
} // namespace service_name

namespace object_path
{
constexpr auto objectMapper = "/xyz/openbmc_project/object_mapper";
constexpr auto systemInv = "/xyz/openbmc_project/inventory/system";
constexpr auto chassisInv = "/xyz/openbmc_project/inventory/system/chassis";
constexpr auto motherBoardInv =
    "/xyz/openbmc_project/inventory/system/chassis/motherboard";
constexpr auto baseInv = "/xyz/openbmc_project/inventory";
constexpr auto bmcState = "/xyz/openbmc_project/state/bmc0";
constexpr auto chassisState = "/xyz/openbmc_project/state/chassis0";
constexpr auto hostState = "/xyz/openbmc_project/state/host0";
constexpr auto pldm = "/xyz/openbmc_project/pldm";
constexpr auto enableHostPELs =
    "/xyz/openbmc_project/logging/send_event_logs_to_host";
constexpr auto vpdManager = "/com/ibm/VPD/Manager";
constexpr auto logSetting = "/xyz/openbmc_project/logging/settings";
constexpr auto hwIsolation = "/xyz/openbmc_project/hardware_isolation";
constexpr auto bootRawSetting = "/xyz/openbmc_project/state/boot/raw0";
constexpr auto biosConfigMgr = "/xyz/openbmc_project/bios_config/manager";
} // namespace object_path

namespace interface
{
constexpr auto dbusProperty = "org.freedesktop.DBus.Properties";
constexpr auto objectMapper = "xyz.openbmc_project.ObjectMapper";
constexpr auto invAsset = "xyz.openbmc_project.Inventory.Decorator.Asset";
constexpr auto bootProgress = "xyz.openbmc_project.State.Boot.Progress";
constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester";
constexpr auto enable = "xyz.openbmc_project.Object.Enable";
constexpr auto bmcState = "xyz.openbmc_project.State.BMC";
constexpr auto chassisState = "xyz.openbmc_project.State.Chassis";
constexpr auto hostState = "xyz.openbmc_project.State.Host";
constexpr auto invMotherboard =
    "xyz.openbmc_project.Inventory.Item.Board.Motherboard";
constexpr auto viniRecordVPD = "com.ibm.ipzvpd.VINI";
constexpr auto vsbpRecordVPD = "com.ibm.ipzvpd.VSBP";
constexpr auto locCode = "xyz.openbmc_project.Inventory.Decorator.LocationCode";
constexpr auto compatible =
    "xyz.openbmc_project.Configuration.IBMCompatibleSystem";
constexpr auto vpdManager = "com.ibm.VPD.Manager";
constexpr auto ledGroup = "xyz.openbmc_project.Led.Group";
constexpr auto operationalStatus =
    "xyz.openbmc_project.State.Decorator.OperationalStatus";
constexpr auto logSetting = "xyz.openbmc_project.Logging.Settings";
constexpr auto associationDef = "xyz.openbmc_project.Association.Definitions";
constexpr auto dumpEntry = "xyz.openbmc_project.Dump.Entry";
constexpr auto dumpProgress = "xyz.openbmc_project.Common.Progress";
constexpr auto hwIsolationCreate = "org.open_power.HardwareIsolation.Create";
constexpr auto bootRawProgress = "xyz.openbmc_project.State.Boot.Raw";
constexpr auto hwIsolationEntry = "xyz.openbmc_project.HardwareIsolation.Entry";
constexpr auto association = "xyz.openbmc_project.Association";
constexpr auto biosConfigMgr = "xyz.openbmc_project.BIOSConfig.Manager";
} // namespace interface

using namespace sdbusplus::xyz::openbmc_project::State::Boot::server;
using namespace phosphor::logging;

std::pair<std::string, std::string>
    DataInterfaceBase::extractConnectorFromLocCode(
        const std::string& locationCode)
{
    auto base = locationCode;
    std::string connector{};

    auto pos = base.find("-T");
    if (pos != std::string::npos)
    {
        connector = base.substr(pos);
        base = base.substr(0, pos);
    }

    return {base, connector};
}

DataInterface::DataInterface(sdbusplus::bus_t& bus) : _bus(bus)
{
    readBMCFWVersion();
    readServerFWVersion();
    readBMCFWVersionID();

    // Watch the BootProgress property
    _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
        bus, object_path::hostState, interface::bootProgress, "BootProgress",
        *this, [this](const auto& value) {
            this->_bootState = std::get<std::string>(value);
            auto status = Progress::convertProgressStagesFromString(
                std::get<std::string>(value));

            if ((status == Progress::ProgressStages::SystemInitComplete) ||
                (status == Progress::ProgressStages::OSStart) ||
                (status == Progress::ProgressStages::OSRunning))
            {
                setHostUp(true);
            }
            else
            {
                setHostUp(false);
            }
        }));

    // Watch the host PEL enable property
    _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
        bus, object_path::enableHostPELs, interface::enable, "Enabled", *this,
        [this](const auto& value) {
            if (std::get<bool>(value) != this->_sendPELsToHost)
            {
                log<level::INFO>(
                    fmt::format("The send PELs to host setting changed to {}",
                                std::get<bool>(value))
                        .c_str());
            }
            this->_sendPELsToHost = std::get<bool>(value);
        }));

    // Watch the BMCState property
    _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
        bus, object_path::bmcState, interface::bmcState, "CurrentBMCState",
        *this, [this](const auto& value) {
            this->_bmcState = std::get<std::string>(value);
        }));

    // Watch the chassis current and requested power state properties
    _properties.emplace_back(std::make_unique<InterfaceWatcher<DataInterface>>(
        bus, object_path::chassisState, interface::chassisState, *this,
        [this](const auto& properties) {
            auto state = properties.find("CurrentPowerState");
            if (state != properties.end())
            {
                this->_chassisState = std::get<std::string>(state->second);
            }

            auto trans = properties.find("RequestedPowerTransition");
            if (trans != properties.end())
            {
                this->_chassisTransition = std::get<std::string>(trans->second);
            }
        }));

    // Watch the CurrentHostState property
    _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
        bus, object_path::hostState, interface::hostState, "CurrentHostState",
        *this, [this](const auto& value) {
            this->_hostState = std::get<std::string>(value);
        }));

    // Watch the BaseBIOSTable property for the hmc managed attribute
    _properties.emplace_back(std::make_unique<PropertyWatcher<DataInterface>>(
        bus, object_path::biosConfigMgr, interface::biosConfigMgr,
        "BaseBIOSTable", service_name::biosConfigMgr, *this,
        [this](const auto& value) {
            const auto& attributes = std::get<BiosAttributes>(value);

            auto it = attributes.find("pvm_hmc_managed");
            if (it != attributes.end())
            {
                const auto& currentValVariant = std::get<5>(it->second);
                auto currentVal = std::get_if<std::string>(&currentValVariant);
                if (currentVal)
                {
                    this->_hmcManaged =
                        (*currentVal == "Enabled") ? true : false;
                }
            }
        }));
}

DBusPropertyMap
    DataInterface::getAllProperties(const std::string& service,
                                    const std::string& objectPath,
                                    const std::string& interface) const
{
    DBusPropertyMap properties;

    auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
                                       interface::dbusProperty, "GetAll");
    method.append(interface);
    auto reply = _bus.call(method, dbusTimeout);

    reply.read(properties);

    return properties;
}

void DataInterface::getProperty(const std::string& service,
                                const std::string& objectPath,
                                const std::string& interface,
                                const std::string& property,
                                DBusValue& value) const
{

    auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
                                       interface::dbusProperty, "Get");
    method.append(interface, property);
    auto reply = _bus.call(method, dbusTimeout);

    reply.read(value);
}

DBusPathList DataInterface::getPaths(const DBusInterfaceList& interfaces) const
{

    auto method = _bus.new_method_call(
        service_name::objectMapper, object_path::objectMapper,
        interface::objectMapper, "GetSubTreePaths");

    method.append(std::string{"/"}, 0, interfaces);

    auto reply = _bus.call(method, dbusTimeout);

    DBusPathList paths;
    reply.read(paths);

    return paths;
}

DBusService DataInterface::getService(const std::string& objectPath,
                                      const std::string& interface) const
{
    auto method = _bus.new_method_call(service_name::objectMapper,
                                       object_path::objectMapper,
                                       interface::objectMapper, "GetObject");

    method.append(objectPath, std::vector<std::string>({interface}));

    auto reply = _bus.call(method, dbusTimeout);

    std::map<DBusService, DBusInterfaceList> response;
    reply.read(response);

    if (!response.empty())
    {
        return response.begin()->first;
    }

    return std::string{};
}

void DataInterface::readBMCFWVersion()
{
    _bmcFWVersion =
        phosphor::logging::util::getOSReleaseValue("VERSION").value_or("");
}

void DataInterface::readServerFWVersion()
{
    auto value =
        phosphor::logging::util::getOSReleaseValue("VERSION_ID").value_or("");
    if ((value != "") && (value.find_last_of(')') != std::string::npos))
    {
        std::size_t pos = value.find_first_of('(') + 1;
        _serverFWVersion = value.substr(pos, value.find_last_of(')') - pos);
    }
}

void DataInterface::readBMCFWVersionID()
{
    _bmcFWVersionID =
        phosphor::logging::util::getOSReleaseValue("VERSION_ID").value_or("");
}

std::string DataInterface::getMachineTypeModel() const
{
    std::string model;
    try
    {

        auto service = getService(object_path::systemInv, interface::invAsset);
        if (!service.empty())
        {
            DBusValue value;
            getProperty(service, object_path::systemInv, interface::invAsset,
                        "Model", value);

            model = std::get<std::string>(value);
        }
    }
    catch (const std::exception& e)
    {
        log<level::WARNING>(fmt::format("Failed reading Model property from "
                                        "Interface: {} exception: {}",
                                        interface::invAsset, e.what())
                                .c_str());
    }

    return model;
}

std::string DataInterface::getMachineSerialNumber() const
{
    std::string sn;
    try
    {

        auto service = getService(object_path::systemInv, interface::invAsset);
        if (!service.empty())
        {
            DBusValue value;
            getProperty(service, object_path::systemInv, interface::invAsset,
                        "SerialNumber", value);

            sn = std::get<std::string>(value);
        }
    }
    catch (const std::exception& e)
    {
        log<level::WARNING>(
            fmt::format("Failed reading SerialNumber property from "
                        "Interface: {} exception: {}",
                        interface::invAsset, e.what())
                .c_str());
    }

    return sn;
}

std::string DataInterface::getMotherboardCCIN() const
{
    std::string ccin;

    try
    {
        auto service =
            getService(object_path::motherBoardInv, interface::viniRecordVPD);
        if (!service.empty())
        {
            DBusValue value;
            getProperty(service, object_path::motherBoardInv,
                        interface::viniRecordVPD, "CC", value);

            auto cc = std::get<std::vector<uint8_t>>(value);
            ccin = std::string{cc.begin(), cc.end()};
        }
    }
    catch (const std::exception& e)
    {
        log<level::WARNING>(
            fmt::format("Failed reading Motherboard CCIN property from "
                        "Interface: {} exception: {}",
                        interface::viniRecordVPD, e.what())
                .c_str());
    }

    return ccin;
}

std::vector<uint8_t> DataInterface::getSystemIMKeyword() const
{
    std::vector<uint8_t> systemIM;

    try
    {
        auto service =
            getService(object_path::motherBoardInv, interface::vsbpRecordVPD);
        if (!service.empty())
        {
            DBusValue value;
            getProperty(service, object_path::motherBoardInv,
                        interface::vsbpRecordVPD, "IM", value);

            systemIM = std::get<std::vector<uint8_t>>(value);
        }
    }
    catch (const std::exception& e)
    {
        log<level::WARNING>(
            fmt::format("Failed reading System IM property from "
                        "Interface: {} exception: {}",
                        interface::vsbpRecordVPD, e.what())
                .c_str());
    }

    return systemIM;
}

void DataInterface::getHWCalloutFields(const std::string& inventoryPath,
                                       std::string& fruPartNumber,
                                       std::string& ccin,
                                       std::string& serialNumber) const
{
    // For now, attempt to get all of the properties directly on the path
    // passed in.  In the future, may need to make use of an algorithm
    // to figure out which inventory objects actually hold these
    // interfaces in the case of non FRUs, or possibly another service
    // will provide this info.  Any missing interfaces will result
    // in exceptions being thrown.

    auto service = getService(inventoryPath, interface::viniRecordVPD);

    auto properties =
        getAllProperties(service, inventoryPath, interface::viniRecordVPD);

    auto value = std::get<std::vector<uint8_t>>(properties["FN"]);
    fruPartNumber = std::string{value.begin(), value.end()};

    value = std::get<std::vector<uint8_t>>(properties["CC"]);
    ccin = std::string{value.begin(), value.end()};

    value = std::get<std::vector<uint8_t>>(properties["SN"]);
    serialNumber = std::string{value.begin(), value.end()};
}

std::string
    DataInterface::getLocationCode(const std::string& inventoryPath) const
{
    auto service = getService(inventoryPath, interface::locCode);

    DBusValue locCode;
    getProperty(service, inventoryPath, interface::locCode, "LocationCode",
                locCode);

    return std::get<std::string>(locCode);
}

std::string
    DataInterface::addLocationCodePrefix(const std::string& locationCode)
{
    static const std::string locationCodePrefix{"Ufcs-"};

    // Technically there are 2 location code prefixes, Ufcs and Umts, so
    // if it already starts with a U then don't need to do anything.
    if (locationCode.front() != 'U')
    {
        return locationCodePrefix + locationCode;
    }

    return locationCode;
}

std::string DataInterface::expandLocationCode(const std::string& locationCode,
                                              uint16_t /*node*/) const
{
    // Location codes for connectors are the location code of the FRU they are
    // on, plus a '-Tx' segment.  Remove this last segment before expanding it
    // and then add it back in afterwards.  This way, the connector doesn't have
    // to be in the model just so that it can be expanded.
    auto [baseLoc, connectorLoc] = extractConnectorFromLocCode(locationCode);

    auto method =
        _bus.new_method_call(service_name::vpdManager, object_path::vpdManager,
                             interface::vpdManager, "GetExpandedLocationCode");

    method.append(addLocationCodePrefix(baseLoc), static_cast<uint16_t>(0));

    auto reply = _bus.call(method, dbusTimeout);

    std::string expandedLocationCode;
    reply.read(expandedLocationCode);

    if (!connectorLoc.empty())
    {
        expandedLocationCode += connectorLoc;
    }

    return expandedLocationCode;
}

std::string
    DataInterface::getInventoryFromLocCode(const std::string& locationCode,
                                           uint16_t node, bool expanded) const
{
    std::string methodName = expanded ? "GetFRUsByExpandedLocationCode"
                                      : "GetFRUsByUnexpandedLocationCode";

    // Remove the connector segment, if present, so that this method call
    // returns an inventory path that getHWCalloutFields() can be used with.
    // (The serial number, etc, aren't stored on the connector in the
    // inventory, and may not even be modeled.)
    auto [baseLoc, connectorLoc] = extractConnectorFromLocCode(locationCode);

    auto method =
        _bus.new_method_call(service_name::vpdManager, object_path::vpdManager,
                             interface::vpdManager, methodName.c_str());

    if (expanded)
    {
        method.append(baseLoc);
    }
    else
    {
        method.append(addLocationCodePrefix(baseLoc), node);
    }

    auto reply = _bus.call(method, dbusTimeout);

    std::vector<sdbusplus::message::object_path> entries;
    reply.read(entries);

    // Get the shortest entry from the paths received, as this
    // would be the path furthest up the inventory hierarchy so
    // would be the parent FRU.  There is guaranteed to at least
    // be one entry if the call didn't fail.
    std::string shortest{entries[0]};

    std::for_each(entries.begin(), entries.end(),
                  [&shortest](const auto& path) {
                      if (path.str.size() < shortest.size())
                      {
                          shortest = path;
                      }
                  });

    return shortest;
}

void DataInterface::assertLEDGroup(const std::string& ledGroup,
                                   bool value) const
{
    DBusValue variant = value;
    auto method =
        _bus.new_method_call(service_name::ledGroupManager, ledGroup.c_str(),
                             interface::dbusProperty, "Set");
    method.append(interface::ledGroup, "Asserted", variant);
    _bus.call(method, dbusTimeout);
}

void DataInterface::setFunctional(const std::string& objectPath,
                                  bool value) const
{
    DBusValue variant = value;
    auto service = getService(objectPath, interface::operationalStatus);

    auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
                                       interface::dbusProperty, "Set");

    method.append(interface::operationalStatus, "Functional", variant);
    _bus.call(method, dbusTimeout);
}

using AssociationTuple = std::tuple<std::string, std::string, std::string>;
using AssociationsProperty = std::vector<AssociationTuple>;

void DataInterface::setCriticalAssociation(const std::string& objectPath) const
{
    DBusValue getAssociationValue;

    auto service = getService(objectPath, interface::associationDef);

    getProperty(service, objectPath, interface::associationDef, "Associations",
                getAssociationValue);

    auto association = std::get<AssociationsProperty>(getAssociationValue);

    AssociationTuple critAssociation{
        "health_rollup", "critical",
        "/xyz/openbmc_project/inventory/system/chassis"};

    if (std::find(association.begin(), association.end(), critAssociation) ==
        association.end())
    {
        association.push_back(critAssociation);
        DBusValue setAssociationValue = association;

        auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
                                           interface::dbusProperty, "Set");

        method.append(interface::associationDef, "Associations",
                      setAssociationValue);
        _bus.call(method, dbusTimeout);
    }
}

std::vector<std::string> DataInterface::getSystemNames() const
{
    DBusSubTree subtree;
    DBusValue names;

    auto method = _bus.new_method_call(service_name::objectMapper,
                                       object_path::objectMapper,
                                       interface::objectMapper, "GetSubTree");
    method.append(std::string{"/"}, 0,
                  std::vector<std::string>{interface::compatible});
    auto reply = _bus.call(method, dbusTimeout);

    reply.read(subtree);
    if (subtree.empty())
    {
        throw std::runtime_error("Compatible interface not on D-Bus");
    }

    const auto& object = *(subtree.begin());
    const auto& path = object.first;
    const auto& service = object.second.begin()->first;

    getProperty(service, path, interface::compatible, "Names", names);

    return std::get<std::vector<std::string>>(names);
}

bool DataInterface::getQuiesceOnError() const
{
    bool ret = false;

    try
    {
        auto service =
            getService(object_path::logSetting, interface::logSetting);
        if (!service.empty())
        {
            DBusValue value;
            getProperty(service, object_path::logSetting, interface::logSetting,
                        "QuiesceOnHwError", value);

            ret = std::get<bool>(value);
        }
    }
    catch (const std::exception& e)
    {
        log<level::WARNING>(
            fmt::format("Failed reading QuiesceOnHwError property from "
                        "Interface: {} exception: {}",
                        interface::logSetting, e.what())
                .c_str());
    }

    return ret;
}

std::vector<bool>
    DataInterface::checkDumpStatus(const std::vector<std::string>& type) const
{
    DBusSubTree subtree;
    std::vector<bool> result(type.size(), false);

    // Query GetSubTree for the availability of dump interface
    auto method = _bus.new_method_call(service_name::objectMapper,
                                       object_path::objectMapper,
                                       interface::objectMapper, "GetSubTree");
    method.append(std::string{"/"}, 0,
                  std::vector<std::string>{interface::dumpEntry});
    auto reply = _bus.call(method, dbusTimeout);

    reply.read(subtree);

    if (subtree.empty())
    {
        return result;
    }

    std::vector<bool>::iterator itDumpStatus = result.begin();
    uint8_t count = 0;
    for (const auto& [path, serviceInfo] : subtree)
    {
        const auto& service = serviceInfo.begin()->first;
        // Check for dump type on the object path
        for (const auto& it : type)
        {
            if (path.find(it) != std::string::npos)
            {
                DBusValue value, progress;

                // If dump type status is already available go for next path
                if (*itDumpStatus)
                {
                    break;
                }

                // Check for valid dump to be available if following
                // conditions are met for the dump entry path -
                // Offloaded == false and Status == Completed
                getProperty(service, path, interface::dumpEntry, "Offloaded",
                            value);
                getProperty(service, path, interface::dumpProgress, "Status",
                            progress);
                auto offload = std::get<bool>(value);
                auto status = std::get<std::string>(progress);
                if (!offload && (status.find("Completed") != std::string::npos))
                {
                    *itDumpStatus = true;
                    count++;
                    if (count >= type.size())
                    {
                        return result;
                    }
                    break;
                }
            }
            ++itDumpStatus;
        }
        itDumpStatus = result.begin();
    }

    return result;
}

void DataInterface::createGuardRecord(const std::vector<uint8_t>& binPath,
                                      const std::string& type,
                                      const std::string& logPath) const
{
    try
    {
        auto method = _bus.new_method_call(
            service_name::hwIsolation, object_path::hwIsolation,
            interface::hwIsolationCreate, "CreateWithEntityPath");
        method.append(binPath, type, sdbusplus::message::object_path(logPath));
        // Note: hw isolation "CreateWithEntityPath" got dependency on logging
        // api's. Making d-bus call no reply type to avoid cyclic dependency.
        // Added minimal timeout to catch initial failures.
        // Need to revisit this design later to avoid cyclic dependency.
        constexpr auto hwIsolationTimeout = 100000; // in micro seconds
        _bus.call_noreply(method, hwIsolationTimeout);
    }

    catch (const sdbusplus::exception_t& e)
    {
        std::string errName = e.name();
        // SD_BUS_ERROR_TIMEOUT error is expected, due to PEL api dependency
        // mentioned above. Ignoring the error.
        if (errName != SD_BUS_ERROR_TIMEOUT)
        {
            log<level::ERR>(
                fmt::format("GUARD D-Bus call exception"
                            "OBJPATH={}, INTERFACE={}, EXCEPTION={}",
                            object_path::hwIsolation,
                            interface::hwIsolationCreate, e.what())
                    .c_str());
        }
    }
}

void DataInterface::createProgressSRC(
    const uint64_t& priSRC, const std::vector<uint8_t>& srcStruct) const
{
    DBusValue variant = std::make_tuple(priSRC, srcStruct);

    auto method = _bus.new_method_call(service_name::bootRawProgress,
                                       object_path::bootRawSetting,
                                       interface::dbusProperty, "Set");

    method.append(interface::bootRawProgress, "Value", variant);

    _bus.call(method, dbusTimeout);
}

std::vector<uint32_t> DataInterface::getLogIDWithHwIsolation() const
{
    std::vector<std::string> association = {"xyz.openbmc_project.Association"};
    std::string hwErrorLog = "/isolated_hw_errorlog";
    std::string errorLog = "/error_log";
    DBusPathList paths;
    std::vector<uint32_t> ids;

    // Get all latest mapper associations
    paths = getPaths(association);
    for (auto& path : paths)
    {
        // Look for object path with hardware isolation entry if any
        size_t pos = path.find(hwErrorLog);
        if (pos != std::string::npos)
        {
            // Get the object path
            std::string ph = path;
            ph.erase(pos, hwErrorLog.length());
            auto service = getService(ph, interface::hwIsolationEntry);
            if (!service.empty())
            {
                bool status;
                DBusValue value;

                // Read the Resolved property from object path
                getProperty(service, ph, interface::hwIsolationEntry,
                            "Resolved", value);

                status = std::get<bool>(value);

                // If the entry isn't resolved
                if (!status)
                {
                    auto assocService =
                        getService(path, interface::association);
                    if (!assocService.empty())
                    {
                        DBusValue endpoints;

                        // Read Endpoints property
                        getProperty(assocService, path, interface::association,
                                    "endpoints", endpoints);

                        auto logPath =
                            std::get<std::vector<std::string>>(endpoints);
                        if (!logPath.empty())
                        {
                            // Get OpenBMC event log Id
                            uint32_t id = stoi(logPath[0].substr(
                                logPath[0].find_last_of('/') + 1));
                            ids.push_back(id);
                        }
                    }
                }
            }
        }

        // Look for object path with error_log entry if any
        pos = path.find(errorLog);
        if (pos != std::string::npos)
        {
            auto service = getService(path, interface::association);
            if (!service.empty())
            {
                DBusValue value;

                // Read Endpoints property
                getProperty(service, path, interface::association, "endpoints",
                            value);

                auto logPath = std::get<std::vector<std::string>>(value);
                if (!logPath.empty())
                {
                    // Get OpenBMC event log Id
                    uint32_t id = stoi(
                        logPath[0].substr(logPath[0].find_last_of('/') + 1));
                    ids.push_back(id);
                }
            }
        }
    }

    if (ids.size() > 1)
    {
        // remove duplicates to have only unique ids
        std::sort(ids.begin(), ids.end());
        ids.erase(std::unique(ids.begin(), ids.end()), ids.end());
    }
    return ids;
}
} // namespace pels
} // namespace openpower
