#include "config.h"

#include "sensorhandler.hpp"

#include "fruread.hpp"

#include <systemd/sd-bus.h>

#include <ipmid/api.hpp>
#include <ipmid/entity_map_json.hpp>
#include <ipmid/types.hpp>
#include <ipmid/utils.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/message/types.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
#include <xyz/openbmc_project/Sensor/Value/server.hpp>

#include <bitset>
#include <cmath>
#include <cstring>
#include <set>

static constexpr uint8_t fruInventoryDevice = 0x10;
static constexpr uint8_t IPMIFruInventory = 0x02;
static constexpr uint8_t BMCTargetAddress = 0x20;

extern int updateSensorRecordFromSSRAESC(const void*);
extern sd_bus* bus;

namespace ipmi
{
namespace sensor
{
extern const IdInfoMap sensors;
} // namespace sensor
} // namespace ipmi

extern const FruMap frus;

using namespace phosphor::logging;
using InternalFailure =
    sdbusplus::error::xyz::openbmc_project::common::InternalFailure;

using SensorValue = sdbusplus::common::xyz::openbmc_project::sensor::Value;

void registerNetFnSenFunctions() __attribute__((constructor));

struct sensorTypemap_t
{
    uint8_t number;
    uint8_t typecode;
    char dbusname[32];
};

sensorTypemap_t g_SensorTypeMap[] = {

    {0x01, 0x6F, "Temp"},
    {0x0C, 0x6F, "DIMM"},
    {0x0C, 0x6F, "MEMORY_BUFFER"},
    {0x07, 0x6F, "PROC"},
    {0x07, 0x6F, "CORE"},
    {0x07, 0x6F, "CPU"},
    {0x0F, 0x6F, "BootProgress"},
    {0xe9, 0x09, "OccStatus"}, // E9 is an internal mapping to handle sensor
                               // type code os 0x09
    {0xC3, 0x6F, "BootCount"},
    {0x1F, 0x6F, "OperatingSystemStatus"},
    {0x12, 0x6F, "SYSTEM_EVENT"},
    {0xC7, 0x03, "SYSTEM"},
    {0xC7, 0x03, "MAIN_PLANAR"},
    {0xC2, 0x6F, "PowerCap"},
    {0x0b, 0xCA, "PowerSupplyRedundancy"},
    {0xDA, 0x03, "TurboAllowed"},
    {0xD8, 0xC8, "PowerSupplyDerating"},
    {0xFF, 0x00, ""},
};

struct sensor_data_t
{
    uint8_t sennum;
} __attribute__((packed));

using SDRCacheMap = std::unordered_map<uint8_t, get_sdr::SensorDataFullRecord>;
SDRCacheMap sdrCacheMap __attribute__((init_priority(101)));

using SensorThresholdMap =
    std::unordered_map<uint8_t, get_sdr::GetSensorThresholdsResponse>;
SensorThresholdMap sensorThresholdMap __attribute__((init_priority(101)));

#ifdef FEATURE_SENSORS_CACHE
std::map<uint8_t, std::unique_ptr<sdbusplus::bus::match_t>> sensorAddedMatches
    __attribute__((init_priority(101)));
std::map<uint8_t, std::unique_ptr<sdbusplus::bus::match_t>> sensorUpdatedMatches
    __attribute__((init_priority(101)));
std::map<uint8_t, std::unique_ptr<sdbusplus::bus::match_t>> sensorRemovedMatches
    __attribute__((init_priority(101)));
std::unique_ptr<sdbusplus::bus::match_t> sensorsOwnerMatch
    __attribute__((init_priority(101)));

ipmi::sensor::SensorCacheMap sensorCacheMap __attribute__((init_priority(101)));

// It is needed to know which objects belong to which service, so that when a
// service exits without interfacesRemoved signal, we could invaildate the cache
// that is related to the service. It uses below two variables:
// - idToServiceMap records which sensors are known to have a related service;
// - serviceToIdMap maps a service to the sensors.
using sensorIdToServiceMap = std::unordered_map<uint8_t, std::string>;
sensorIdToServiceMap idToServiceMap __attribute__((init_priority(101)));

using sensorServiceToIdMap = std::unordered_map<std::string, std::set<uint8_t>>;
sensorServiceToIdMap serviceToIdMap __attribute__((init_priority(101)));

static void fillSensorIdServiceMap(const std::string&,
                                   const std::string& /*intf*/, uint8_t id,
                                   const std::string& service)
{
    if (idToServiceMap.find(id) != idToServiceMap.end())
    {
        return;
    }
    idToServiceMap[id] = service;
    serviceToIdMap[service].insert(id);
}

static void fillSensorIdServiceMap(const std::string& obj,
                                   const std::string& intf, uint8_t id)
{
    if (idToServiceMap.find(id) != idToServiceMap.end())
    {
        return;
    }
    try
    {
        sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
        auto service = ipmi::getService(bus, intf, obj);
        idToServiceMap[id] = service;
        serviceToIdMap[service].insert(id);
    }
    catch (...)
    {
        // Ignore
    }
}

void initSensorMatches()
{
    using namespace sdbusplus::bus::match::rules;
    sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
    for (const auto& s : ipmi::sensor::sensors)
    {
        sensorAddedMatches.emplace(
            s.first,
            std::make_unique<sdbusplus::bus::match_t>(
                bus, interfacesAdded() + argNpath(0, s.second.sensorPath),
                [id = s.first, obj = s.second.sensorPath,
                 intf = s.second.propertyInterfaces.begin()->first](
                    auto& /*msg*/) { fillSensorIdServiceMap(obj, intf, id); }));
        sensorRemovedMatches.emplace(
            s.first,
            std::make_unique<sdbusplus::bus::match_t>(
                bus, interfacesRemoved() + argNpath(0, s.second.sensorPath),
                [id = s.first](auto& /*msg*/) {
                    // Ideally this should work.
                    // But when a service is terminated or crashed, it does not
                    // emit interfacesRemoved signal. In that case it's handled
                    // by sensorsOwnerMatch
                    sensorCacheMap[id].reset();
                }));
        sensorUpdatedMatches.emplace(
            s.first,
            std::make_unique<sdbusplus::bus::match_t>(
                bus,
                type::signal() + path(s.second.sensorPath) +
                    member("PropertiesChanged"s) +
                    interface("org.freedesktop.DBus.Properties"s),
                [&s](auto& msg) {
                    fillSensorIdServiceMap(
                        s.second.sensorPath,
                        s.second.propertyInterfaces.begin()->first, s.first);
                    try
                    {
                        // This is signal callback
                        auto interfaceName = msg.unpack<std::string>();

                        auto props = msg.unpack<ipmi::PropertyMap>();

                        s.second.getFunc(s.first, s.second, props);
                    }
                    catch (const std::exception& e)
                    {
                        sensorCacheMap[s.first].reset();
                    }
                }));
    }
    sensorsOwnerMatch = std::make_unique<sdbusplus::bus::match_t>(
        bus, nameOwnerChanged(), [](auto& msg) {
            std::string name;
            std::string oldOwner;
            std::string newOwner;
            msg.read(name, oldOwner, newOwner);

            if (!name.empty() && newOwner.empty())
            {
                // The service exits
                const auto it = serviceToIdMap.find(name);
                if (it == serviceToIdMap.end())
                {
                    return;
                }
                for (const auto& id : it->second)
                {
                    // Invalidate cache
                    sensorCacheMap[id].reset();
                }
            }
        });
}
#endif

