#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;

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
                        std::string interfaceName;
                        msg.read(interfaceName);
                        ipmi::PropertyMap props;
                        msg.read(props);
                        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 = {
    "xyz.openbmc_project.Sensor.Value",
    "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)
{
    constexpr auto valueInterface = "xyz.openbmc_project.Sensor.Value";

    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(valueInterface) ==
        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();
    }

    constexpr auto valueInterface = "xyz.openbmc_project.Sensor.Value";

    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(valueInterface) ==
        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::Cc ipmicmdPlatformEvent(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
                              ipmi_response_t, ipmi_data_len_t dataLen,
                              ipmi_context_t)
{
    uint16_t generatorID;
    size_t count;
    bool assert = true;
    std::string sensorPath;
    size_t paraLen = *dataLen;
    PlatformEventRequest* req;
    *dataLen = 0;

    if ((paraLen < selSystemEventSizeWith1Bytes) ||
        (paraLen > selSystemEventSizeWith3Bytes))
    {
        return ipmi::ccReqDataLenInvalid;
    }

    if (isFromSystemChannel())
    { // first byte for SYSTEM Interface is Generator ID
        // +1 to get common struct
        req = reinterpret_cast<PlatformEventRequest*>((uint8_t*)request + 1);
        // Capture the generator ID
        generatorID = *reinterpret_cast<uint8_t*>(request);
        // 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<PlatformEventRequest*>(request);
        // TODO GenratorID for IPMB is combination of RqSA and RqLUN
        generatorID = 0xff;
        sensorPath = "IPMB";
    }
    // 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::ccReqDataLenInvalid;
    }

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

    sdbusplus::bus_t dbus(bus);
    std::string service =
        ipmi::getService(dbus, ipmiSELAddInterface, ipmiSELPath);
    sdbusplus::message_t writeSEL = dbus.new_method_call(
        service.c_str(), ipmiSELPath, ipmiSELAddInterface, "IpmiSelAdd");
    writeSEL.append(ipmiSELAddMessage, sensorPath, eventData, assert,
                    generatorID);
    try
    {
        dbus.call(writeSEL);
    }
    catch (const sdbusplus::exception_t& e)
    {
        lg2::error("exception message: {ERROR}", "ERROR", e);
        return ipmi::ccUnspecifiedError;
    }
    return ipmi::ccSuccess;
}

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_register_callback(ipmi::netFnSensor,
                           ipmi::sensor_event::cmdPlatformEvent, nullptr,
                           ipmicmdPlatformEvent, PRIVILEGE_OPERATOR);

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

    return;
}
