// Copyright 2022 Google LLC
//
// 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 "handler.hpp"

#include "bm_config.h"

#include "bmc_mode_enum.hpp"
#include "errors.hpp"
#include "handler_impl.hpp"
#include "util.hpp"

#include <fcntl.h>
#include <ipmid/api.h>
#include <mtd/mtd-abi.h>
#include <mtd/mtd-user.h>
#include <sys/ioctl.h>
#include <unistd.h>

#include <nlohmann/json.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
#include <stdplus/print.hpp>
#include <xyz/openbmc_project/Common/error.hpp>

#include <cinttypes>
#include <cstdio>
#include <filesystem>
#include <fstream>
#include <map>
#include <sstream>
#include <string>
#include <string_view>
#include <tuple>
#include <variant>

#ifndef NCSI_IF_NAME
#define NCSI_IF_NAME eth0
#endif

// To deal with receiving a string without quotes.
#define QUOTE(name) #name
#define STR(macro) QUOTE(macro)
#define NCSI_IF_NAME_STR STR(NCSI_IF_NAME)

namespace ipmi
{
std::uint8_t getChannelByName(const std::string& chName);
}

namespace google
{
namespace ipmi
{
using Json = nlohmann::json;
using namespace phosphor::logging;
using InternalFailure =
    sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
using Value = std::variant<double>;

uint8_t isBmcInBareMetalMode(const std::unique_ptr<FileSystemInterface>& fs)
{
#if BARE_METAL
    return static_cast<uint8_t>(BmcMode::BM_MODE);
#else
    std::error_code ec;

    if (fs->exists(bmDriveCleaningDoneAckFlagPath, ec))
    {
        stdplus::print(
            stderr,
            "{} exists so we acked cleaning done and must be in BM mode\n",
            bmDriveCleaningDoneAckFlagPath);
        return static_cast<uint8_t>(BmcMode::BM_MODE);
    }

    if (fs->exists(bmDriveCleaningDoneFlagPath, ec))
    {
        fs->rename(bmDriveCleaningDoneFlagPath, bmDriveCleaningDoneAckFlagPath,
                   ec);
        stdplus::print(
            stderr,
            "{} exists so we just finished cleaning and must be in BM mode\n",
            bmDriveCleaningDoneFlagPath);
        return static_cast<uint8_t>(BmcMode::BM_MODE);
    }

    if (fs->exists(BM_SIGNAL_PATH, ec))
    {
        if (!fs->exists(bmDriveCleaningFlagPath, ec))
        {
            fs->create(bmDriveCleaningFlagPath);
        }

        stdplus::print(
            stderr,
            "{} exists and no done/ack flag, we must be in BM cleaning mode\n",
            BM_SIGNAL_PATH);
        return static_cast<uint8_t>(BmcMode::BM_CLEANING_MODE);
    }

    stdplus::print(
        stderr,
        "Unable to find any BM state files so we must not be in BM mode\n");
    return static_cast<uint8_t>(BmcMode::NON_BM_MODE);
#endif
}

uint8_t Handler::getBmcMode()
{
    // BM_CLEANING_MODE is not implemented yet
    return isBmcInBareMetalMode(this->getFs());
}

std::tuple<std::uint8_t, std::string>
    Handler::getEthDetails(std::string intf) const
{
    if (intf.empty())
    {
        intf = NCSI_IF_NAME_STR;
    }
    return std::make_tuple(::ipmi::getChannelByName(intf), std::move(intf));
}

std::int64_t Handler::getRxPackets(const std::string& name) const
{
    std::ostringstream opath;
    opath << "/sys/class/net/" << name << "/statistics/rx_packets";
    std::string path = opath.str();

    // Minor sanity & security check (of course, I'm less certain if unicode
    // comes into play here.
    //
    // Basically you can't easily inject ../ or /../ into the path below.
    if (name.find("/") != std::string::npos)
    {
        stdplus::print(stderr, "Invalid or illegal name: '{}'\n", name);
        throw IpmiException(::ipmi::ccInvalidFieldRequest);
    }

    std::error_code ec;
    if (!this->getFs()->exists(path, ec))
    {
        stdplus::print(stderr, "Path: '{}' doesn't exist.\n", path);
        throw IpmiException(::ipmi::ccInvalidFieldRequest);
    }
    // We're uninterested in the state of ec.

    int64_t count = 0;
    std::ifstream ifs;
    ifs.exceptions(std::ifstream::failbit);
    try
    {
        ifs.open(path);
        ifs >> count;
    }
    catch (std::ios_base::failure& fail)
    {
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    return count;
}

VersionTuple Handler::getCpldVersion(unsigned int id) const
{
    std::ostringstream opath;
    opath << "/run/cpld" << id << ".version";
    // Check for file

    std::error_code ec;
    if (!this->getFs()->exists(opath.str(), ec))
    {
        stdplus::print(stderr, "Path: '{}' doesn't exist.\n", opath.str());
        throw IpmiException(::ipmi::ccInvalidFieldRequest);
    }
    // We're uninterested in the state of ec.

    // If file exists, read.
    std::ifstream ifs;
    ifs.exceptions(std::ifstream::failbit);
    std::string value;
    try
    {
        ifs.open(opath.str());
        ifs >> value;
    }
    catch (std::ios_base::failure& fail)
    {
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    // If value parses as expected, return version.
    VersionTuple version = std::make_tuple(0, 0, 0, 0);

    int num_fields = std::sscanf(value.c_str(),
                                 "%" SCNu8 ".%" SCNu8 ".%" SCNu8 ".%" SCNu8,
                                 &std::get<0>(version), &std::get<1>(version),
                                 &std::get<2>(version), &std::get<3>(version));
    if (num_fields == 0)
    {
        stdplus::print(stderr, "Invalid version.\n");
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    return version;
}

static constexpr auto TIME_DELAY_FILENAME = "/run/psu_timedelay";
static constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
static constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
static constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
static constexpr auto PSU_HARDRESET_TARGET = "gbmc-psu-hardreset.target";

void Handler::psuResetDelay(std::uint32_t delay) const
{
    std::ofstream ofs;
    ofs.open(TIME_DELAY_FILENAME, std::ofstream::out);
    if (!ofs.good())
    {
        stdplus::print(stderr, "Unable to open file for output.\n");
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    ofs << "PSU_HARDRESET_DELAY=" << delay << std::endl;
    if (ofs.fail())
    {
        stdplus::print(stderr, "Write failed\n");
        ofs.close();
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    // Write succeeded, please continue.
    ofs.flush();
    ofs.close();

    auto bus = sdbusplus::bus::new_default();
    auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
                                      SYSTEMD_INTERFACE, "StartUnit");

    method.append(PSU_HARDRESET_TARGET);
    method.append("replace");

    try
    {
        bus.call_noreply(method);
    }
    catch (const sdbusplus::exception::SdBusError& ex)
    {
        log<level::ERR>("Failed to call PSU hard reset");
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }
}

static constexpr auto RESET_ON_SHUTDOWN_FILENAME = "/run/powercycle_on_s5";

void Handler::psuResetOnShutdown() const
{
    std::ofstream ofs;
    ofs.open(RESET_ON_SHUTDOWN_FILENAME, std::ofstream::out);
    if (!ofs.good())
    {
        stdplus::print(stderr, "Unable to open file for output.\n");
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }
    ofs.close();
}

uint32_t Handler::getFlashSize()
{
    mtd_info_t info;
    int fd = open("/dev/mtd0", O_RDONLY);
    int err = ioctl(fd, MEMGETINFO, &info);
    close(fd);

    if (err)
    {
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }
    return info.size;
}

std::string Handler::getEntityName(std::uint8_t id, std::uint8_t instance)
{
    // Check if we support this Entity ID.
    auto it = _entityIdToName.find(id);
    if (it == _entityIdToName.end())
    {
        log<level::ERR>("Unknown Entity ID", entry("ENTITY_ID=%d", id));
        throw IpmiException(::ipmi::ccInvalidFieldRequest);
    }

    std::string entityName;
    try
    {
        // Parse the JSON config file.
        if (!_entityConfigParsed)
        {
            _entityConfig = parseConfig(_configFile);
            _entityConfigParsed = true;
        }

        // Find the "entity id:entity instance" mapping to entity name.
        entityName = readNameFromConfig(it->second, instance, _entityConfig);
        if (entityName.empty())
        {
            throw IpmiException(::ipmi::ccInvalidFieldRequest);
        }
    }
    catch (InternalFailure& e)
    {
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    return entityName;
}

std::string Handler::getMachineName()
{
    const char* path = "/etc/os-release";
    std::ifstream ifs(path);
    if (ifs.fail())
    {
        stdplus::print(stderr, "Failed to open: {}\n", path);
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    std::string line;
    while (true)
    {
        std::getline(ifs, line);
        if (ifs.eof())
        {
            stdplus::print(stderr,
                           "Failed to find OPENBMC_TARGET_MACHINE: {}\n", path);
            throw IpmiException(::ipmi::ccInvalidCommand);
        }
        if (ifs.fail())
        {
            stdplus::print(stderr, "Failed to read: {}\n", path);
            throw IpmiException(::ipmi::ccUnspecifiedError);
        }
        std::string_view lineView(line);
        constexpr std::string_view prefix = "OPENBMC_TARGET_MACHINE=";
        if (lineView.substr(0, prefix.size()) != prefix)
        {
            continue;
        }
        lineView.remove_prefix(prefix.size());
        lineView.remove_prefix(
            std::min(lineView.find_first_not_of('"'), lineView.size()));
        lineView.remove_suffix(
            lineView.size() - 1 -
            std::min(lineView.find_last_not_of('"'), lineView.size() - 1));
        return std::string(lineView);
    }
}

static constexpr auto HOST_TIME_DELAY_FILENAME = "/run/host_poweroff_delay";
static constexpr auto HOST_POWEROFF_TARGET = "gbmc-host-poweroff.target";

void Handler::hostPowerOffDelay(std::uint32_t delay) const
{
    // Set time delay
    std::ofstream ofs;
    ofs.open(HOST_TIME_DELAY_FILENAME, std::ofstream::out);
    if (!ofs.good())
    {
        stdplus::print(stderr, "Unable to open file for output.\n");
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    ofs << "HOST_POWEROFF_DELAY=" << delay << std::endl;
    ofs.close();
    if (ofs.fail())
    {
        stdplus::print(stderr, "Write failed\n");
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    // Write succeeded, please continue.
    auto bus = sdbusplus::bus::new_default();
    auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
                                      SYSTEMD_INTERFACE, "StartUnit");

    method.append(HOST_POWEROFF_TARGET);
    method.append("replace");

    try
    {
        bus.call_noreply(method);
    }
    catch (const sdbusplus::exception::SdBusError& ex)
    {
        log<level::ERR>("Failed to call Power Off",
                        entry("WHAT=%s", ex.what()));
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }
}

std::string readNameFromConfig(const std::string& type, uint8_t instance,
                               const Json& config)
{
    static const std::vector<Json> empty{};
    std::vector<Json> readings = config.value(type, empty);
    std::string name = "";

    for (const auto& j : readings)
    {
        uint8_t instanceNum = j.value("instance", 0);
        // Not the instance we're interested in
        if (instanceNum != instance)
        {
            continue;
        }

        // Found the instance we're interested in
        name = j.value("name", "");

        break;
    }

    return name;
}

void Handler::buildI2cPcieMapping()
{
    _pcie_i2c_map = buildPcieMap();
}

size_t Handler::getI2cPcieMappingSize() const
{
    return _pcie_i2c_map.size();
}

std::tuple<std::uint32_t, std::string>
    Handler::getI2cEntry(unsigned int entry) const
{
    return _pcie_i2c_map[entry];
}

namespace
{

static constexpr std::string_view ACCEL_OOB_ROOT = "/com/google/customAccel/";
static constexpr char ACCEL_OOB_SERVICE[] = "com.google.custom_accel";
static constexpr char ACCEL_OOB_INTERFACE[] = "com.google.custom_accel.BAR";

// C type for "a{oa{sa{sv}}}" from DBus.ObjectManager::GetManagedObjects()
using AnyType = std::variant<std::string, uint8_t, uint32_t, uint64_t>;
using AnyTypeList = std::vector<std::pair<std::string, AnyType>>;
using NamedArrayOfAnyTypeLists =
    std::vector<std::pair<std::string, AnyTypeList>>;
using ArrayOfObjectPathsAndTieredAnyTypeLists = std::vector<
    std::pair<sdbusplus::message::object_path, NamedArrayOfAnyTypeLists>>;

} // namespace

sdbusplus::bus_t Handler::getDbus() const
{
    return sdbusplus::bus::new_default();
}

const std::unique_ptr<FileSystemInterface>& Handler::getFs() const
{
    return this->fsPtr;
}

uint32_t Handler::accelOobDeviceCount() const
{
    ArrayOfObjectPathsAndTieredAnyTypeLists data;

    try
    {
        auto bus = getDbus();
        auto method = bus.new_method_call(ACCEL_OOB_SERVICE, "/",
                                          "org.freedesktop.DBus.ObjectManager",
                                          "GetManagedObjects");
        bus.call(method).read(data);
    }
    catch (const sdbusplus::exception::SdBusError& ex)
    {
        log<level::ERR>(
            "Failed to call GetManagedObjects on com.google.custom_accel",
            entry("WHAT=%s", ex.what()));
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    return data.size();
}

std::string Handler::accelOobDeviceName(size_t index) const
{
    ArrayOfObjectPathsAndTieredAnyTypeLists data;

    try
    {
        auto bus = getDbus();
        auto method = bus.new_method_call(ACCEL_OOB_SERVICE, "/",
                                          "org.freedesktop.DBus.ObjectManager",
                                          "GetManagedObjects");
        bus.call(method).read(data);
    }
    catch (const sdbusplus::exception::SdBusError& ex)
    {
        log<level::ERR>(
            "Failed to call GetManagedObjects on com.google.custom_accel",
            entry("WHAT=%s", ex.what()));
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    if (index >= data.size())
    {
        log<level::WARNING>(
            "Requested index is larger than the number of entries.",
            entry("INDEX=%zu", index), entry("NUM_NAMES=%zu", data.size()));
        throw IpmiException(::ipmi::ccParmOutOfRange);
    }

    std::string_view name(data[index].first.str);
    if (!name.starts_with(ACCEL_OOB_ROOT))
    {
        throw IpmiException(::ipmi::ccInvalidCommand);
    }
    name.remove_prefix(ACCEL_OOB_ROOT.length());
    return std::string(name);
}

uint64_t Handler::accelOobRead(std::string_view name, uint64_t address,
                               uint8_t num_bytes) const
{
    static constexpr char ACCEL_OOB_METHOD[] = "Read";

    std::string object_name(ACCEL_OOB_ROOT);
    object_name.append(name);

    auto bus = getDbus();
    auto method = bus.new_method_call(ACCEL_OOB_SERVICE, object_name.c_str(),
                                      ACCEL_OOB_INTERFACE, ACCEL_OOB_METHOD);
    method.append(address, static_cast<uint64_t>(num_bytes));

    std::vector<uint8_t> bytes;

    try
    {
        bus.call(method).read(bytes);
    }
    catch (const sdbusplus::exception::SdBusError& ex)
    {
        log<level::ERR>("Failed to call Read on com.google.custom_accel",
                        entry("WHAT=%s", ex.what()),
                        entry("DBUS_SERVICE=%s", ACCEL_OOB_SERVICE),
                        entry("DBUS_OBJECT=%s", object_name.c_str()),
                        entry("DBUS_INTERFACE=%s", ACCEL_OOB_INTERFACE),
                        entry("DBUS_METHOD=%s", ACCEL_OOB_METHOD),
                        entry("DBUS_ARG_ADDRESS=%016llx", address),
                        entry("DBUS_ARG_NUM_BYTES=%zu", (size_t)num_bytes));
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    if (bytes.size() < num_bytes)
    {
        log<level::ERR>(
            "Call to Read on com.google.custom_accel didn't return the expected"
            " number of bytes.",
            entry("DBUS_SERVICE=%s", ACCEL_OOB_SERVICE),
            entry("DBUS_OBJECT=%s", object_name.c_str()),
            entry("DBUS_INTERFACE=%s", ACCEL_OOB_INTERFACE),
            entry("DBUS_METHOD=%s", ACCEL_OOB_METHOD),
            entry("DBUS_ARG_ADDRESS=%016llx", address),
            entry("DBUS_ARG_NUM_BYTES=%zu", (size_t)num_bytes),
            entry("DBUS_RETURN_SIZE=%zu", bytes.size()));
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    if (bytes.size() > sizeof(uint64_t))
    {
        log<level::ERR>(
            "Call to Read on com.google.custom_accel returned more than 8B.",
            entry("DBUS_SERVICE=%s", ACCEL_OOB_SERVICE),
            entry("DBUS_OBJECT=%s", object_name.c_str()),
            entry("DBUS_INTERFACE=%s", ACCEL_OOB_INTERFACE),
            entry("DBUS_METHOD=%s", ACCEL_OOB_METHOD),
            entry("DBUS_ARG_ADDRESS=%016llx", address),
            entry("DBUS_ARG_NUM_BYTES=%zu", (size_t)num_bytes),
            entry("DBUS_RETURN_SIZE=%zu", bytes.size()));
        throw IpmiException(::ipmi::ccReqDataTruncated);
    }

    uint64_t data = 0;
    for (size_t i = 0; i < num_bytes; ++i)
    {
        data = (data << 8) | bytes[i];
    }

    return data;
}

void Handler::accelOobWrite(std::string_view name, uint64_t address,
                            uint8_t num_bytes, uint64_t data) const
{
    static constexpr std::string_view ACCEL_OOB_METHOD = "Write";

    std::string object_name(ACCEL_OOB_ROOT);
    object_name.append(name);

    if (num_bytes > sizeof(data))
    {
        log<level::ERR>(
            "Call to Write on com.google.custom_accel requested more than 8B.",
            entry("DBUS_SERVICE=%s", ACCEL_OOB_SERVICE),
            entry("DBUS_OBJECT=%s", object_name.c_str()),
            entry("DBUS_INTERFACE=%s", ACCEL_OOB_INTERFACE),
            entry("DBUS_METHOD=%s", ACCEL_OOB_METHOD.data()),
            entry("DBUS_ARG_ADDRESS=%016llx", address),
            entry("DBUS_ARG_NUM_BYTES=%zu", (size_t)num_bytes),
            entry("DBUS_ARG_DATA=%016llx", data));
        throw IpmiException(::ipmi::ccParmOutOfRange);
    }

    std::vector<uint8_t> bytes;
    bytes.reserve(num_bytes);
    for (size_t i = 0; i < num_bytes; ++i)
    {
        bytes.emplace_back(data & 0xff);
        data >>= 8;
    }

    try
    {
        auto bus = getDbus();
        auto method =
            bus.new_method_call(ACCEL_OOB_SERVICE, object_name.c_str(),
                                ACCEL_OOB_INTERFACE, ACCEL_OOB_METHOD.data());
        method.append(address, bytes);
        bus.call_noreply(method);
    }
    catch (const sdbusplus::exception::SdBusError& ex)
    {
        log<level::ERR>("Failed to call Write on com.google.custom_accel",
                        entry("WHAT=%s", ex.what()),
                        entry("DBUS_SERVICE=%s", ACCEL_OOB_SERVICE),
                        entry("DBUS_OBJECT=%s", object_name.c_str()),
                        entry("DBUS_INTERFACE=%s", ACCEL_OOB_INTERFACE),
                        entry("DBUS_METHOD=%s", ACCEL_OOB_METHOD.data()),
                        entry("DBUS_ARG_ADDRESS=%016llx", address),
                        entry("DBUS_ARG_NUM_BYTES=%zu", (size_t)num_bytes),
                        entry("DBUS_ARG_DATA=%016llx", data));
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }
}

std::vector<uint8_t> Handler::pcieBifurcation(uint8_t index)
{
    return bifurcationHelper.get().getBifurcation(index).value_or(
        std::vector<uint8_t>{});
}

static constexpr auto BARE_METAL_TARGET = "gbmc-bare-metal-active.target";

void Handler::linuxBootDone() const
{
    if (isBmcInBareMetalMode(this->fsPtr) !=
        static_cast<uint8_t>(BmcMode::BM_MODE))
    {
        return;
    }

    log<level::INFO>("LinuxBootDone: Disabling IPMI");

    // Start the bare metal active systemd target.
    auto bus = sdbusplus::bus::new_default();
    auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
                                      SYSTEMD_INTERFACE, "StartUnit");

    method.append(BARE_METAL_TARGET);
    method.append("replace");

    try
    {
        bus.call_noreply(method);
    }
    catch (const sdbusplus::exception::SdBusError& ex)
    {
        log<level::ERR>("Failed to start bare metal active systemd target",
                        entry("WHAT=%s", ex.what()));
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }
}

static constexpr char ACCEL_POWER_SERVICE[] = "xyz.openbmc_project.AccelPower";
static constexpr char ACCEL_POWER_PATH_PREFIX[] =
    "/xyz/openbmc_project/control/accel_power_";
static constexpr char POWER_MODE_IFC[] =
    "xyz.openbmc_project.Control.Power.Mode";

void Handler::accelSetVrSettings(::ipmi::Context::ptr ctx, uint8_t chip_id,
                                 uint8_t settings_id, uint16_t value) const
{
    int vrSettingsReq;
    boost::system::error_code ec;
    if (_vrSettingsMap.find(settings_id) == _vrSettingsMap.end())
    {
        log<level::ERR>("Settings ID is not supported",
                        entry("settings_id=%d", settings_id));
        throw IpmiException(::ipmi::ccParmOutOfRange);
    }

    vrSettingsReq = static_cast<int>(settings_id | value << 8);
    std::string object_name(
        std::format("{}{}", ACCEL_POWER_PATH_PREFIX, chip_id));

    std::variant<int> val = vrSettingsReq;
    ctx->bus->yield_method_call(ctx->yield, ec, ACCEL_POWER_SERVICE,
                                object_name.c_str(),
                                "org.freedesktop.DBus.Properties", "Set",
                                POWER_MODE_IFC, "PowerMode", val);
    if (ec)
    {
        log<level::ERR>("Failed to set PowerMode property");
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }
}

static constexpr char EXTERNAL_SENSOR_SERVICE[] =
    "xyz.openbmc_project.ExternalSensor";
static constexpr char EXTERNAL_SENSOR_PATH_PREFIX[] =
    "/xyz/openbmc_project/sensors/power/";
static constexpr char SENSOR_VALUE_IFC[] = "xyz.openbmc_project.Sensor.Value";

uint16_t Handler::accelGetVrSettings(::ipmi::Context::ptr ctx, uint8_t chip_id,
                                     uint8_t settings_id) const
{
    Value value;
    boost::system::error_code ec;
    std::string object_name(std::format("{}{}{}", EXTERNAL_SENSOR_PATH_PREFIX,
                                        _vrSettingsMap.at(settings_id),
                                        chip_id));

    if (_vrSettingsMap.find(settings_id) == _vrSettingsMap.end())
    {
        log<level::ERR>("Settings ID is not supported",
                        entry("settings_id=%d", settings_id));
        throw IpmiException(::ipmi::ccParmOutOfRange);
    }

    value = ctx->bus->yield_method_call<std::variant<double>>(
        ctx->yield, ec, EXTERNAL_SENSOR_SERVICE, object_name.c_str(),
        "org.freedesktop.DBus.Properties", "Get", SENSOR_VALUE_IFC, "Value");
    if (ec)
    {
        log<level::ERR>("accelGetVrSettings: Failed to call GetObject ");
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    return static_cast<uint16_t>(std::get<double>(value));
}
} // namespace ipmi
} // namespace google