// Use a lookup table to find the interface name of a specific sensor
// This will be used until an alternative is found.  this is the first
// step for mapping IPMI
int find_openbmc_path(uint8_t num, dbus_interface_t* interface)
{
    const auto& sensor_it = ipmi::sensor::sensors.find(num);
    if (sensor_it == ipmi::sensor::sensors.end())
    {
        // The sensor map does not contain the sensor requested
        return -EINVAL;
    }

    const auto& info = sensor_it->second;

    std::string serviceName{};
    try
    {
        sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
        serviceName =
            ipmi::getService(bus, info.sensorInterface, info.sensorPath);
    }
    catch (const sdbusplus::exception_t&)
    {
        std::fprintf(stderr, "Failed to get %s busname: %s\n",
                     info.sensorPath.c_str(), serviceName.c_str());
        return -EINVAL;
    }

    interface->sensortype = info.sensorType;
    strcpy(interface->bus, serviceName.c_str());
    strcpy(interface->path, info.sensorPath.c_str());
    // Take the interface name from the beginning of the DbusInterfaceMap. This
    // works for the Value interface but may not suffice for more complex
    // sensors.
    // tracked https://github.com/openbmc/phosphor-host-ipmid/issues/103
    strcpy(interface->interface,
           info.propertyInterfaces.begin()->first.c_str());
    interface->sensornumber = num;

    return 0;
}

/////////////////////////////////////////////////////////////////////
//
// Routines used by ipmi commands wanting to interact on the dbus
//
/////////////////////////////////////////////////////////////////////
int set_sensor_dbus_state_s(uint8_t number, const char* method,
                            const char* value)
{
    dbus_interface_t a;
    int r;
    sd_bus_error error = SD_BUS_ERROR_NULL;
    sd_bus_message* m = nullptr;

    r = find_openbmc_path(number, &a);

    if (r < 0)
    {
        std::fprintf(stderr, "Failed to find Sensor 0x%02x\n", number);
        return 0;
    }

    r = sd_bus_message_new_method_call(bus, &m, a.bus, a.path, a.interface,
                                       method);
    if (r < 0)
    {
        std::fprintf(stderr, "Failed to create a method call: %s",
                     strerror(-r));
        goto final;
    }

    r = sd_bus_message_append(m, "v", "s", value);
    if (r < 0)
    {
        std::fprintf(stderr, "Failed to create a input parameter: %s",
                     strerror(-r));
        goto final;
    }

    r = sd_bus_call(bus, m, 0, &error, nullptr);
    if (r < 0)
    {
        std::fprintf(stderr, "Failed to call the method: %s", strerror(-r));
    }

final:
    sd_bus_error_free(&error);
    m = sd_bus_message_unref(m);

    return 0;
}
int set_sensor_dbus_state_y(uint8_t number, const char* method,
                            const uint8_t value)
{
    dbus_interface_t a;
    int r;
    sd_bus_error error = SD_BUS_ERROR_NULL;
    sd_bus_message* m = nullptr;

    r = find_openbmc_path(number, &a);

    if (r < 0)
    {
        std::fprintf(stderr, "Failed to find Sensor 0x%02x\n", number);
        return 0;
    }

    r = sd_bus_message_new_method_call(bus, &m, a.bus, a.path, a.interface,
                                       method);
    if (r < 0)
    {
        std::fprintf(stderr, "Failed to create a method call: %s",
                     strerror(-r));
        goto final;
    }

    r = sd_bus_message_append(m, "v", "i", value);
    if (r < 0)
    {
        std::fprintf(stderr, "Failed to create a input parameter: %s",
                     strerror(-r));
        goto final;
    }

    r = sd_bus_call(bus, m, 0, &error, nullptr);
    if (r < 0)
    {
        std::fprintf(stderr, "12 Failed to call the method: %s", strerror(-r));
    }

final:
    sd_bus_error_free(&error);
    m = sd_bus_message_unref(m);

    return 0;
}

uint8_t dbus_to_sensor_type(char* p)
{
    sensorTypemap_t* s = g_SensorTypeMap;
    char r = 0;
    while (s->number != 0xFF)
    {
        if (!strcmp(s->dbusname, p))
        {
            r = s->typecode;
            break;
        }
        s++;
    }

    if (s->number == 0xFF)
        printf("Failed to find Sensor Type %s\n", p);

    return r;
}

uint8_t get_type_from_interface(dbus_interface_t dbus_if)
{
    uint8_t type;

    // This is where sensors that do not exist in dbus but do
    // exist in the host code stop.  This should indicate it
    // is not a supported sensor
    if (dbus_if.interface[0] == 0)
    {
        return 0;
    }

    // Fetch type from interface itself.
    if (dbus_if.sensortype != 0)
    {
        type = dbus_if.sensortype;
    }
    else
    {
        // Non InventoryItems
        char* p = strrchr(dbus_if.path, '/');
        type = dbus_to_sensor_type(p + 1);
    }

    return type;
}

// Replaces find_sensor
uint8_t find_type_for_sensor_number(uint8_t num)
{
    int r;
    dbus_interface_t dbus_if;
    r = find_openbmc_path(num, &dbus_if);
    if (r < 0)
    {
        std::fprintf(stderr, "Could not find sensor %d\n", num);
        return 0;
    }
    return get_type_from_interface(dbus_if);
}

/**
 *  @brief implements the get sensor type command.
 *  @param - sensorNumber
 *
 *  @return IPMI completion code plus response data on success.
 *   - sensorType
 *   - eventType
 **/

ipmi::RspType<uint8_t, // sensorType
              uint8_t  // eventType
              >
    ipmiGetSensorType(uint8_t sensorNumber)
{
    const auto it = ipmi::sensor::sensors.find(sensorNumber);
    if (it == ipmi::sensor::sensors.end())
    {
        // The sensor map does not contain the sensor requested
        return ipmi::responseSensorInvalid();
    }

    const auto& info = it->second;
    uint8_t sensorType = info.sensorType;
    uint8_t eventType = info.sensorReadingType;

    return ipmi::responseSuccess(sensorType, eventType);
}

const std::set<std::string> analogSensorInterfaces = {
    SensorValue::interface,
    "xyz.openbmc_project.Control.FanPwm",
};

bool isAnalogSensor(const std::string& interface)
{
    return (analogSensorInterfaces.count(interface));
}

/**
@brief This command is used to set sensorReading.

@param
    -  sensorNumber
    -  operation
    -  reading
    -  assertOffset0_7
    -  assertOffset8_14
    -  deassertOffset0_7
    -  deassertOffset8_14
    -  eventData1
    -  eventData2
    -  eventData3

@return completion code on success.
**/

ipmi::RspType<> ipmiSetSensorReading(
    uint8_t sensorNumber, uint8_t operation, uint8_t reading,
    uint8_t assertOffset0_7, uint8_t assertOffset8_14,
    uint8_t deassertOffset0_7, uint8_t deassertOffset8_14, uint8_t eventData1,
    uint8_t eventData2, uint8_t eventData3)
{
    lg2::debug("IPMI SET_SENSOR, sensorNumber: {SENSOR_NUM}", "SENSOR_NUM",
               lg2::hex, sensorNumber);

    if (sensorNumber == 0xFF)
    {
        return ipmi::responseInvalidFieldRequest();
    }
    ipmi::sensor::SetSensorReadingReq cmdData;

    cmdData.number = sensorNumber;
    cmdData.operation = operation;
    cmdData.reading = reading;
    cmdData.assertOffset0_7 = assertOffset0_7;
    cmdData.assertOffset8_14 = assertOffset8_14;
    cmdData.deassertOffset0_7 = deassertOffset0_7;
    cmdData.deassertOffset8_14 = deassertOffset8_14;
    cmdData.eventData1 = eventData1;
    cmdData.eventData2 = eventData2;
    cmdData.eventData3 = eventData3;

    // Check if the Sensor Number is present
    const auto iter = ipmi::sensor::sensors.find(sensorNumber);
    if (iter == ipmi::sensor::sensors.end())
    {
        updateSensorRecordFromSSRAESC(&sensorNumber);
        return ipmi::responseSuccess();
    }

    try
    {
        if (ipmi::sensor::Mutability::Write !=
            (iter->second.mutability & ipmi::sensor::Mutability::Write))
        {
            lg2::error("Sensor Set operation is not allowed, "
                       "sensorNumber: {SENSOR_NUM}",
                       "SENSOR_NUM", lg2::hex, sensorNumber);
            return ipmi::responseIllegalCommand();
        }
        auto ipmiRC = iter->second.updateFunc(cmdData, iter->second);
        return ipmi::response(ipmiRC);
    }
    catch (const InternalFailure& e)
    {
        lg2::error("Set sensor failed, sensorNumber: {SENSOR_NUM}",
                   "SENSOR_NUM", lg2::hex, sensorNumber);
        commit<InternalFailure>();
        return ipmi::responseUnspecifiedError();
    }
    catch (const std::runtime_error& e)
    {
        lg2::error("runtime error: {ERROR}", "ERROR", e);
        return ipmi::responseUnspecifiedError();
    }
}

/** @brief implements the get sensor reading command
 *  @param sensorNum - sensor number
 *
 *  @returns IPMI completion code plus response data
 *   - senReading           - sensor reading
 *   - reserved
 *   - readState            - sensor reading state enabled
 *   - senScanState         - sensor scan state disabled
 *   - allEventMessageState - all Event message state disabled
 *   - assertionStatesLsb   - threshold levels states
 *   - assertionStatesMsb   - discrete reading sensor states
 */
ipmi::RspType<uint8_t, // sensor reading

              uint5_t, // reserved
              bool,    // reading state
              bool,    // 0 = sensor scanning state disabled
              bool,    // 0 = all event messages disabled

              uint8_t, // threshold levels states
              uint8_t  // discrete reading sensor states
              >
    ipmiSensorGetSensorReading([[maybe_unused]] ipmi::Context::ptr& ctx,
                               uint8_t sensorNum)
{
    if (sensorNum == 0xFF)
    {
        return ipmi::responseInvalidFieldRequest();
    }

    const auto iter = ipmi::sensor::sensors.find(sensorNum);
    if (iter == ipmi::sensor::sensors.end())
    {
        return ipmi::responseSensorInvalid();
    }
    if (ipmi::sensor::Mutability::Read !=
        (iter->second.mutability & ipmi::sensor::Mutability::Read))
    {
        return ipmi::responseIllegalCommand();
    }

    try
    {
#ifdef FEATURE_SENSORS_CACHE
        auto& sensorData = sensorCacheMap[sensorNum];
        if (!sensorData.has_value())
        {
            // No cached value, try read it
            std::string service;
            boost::system::error_code ec;
            const auto& sensorInfo = iter->second;
            ec = ipmi::getService(ctx, sensorInfo.sensorInterface,
                                  sensorInfo.sensorPath, service);
            if (ec)
            {
                return ipmi::responseUnspecifiedError();
            }
            fillSensorIdServiceMap(sensorInfo.sensorPath,
                                   sensorInfo.propertyInterfaces.begin()->first,
                                   iter->first, service);

            ipmi::PropertyMap props;
            ec = ipmi::getAllDbusProperties(
                ctx, service, sensorInfo.sensorPath,
                sensorInfo.propertyInterfaces.begin()->first, props);
            if (ec)
            {
                fprintf(stderr, "Failed to get sensor %s, %d: %s\n",
                        sensorInfo.sensorPath.c_str(), ec.value(),
                        ec.message().c_str());
                // Intitilizing with default values
                constexpr uint8_t senReading = 0;
                constexpr uint5_t reserved{0};
                constexpr bool readState = true;
                constexpr bool senScanState = false;
                constexpr bool allEventMessageState = false;
                constexpr uint8_t assertionStatesLsb = 0;
                constexpr uint8_t assertionStatesMsb = 0;

                return ipmi::responseSuccess(
                    senReading, reserved, readState, senScanState,
                    allEventMessageState, assertionStatesLsb,
                    assertionStatesMsb);
            }
            sensorInfo.getFunc(sensorNum, sensorInfo, props);
        }
        return ipmi::responseSuccess(
            sensorData->response.reading, uint5_t(0),
            sensorData->response.readingOrStateUnavailable,
            sensorData->response.scanningEnabled,
            sensorData->response.allEventMessagesEnabled,
            sensorData->response.thresholdLevelsStates,
            sensorData->response.discreteReadingSensorStates);

#else
        ipmi::sensor::GetSensorResponse getResponse =
            iter->second.getFunc(iter->second);

        return ipmi::responseSuccess(
            getResponse.reading, uint5_t(0),
            getResponse.readingOrStateUnavailable, getResponse.scanningEnabled,
            getResponse.allEventMessagesEnabled,
            getResponse.thresholdLevelsStates,
            getResponse.discreteReadingSensorStates);
#endif
    }
#ifdef UPDATE_FUNCTIONAL_ON_FAIL
    catch (const SensorFunctionalError& e)
    {
        return ipmi::responseResponseError();
    }
#endif
    catch (const std::exception& e)
    {
        // Intitilizing with default values
        constexpr uint8_t senReading = 0;
        constexpr uint5_t reserved{0};
        constexpr bool readState = true;
        constexpr bool senScanState = false;
        constexpr bool allEventMessageState = false;
        constexpr uint8_t assertionStatesLsb = 0;
        constexpr uint8_t assertionStatesMsb = 0;

        return ipmi::responseSuccess(senReading, reserved, readState,
                                     senScanState, allEventMessageState,
                                     assertionStatesLsb, assertionStatesMsb);
    }
}

void updateWarningThreshold(uint8_t lowerValue, uint8_t upperValue,
                            get_sdr::GetSensorThresholdsResponse& resp)
{
    resp.lowerNonCritical = lowerValue;
    resp.upperNonCritical = upperValue;
    if (lowerValue)
    {
        resp.validMask |= static_cast<uint8_t>(
            ipmi::sensor::ThresholdMask::NON_CRITICAL_LOW_MASK);
    }

    if (upperValue)
    {
        resp.validMask |= static_cast<uint8_t>(
            ipmi::sensor::ThresholdMask::NON_CRITICAL_HIGH_MASK);
    }
}

void updateCriticalThreshold(uint8_t lowerValue, uint8_t upperValue,
                             get_sdr::GetSensorThresholdsResponse& resp)
{
    resp.lowerCritical = lowerValue;
    resp.upperCritical = upperValue;
    if (lowerValue)
    {
        resp.validMask |= static_cast<uint8_t>(
            ipmi::sensor::ThresholdMask::CRITICAL_LOW_MASK);
    }

    if (upperValue)
    {
        resp.validMask |= static_cast<uint8_t>(
            ipmi::sensor::ThresholdMask::CRITICAL_HIGH_MASK);
    }
}

void updateNonRecoverableThreshold(uint8_t lowerValue, uint8_t upperValue,
                                   get_sdr::GetSensorThresholdsResponse& resp)
{
    resp.lowerNonRecoverable = lowerValue;
    resp.upperNonRecoverable = upperValue;
    if (lowerValue)
    {
        resp.validMask |= static_cast<uint8_t>(
            ipmi::sensor::ThresholdMask::NON_RECOVERABLE_LOW_MASK);
    }

    if (upperValue)
    {
        resp.validMask |= static_cast<uint8_t>(
            ipmi::sensor::ThresholdMask::NON_RECOVERABLE_HIGH_MASK);
    }
}

get_sdr::GetSensorThresholdsResponse getSensorThresholds(
    ipmi::Context::ptr& ctx, uint8_t sensorNum)
{
    get_sdr::GetSensorThresholdsResponse resp{};
    const auto iter = ipmi::sensor::sensors.find(sensorNum);
    const auto info = iter->second;

    std::string service;
    boost::system::error_code ec;
    ec = ipmi::getService(ctx, info.sensorInterface, info.sensorPath, service);
    if (ec)
    {
        return resp;
    }

    int32_t minClamp;
    int32_t maxClamp;
    int32_t rawData;
    constexpr uint8_t sensorUnitsSignedBits = 2 << 6;
    constexpr uint8_t signedDataFormat = 0x80;
    if ((info.sensorUnits1 & sensorUnitsSignedBits) == signedDataFormat)
    {
        minClamp = std::numeric_limits<int8_t>::lowest();
        maxClamp = std::numeric_limits<int8_t>::max();
    }
    else
    {
        minClamp = std::numeric_limits<uint8_t>::lowest();
        maxClamp = std::numeric_limits<uint8_t>::max();
    }

    static std::vector<std::string> thresholdNames{"Warning", "Critical",
                                                   "NonRecoverable"};

    for (const auto& thresholdName : thresholdNames)
    {
        std::string thresholdInterface =
            "xyz.openbmc_project.Sensor.Threshold." + thresholdName;
        std::string thresholdLow = thresholdName + "Low";
        std::string thresholdHigh = thresholdName + "High";

        ipmi::PropertyMap thresholds;
        ec = ipmi::getAllDbusProperties(ctx, service, info.sensorPath,
                                        thresholdInterface, thresholds);
        if (ec)
        {
            continue;
        }

        double lowValue = ipmi::mappedVariant<double>(
            thresholds, thresholdLow, std::numeric_limits<double>::quiet_NaN());
        double highValue = ipmi::mappedVariant<double>(
            thresholds, thresholdHigh,
            std::numeric_limits<double>::quiet_NaN());

        uint8_t lowerValue = 0;
        uint8_t upperValue = 0;
        if (std::isfinite(lowValue))
        {
            lowValue *= std::pow(10, info.scale - info.exponentR);
            rawData = round((lowValue - info.scaledOffset) / info.coefficientM);
            lowerValue =
                static_cast<uint8_t>(std::clamp(rawData, minClamp, maxClamp));
        }

        if (std::isfinite(highValue))
        {
            highValue *= std::pow(10, info.scale - info.exponentR);
            rawData =
                round((highValue - info.scaledOffset) / info.coefficientM);
            upperValue =
                static_cast<uint8_t>(std::clamp(rawData, minClamp, maxClamp));
        }

        if (thresholdName == "Warning")
        {
            updateWarningThreshold(lowerValue, upperValue, resp);
        }
        else if (thresholdName == "Critical")
        {
            updateCriticalThreshold(lowerValue, upperValue, resp);
        }
        else if (thresholdName == "NonRecoverable")
        {
            updateNonRecoverableThreshold(lowerValue, upperValue, resp);
        }
    }

    return resp;
}

/** @brief implements the get sensor thresholds command
 *  @param ctx - IPMI context pointer
 *  @param sensorNum - sensor number
 *
 *  @returns IPMI completion code plus response data
 *   - validMask - threshold mask
 *   - lower non-critical threshold - IPMI messaging state
 *   - lower critical threshold - link authentication state
 *   - lower non-recoverable threshold - callback state
 *   - upper non-critical threshold
 *   - upper critical
 *   - upper non-recoverable
 */
ipmi::RspType<uint8_t, // validMask
              uint8_t, // lowerNonCritical
              uint8_t, // lowerCritical
              uint8_t, // lowerNonRecoverable
              uint8_t, // upperNonCritical
              uint8_t, // upperCritical
              uint8_t  // upperNonRecoverable
              >
    ipmiSensorGetSensorThresholds(ipmi::Context::ptr& ctx, uint8_t sensorNum)
{
    const auto iter = ipmi::sensor::sensors.find(sensorNum);
    if (iter == ipmi::sensor::sensors.end())
    {
        return ipmi::responseSensorInvalid();
    }

    const auto info = iter->second;

    // Proceed only if the sensor value interface is implemented.
    if (info.propertyInterfaces.find(SensorValue::interface) ==
        info.propertyInterfaces.end())
    {
        // return with valid mask as 0
        return ipmi::responseSuccess();
    }

    auto it = sensorThresholdMap.find(sensorNum);
    if (it == sensorThresholdMap.end())
    {
        auto resp = getSensorThresholds(ctx, sensorNum);
        if (resp.validMask == 0)
        {
            return ipmi::responseSensorInvalid();
        }
        sensorThresholdMap[sensorNum] = std::move(resp);
    }

    const auto& resp = sensorThresholdMap[sensorNum];

    return ipmi::responseSuccess(
        resp.validMask, resp.lowerNonCritical, resp.lowerCritical,
        resp.lowerNonRecoverable, resp.upperNonCritical, resp.upperCritical,
        resp.upperNonRecoverable);
}

/** @brief implements the Set Sensor threshold command
 *  @param sensorNumber        - sensor number
 *  @param lowerNonCriticalThreshMask
 *  @param lowerCriticalThreshMask
 *  @param lowerNonRecovThreshMask
 *  @param upperNonCriticalThreshMask
 *  @param upperCriticalThreshMask
 *  @param upperNonRecovThreshMask
 *  @param reserved
 *  @param lowerNonCritical    - lower non-critical threshold
 *  @param lowerCritical       - Lower critical threshold
 *  @param lowerNonRecoverable - Lower non recovarable threshold
 *  @param upperNonCritical    - Upper non-critical threshold
 *  @param upperCritical       - Upper critical
 *  @param upperNonRecoverable - Upper Non-recoverable
 *
 *  @returns IPMI completion code
 */
ipmi::RspType<> ipmiSenSetSensorThresholds(
    ipmi::Context::ptr& ctx, uint8_t sensorNum, bool lowerNonCriticalThreshMask,
    bool lowerCriticalThreshMask, bool lowerNonRecovThreshMask,
    bool upperNonCriticalThreshMask, bool upperCriticalThreshMask,
    bool upperNonRecovThreshMask, uint2_t reserved, uint8_t lowerNonCritical,
    uint8_t lowerCritical, uint8_t, uint8_t upperNonCritical,
    uint8_t upperCritical, uint8_t)
{
    if (reserved)
    {
        return ipmi::responseInvalidFieldRequest();
    }

    // lower nc and upper nc not suppported on any sensor
    if (lowerNonRecovThreshMask || upperNonRecovThreshMask)
    {
        return ipmi::responseInvalidFieldRequest();
    }

    // if none of the threshold mask are set, nothing to do
    if (!(lowerNonCriticalThreshMask | lowerCriticalThreshMask |
          lowerNonRecovThreshMask | upperNonCriticalThreshMask |
          upperCriticalThreshMask | upperNonRecovThreshMask))
    {
        return ipmi::responseSuccess();
    }

    const auto iter = ipmi::sensor::sensors.find(sensorNum);
    if (iter == ipmi::sensor::sensors.end())
    {
        return ipmi::responseSensorInvalid();
    }

    const auto& info = iter->second;

    // Proceed only if the sensor value interface is implemented.
    if (info.propertyInterfaces.find(SensorValue::interface) ==
        info.propertyInterfaces.end())
    {
        // return with valid mask as 0
        return ipmi::responseSuccess();
    }

    constexpr auto warningThreshIntf =
        "xyz.openbmc_project.Sensor.Threshold.Warning";
    constexpr auto criticalThreshIntf =
        "xyz.openbmc_project.Sensor.Threshold.Critical";

    std::string service;
    boost::system::error_code ec;
    ec = ipmi::getService(ctx, info.sensorInterface, info.sensorPath, service);
    if (ec)
    {
        return ipmi::responseResponseError();
    }
    // store a vector of property name, value to set, and interface
    std::vector<std::tuple<std::string, uint8_t, std::string>> thresholdsToSet;

    // define the indexes of the tuple
    constexpr uint8_t propertyName = 0;
    constexpr uint8_t thresholdValue = 1;
    constexpr uint8_t interface = 2;
    // verifiy all needed fields are present
    if (lowerCriticalThreshMask || upperCriticalThreshMask)
    {
        ipmi::PropertyMap findThreshold;
        ec = ipmi::getAllDbusProperties(ctx, service, info.sensorPath,
                                        criticalThreshIntf, findThreshold);

        if (!ec)
        {
            if (lowerCriticalThreshMask)
            {
                auto findLower = findThreshold.find("CriticalLow");
                if (findLower == findThreshold.end())
                {
                    return ipmi::responseInvalidFieldRequest();
                }
                thresholdsToSet.emplace_back("CriticalLow", lowerCritical,
                                             criticalThreshIntf);
            }
            if (upperCriticalThreshMask)
            {
                auto findUpper = findThreshold.find("CriticalHigh");
                if (findUpper == findThreshold.end())
                {
                    return ipmi::responseInvalidFieldRequest();
                }
                thresholdsToSet.emplace_back("CriticalHigh", upperCritical,
                                             criticalThreshIntf);
            }
        }
    }
    if (lowerNonCriticalThreshMask || upperNonCriticalThreshMask)
    {
        ipmi::PropertyMap findThreshold;
        ec = ipmi::getAllDbusProperties(ctx, service, info.sensorPath,
                                        warningThreshIntf, findThreshold);

        if (!ec)
        {
            if (lowerNonCriticalThreshMask)
            {
                auto findLower = findThreshold.find("WarningLow");
                if (findLower == findThreshold.end())
                {
                    return ipmi::responseInvalidFieldRequest();
                }
                thresholdsToSet.emplace_back("WarningLow", lowerNonCritical,
                                             warningThreshIntf);
            }
            if (upperNonCriticalThreshMask)
            {
                auto findUpper = findThreshold.find("WarningHigh");
                if (findUpper == findThreshold.end())
                {
                    return ipmi::responseInvalidFieldRequest();
                }
                thresholdsToSet.emplace_back("WarningHigh", upperNonCritical,
                                             warningThreshIntf);
            }
        }
    }
    for (const auto& property : thresholdsToSet)
    {
        // from section 36.3 in the IPMI Spec, assume all linear
        double valueToSet =
            ((info.coefficientM * std::get<thresholdValue>(property)) +
             (info.scaledOffset * std::pow(10.0, info.scale))) *
            std::pow(10.0, info.exponentR);
        ipmi::setDbusProperty(
            ctx, service, info.sensorPath, std::get<interface>(property),
            std::get<propertyName>(property), ipmi::Value(valueToSet));
    }

    // Invalidate the cache
    sensorThresholdMap.erase(sensorNum);
    return ipmi::responseSuccess();
}

/** @brief implements the get SDR Info command
 *  @param count - Operation
 *
 *  @returns IPMI completion code plus response data
 *   - sdrCount - sensor/SDR count
 *   - lunsAndDynamicPopulation - static/Dynamic sensor population flag
 */
ipmi::RspType<uint8_t, // respcount
              uint8_t  // dynamic population flags
              >
    ipmiSensorGetDeviceSdrInfo(std::optional<uint8_t> count)
{
    uint8_t sdrCount;
    // multiple LUNs not supported.
    constexpr uint8_t lunsAndDynamicPopulation = 1;
    constexpr uint8_t getSdrCount = 0x01;
    constexpr uint8_t getSensorCount = 0x00;

    if (count.value_or(0) == getSdrCount)
    {
        // Get SDR count. This returns the total number of SDRs in the device.
        const auto& entityRecords =
            ipmi::sensor::EntityInfoMapContainer::getContainer()
                ->getIpmiEntityRecords();
        sdrCount = ipmi::sensor::sensors.size() + frus.size() +
                   entityRecords.size();
    }
    else if (count.value_or(0) == getSensorCount)
    {
        // Get Sensor count. This returns the number of sensors
        sdrCount = ipmi::sensor::sensors.size();
    }
    else
    {
        return ipmi::responseInvalidCommandOnLun();
    }

    return ipmi::responseSuccess(sdrCount, lunsAndDynamicPopulation);
}

/** @brief implements the reserve SDR command
 *  @returns IPMI completion code plus response data
 *   - reservationID - reservation ID
 */
ipmi::RspType<uint16_t> ipmiSensorReserveSdr()
{
    // A constant reservation ID is okay until we implement add/remove SDR.
    constexpr uint16_t reservationID = 1;

    return ipmi::responseSuccess(reservationID);
}

void setUnitFieldsForObject(const ipmi::sensor::Info& info,
                            get_sdr::SensorDataFullRecordBody& body)
{
    namespace server = sdbusplus::server::xyz::openbmc_project::sensor;
    body.sensorUnits1 = info.sensorUnits1; // default is 0. unsigned, no rate,
                                           // no modifier, not a %
    try
    {
        auto unit = server::Value::convertUnitFromString(info.unit);
        // Unit strings defined in
        // phosphor-dbus-interfaces/xyz/openbmc_project/Sensor/Value.interface.yaml
        switch (unit)
        {
            case server::Value::Unit::DegreesC:
                body.sensorUnits2Base = get_sdr::SENSOR_UNIT_DEGREES_C;
                break;
            case server::Value::Unit::RPMS:
                body.sensorUnits2Base = get_sdr::SENSOR_UNIT_RPM;
                break;
            case server::Value::Unit::Volts:
                body.sensorUnits2Base = get_sdr::SENSOR_UNIT_VOLTS;
                break;
            case server::Value::Unit::Meters:
                body.sensorUnits2Base = get_sdr::SENSOR_UNIT_METERS;
                break;
            case server::Value::Unit::Amperes:
                body.sensorUnits2Base = get_sdr::SENSOR_UNIT_AMPERES;
                break;
            case server::Value::Unit::Joules:
                body.sensorUnits2Base = get_sdr::SENSOR_UNIT_JOULES;
                break;
            case server::Value::Unit::Watts:
                body.sensorUnits2Base = get_sdr::SENSOR_UNIT_WATTS;
                break;
            case server::Value::Unit::Percent:
                get_sdr::body::setPercentage(body);
                break;
            default:
                // Cannot be hit.
                std::fprintf(stderr, "Unknown value unit type: = %s\n",
                             info.unit.c_str());
        }
    }
    catch (const sdbusplus::exception::InvalidEnumString& e)
    {
        lg2::warning("Warning: no unit provided for sensor!");
    }
}

ipmi::Cc populateRecordFromDbus(const ipmi::sensor::Info& info,
                                get_sdr::SensorDataFullRecordBody& body)
{
    /* Functional sensor case */
    if (isAnalogSensor(info.propertyInterfaces.begin()->first))
    {
        /* Unit info */
        setUnitFieldsForObject(info, body);

        get_sdr::body::setB(info.coefficientB, body);
        get_sdr::body::setM(info.coefficientM, body);
        get_sdr::body::setBexp(info.exponentB, body);
        get_sdr::body::setRexp(info.exponentR, body);
    }

    /* ID string */
    auto idString = info.sensorName;

    if (idString.empty())
    {
        idString = info.sensorNameFunc(info);
    }

    if (idString.length() > FULL_RECORD_ID_STR_MAX_LENGTH)
    {
        get_sdr::body::setIdStrLen(FULL_RECORD_ID_STR_MAX_LENGTH, body);
    }
    else
    {
        get_sdr::body::setIdStrLen(idString.length(), body);
    }
    get_sdr::body::setIdType(3, body); // "8-bit ASCII + Latin 1"
    strncpy(body.idString, idString.c_str(), get_sdr::body::getIdStrLen(body));

    return ipmi::ccSuccess;
};

ipmi::RspType<uint16_t,            // nextRecordId
              std::vector<uint8_t> // recordData
              >
    ipmiFruGetSdr(uint16_t recordID, uint8_t offset, uint8_t bytesToRead)
{
    auto fru = frus.begin();
    uint8_t fruID{};

    fruID = recordID - FRU_RECORD_ID_START;
    fru = frus.find(fruID);
    if (fru == frus.end())
    {
        return ipmi::responseSensorInvalid();
    }

    get_sdr::SensorDataFruRecord record{};
    /* Header */
    record.header.recordId = recordID;
    record.header.sdrVersion = SDR_VERSION; // Based on IPMI Spec v2.0 rev 1.1
    record.header.recordType = get_sdr::SENSOR_DATA_FRU_RECORD;
    record.header.recordLength = sizeof(record.key) + sizeof(record.body);

    /* Key */
    record.key.fruID = fruID;
    record.key.accessLun |= IPMI_LOGICAL_FRU;
    record.key.deviceAddress = BMCTargetAddress;

    /* Body */
    record.body.entityID = fru->second[0].entityID;
    record.body.entityInstance = fru->second[0].entityInstance;
    record.body.deviceType = fruInventoryDevice;
    record.body.deviceTypeModifier = IPMIFruInventory;

    /* Device ID string */
    auto deviceID =
        fru->second[0].path.substr(fru->second[0].path.find_last_of('/') + 1,
                                   fru->second[0].path.length());

    if (deviceID.length() > get_sdr::FRU_RECORD_DEVICE_ID_MAX_LENGTH)
    {
        get_sdr::body::setDeviceIdStrLen(
            get_sdr::FRU_RECORD_DEVICE_ID_MAX_LENGTH, record.body);
    }
    else
    {
        get_sdr::body::setDeviceIdStrLen(deviceID.length(), record.body);
    }

    uint16_t nextRecordId{};
    strncpy(record.body.deviceID, deviceID.c_str(),
            get_sdr::body::getDeviceIdStrLen(record.body));

    if (++fru == frus.end())
    {
        // we have reached till end of fru, so assign the next record id to
        // 512(Max fru ID = 511) + Entity Record ID(may start with 0).
        const auto& entityRecords =
            ipmi::sensor::EntityInfoMapContainer::getContainer()
                ->getIpmiEntityRecords();
        nextRecordId =
            (entityRecords.size())
                ? entityRecords.begin()->first + ENTITY_RECORD_ID_START
                : END_OF_RECORD;
    }
    else
    {
        nextRecordId = FRU_RECORD_ID_START + fru->first;
    }

    // Check for invalid offset size
    if (offset > sizeof(record))
    {
        return ipmi::responseParmOutOfRange();
    }

    size_t dataLen =
        std::min(static_cast<size_t>(bytesToRead), sizeof(record) - offset);

    std::vector<uint8_t> recordData(dataLen);
    std::memcpy(recordData.data(),
                reinterpret_cast<const uint8_t*>(&record) + offset, dataLen);

    return ipmi::responseSuccess(nextRecordId, recordData);
}

ipmi::RspType<uint16_t,            // nextRecordId
              std::vector<uint8_t> // recordData
              >
    ipmiEntityGetSdr(uint16_t recordID, uint8_t offset, uint8_t bytesToRead)
{
    const auto& entityRecords =
        ipmi::sensor::EntityInfoMapContainer::getContainer()
            ->getIpmiEntityRecords();
    auto entity = entityRecords.begin();
    uint8_t entityRecordID;

    entityRecordID = recordID - ENTITY_RECORD_ID_START;
    entity = entityRecords.find(entityRecordID);
    if (entity == entityRecords.end())
    {
        return ipmi::responseSensorInvalid();
    }

    get_sdr::SensorDataEntityRecord record{};
    /* Header */
    record.header.recordId = recordID;
    record.header.sdrVersion = SDR_VERSION; // Based on IPMI Spec v2.0 rev 1.1
    record.header.recordType = get_sdr::SENSOR_DATA_ENTITY_RECORD;
    record.header.recordLength = sizeof(record.key) + sizeof(record.body);

    /* Key */
    record.key.containerEntityId = entity->second.containerEntityId;
    record.key.containerEntityInstance = entity->second.containerEntityInstance;
    get_sdr::key::setFlags(entity->second.isList, entity->second.isLinked,
                           record.key);
    record.key.entityId1 = entity->second.containedEntities[0].first;
    record.key.entityInstance1 = entity->second.containedEntities[0].second;

    /* Body */
    record.body.entityId2 = entity->second.containedEntities[1].first;
    record.body.entityInstance2 = entity->second.containedEntities[1].second;
    record.body.entityId3 = entity->second.containedEntities[2].first;
    record.body.entityInstance3 = entity->second.containedEntities[2].second;
    record.body.entityId4 = entity->second.containedEntities[3].first;
    record.body.entityInstance4 = entity->second.containedEntities[3].second;

    uint16_t nextRecordId{};
    if (++entity == entityRecords.end())
    {
        nextRecordId = END_OF_RECORD;
    }
    else
    {
        nextRecordId = entity->first + ENTITY_RECORD_ID_START;
    }

    // Check for invalid offset size
    if (offset > sizeof(record))
    {
        return ipmi::responseParmOutOfRange();
    }

    size_t dataLen =
        std::min(static_cast<size_t>(bytesToRead), sizeof(record) - offset);

    std::vector<uint8_t> recordData(dataLen);
    std::memcpy(recordData.data(),
                reinterpret_cast<const uint8_t*>(&record) + offset, dataLen);

    return ipmi::responseSuccess(nextRecordId, recordData);
}

ipmi::RspType<uint16_t,            // nextRecordId
              std::vector<uint8_t> // recordData
              >
    ipmiSensorGetSdr(uint16_t /* reservationId */, uint16_t recordID,
                     uint8_t offset, uint8_t bytesToRead)
{
    // Note: we use an iterator so we can provide the next ID at the end of
    // the call.
    auto sensor = ipmi::sensor::sensors.begin();

    // At the beginning of a scan, the host side will send us id=0.
    if (recordID != 0)
    {
        // recordID 0 to 255 means it is a FULL record.
        // recordID 256 to 511 means it is a FRU record.
        // recordID greater then 511 means it is a Entity Association
        // record. Currently we are supporting three record types: FULL
        // record, FRU record and Enttiy Association record.
        if (recordID >= ENTITY_RECORD_ID_START)
        {
            return ipmiEntityGetSdr(recordID, offset, bytesToRead);
        }
        else if (recordID >= FRU_RECORD_ID_START &&
                 recordID < ENTITY_RECORD_ID_START)
        {
            return ipmiFruGetSdr(recordID, offset, bytesToRead);
        }
        else
        {
            sensor = ipmi::sensor::sensors.find(recordID);
            if (sensor == ipmi::sensor::sensors.end())
            {
                return ipmi::responseSensorInvalid();
            }
        }
    }

    uint8_t sensorId = sensor->first;

    auto it = sdrCacheMap.find(sensorId);
    if (it == sdrCacheMap.end())
    {
        /* Header */
        get_sdr::SensorDataFullRecord record = {};
        record.header.recordId = sensorId;
        record.header.sdrVersion = 0x51; // Based on IPMI Spec v2.0 rev 1.1
        record.header.recordType = get_sdr::SENSOR_DATA_FULL_RECORD;
        record.header.recordLength = sizeof(record.key) + sizeof(record.body);

        /* Key */
        get_sdr::key::setOwnerIdBmc(record.key);
        record.key.sensorNumber = sensorId;

        /* Body */
        record.body.entityId = sensor->second.entityType;
        record.body.sensorType = sensor->second.sensorType;
        record.body.eventReadingType = sensor->second.sensorReadingType;
        record.body.entityInstance = sensor->second.instance;
        if (ipmi::sensor::Mutability::Write ==
            (sensor->second.mutability & ipmi::sensor::Mutability::Write))
        {
            get_sdr::body::initSettableState(true, record.body);
        }

        // Set the type-specific details given the DBus interface
        populateRecordFromDbus(sensor->second, record.body);
        sdrCacheMap[sensorId] = std::move(record);
    }

    uint16_t nextRecordId{};
    const auto& record = sdrCacheMap[sensorId];

    if (++sensor == ipmi::sensor::sensors.end())
    {
        // we have reached till end of sensor, so assign the next record id
        // to 256(Max Sensor ID = 255) + FRU ID(may start with 0).
        nextRecordId = (frus.size()) ? frus.begin()->first + FRU_RECORD_ID_START
                                     : END_OF_RECORD;
    }
    else
    {
        nextRecordId = sensor->first;
    }

    if (offset > sizeof(record))
    {
        return ipmi::responseParmOutOfRange();
    }

    size_t dataLen =
        std::min(static_cast<size_t>(bytesToRead), sizeof(record) - offset);

    std::vector<uint8_t> recordData(dataLen);
    std::memcpy(recordData.data(),
                reinterpret_cast<const uint8_t*>(&record) + offset, dataLen);

    return ipmi::responseSuccess(nextRecordId, recordData);
}

static bool isFromSystemChannel()
{
    // TODO we could not figure out where the request is from based on IPMI
    // command handler parameters. because of it, we can not differentiate
    // request from SMS/SMM or IPMB channel
    return true;
}

ipmi::RspType<> ipmicmdPlatformEvent(ipmi::Context::ptr& ctx,
                                     const std::vector<uint8_t>& data)
{
    size_t paraLen = data.size();
    if (paraLen < selSystemEventSizeWith1Bytes ||
        paraLen > selSystemEventSizeWith3Bytes)
    {
        return ipmi::responseReqDataLenInvalid();
    }

    uint16_t generatorID = 0xff;
    std::string sensorPath = "IPMB";
    const uint8_t* raw = data.data();
    const PlatformEventRequest* req = nullptr;
    if (isFromSystemChannel())
    {
        // first byte for SYSTEM Interface is Generator ID +1 to get common
        // struct
        req = reinterpret_cast<const PlatformEventRequest*>(raw + 1);
        // Capture the generator ID
        generatorID = *raw;
        // Platform Event usually comes from other firmware, like BIOS.
        // Unlike BMC sensor, it does not have BMC DBUS sensor path.
        sensorPath = "System";
    }
    else
    {
        req = reinterpret_cast<const PlatformEventRequest*>(raw);
        // TODO GenratorID for IPMB is combination of RqSA and RqLUN
    }

    // Content of event data field depends on sensor class.
    // When data0 bit[5:4] is non-zero, valid data counts is 3.
    // When data0 bit[7:6] is non-zero, valid data counts is 2.
    if (((req->data[0] & byte3EnableMask) != 0 &&
         paraLen < selSystemEventSizeWith3Bytes) ||
        ((req->data[0] & byte2EnableMask) != 0 &&
         paraLen < selSystemEventSizeWith2Bytes))
    {
        return ipmi::responseReqDataLenInvalid();
    }

    // Count bytes of Event Data
    size_t count;
    if ((req->data[0] & byte3EnableMask) != 0)
    {
        count = 3;
    }
    else if ((req->data[0] & byte2EnableMask) != 0)
    {
        count = 2;
    }
    else
    {
        count = 1;
    }
    bool assert = req->eventDirectionType & directionMask ? false : true;
    std::vector<uint8_t> eventData(req->data, req->data + count);

    auto ec = ipmi::callDbusMethod(
        ctx, ipmiSELObject, ipmiSELPath, ipmiSELAddInterface, "IpmiSelAdd",
        ipmiSELAddMessage, sensorPath, eventData, assert, generatorID);
    if (ec)
    {
        lg2::error("IpmiSelAdd call failed: {ERROR}", "ERROR", ec.message());
        return ipmi::responseUnspecifiedError();
    }

    return ipmi::responseSuccess();
}

void registerNetFnSenFunctions()
{
    // Handlers with dbus-sdr handler implementation.
    // Do not register the hander if it dynamic sensors stack is used.

#ifndef FEATURE_DYNAMIC_SENSORS

#ifdef FEATURE_SENSORS_CACHE
    // Initialize the sensor matches
    initSensorMatches();
#endif

    // <Set Sensor Reading and Event Status>
    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
                          ipmi::sensor_event::cmdSetSensorReadingAndEvtSts,
                          ipmi::Privilege::Operator, ipmiSetSensorReading);
    // <Get Sensor Reading>
    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
                          ipmi::sensor_event::cmdGetSensorReading,
                          ipmi::Privilege::User, ipmiSensorGetSensorReading);

    // <Reserve Device SDR Repository>
    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
                          ipmi::sensor_event::cmdReserveDeviceSdrRepository,
                          ipmi::Privilege::User, ipmiSensorReserveSdr);

    // <Get Device SDR Info>
    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
                          ipmi::sensor_event::cmdGetDeviceSdrInfo,
                          ipmi::Privilege::User, ipmiSensorGetDeviceSdrInfo);

    // <Get Sensor Thresholds>
    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
                          ipmi::sensor_event::cmdGetSensorThreshold,
                          ipmi::Privilege::User, ipmiSensorGetSensorThresholds);

    // <Set Sensor Thresholds>
    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
                          ipmi::sensor_event::cmdSetSensorThreshold,
                          ipmi::Privilege::User, ipmiSenSetSensorThresholds);

    // <Get Device SDR>
    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
                          ipmi::sensor_event::cmdGetDeviceSdr,
                          ipmi::Privilege::User, ipmiSensorGetSdr);

#endif

    // Common Handers used by both implementation.

    // <Platform Event Message>
    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
                          ipmi::sensor_event::cmdPlatformEvent,
                          ipmi::Privilege::Operator, ipmicmdPlatformEvent);

    // <Get Sensor Type>
    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
                          ipmi::sensor_event::cmdGetSensorType,
                          ipmi::Privilege::User, ipmiGetSensorType);

    return;
}
