#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 register_netfn_sen_functions() __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 = NULL;

    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, NULL);
    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 = NULL;

    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, NULL);
    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);
    }
}

get_sdr::GetSensorThresholdsResponse
    getSensorThresholds(ipmi::Context::ptr& ctx, uint8_t sensorNum)
{
    get_sdr::GetSensorThresholdsResponse resp{};
    constexpr auto warningThreshIntf =
        "xyz.openbmc_project.Sensor.Threshold.Warning";
    constexpr auto criticalThreshIntf =
        "xyz.openbmc_project.Sensor.Threshold.Critical";

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

    ipmi::PropertyMap warnThresholds;
    ec = ipmi::getAllDbusProperties(ctx, service, info.sensorPath,
                                    warningThreshIntf, warnThresholds);
    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();
    }
    if (!ec)
    {
        double warnLow = ipmi::mappedVariant<double>(
            warnThresholds, "WarningLow",
            std::numeric_limits<double>::quiet_NaN());
        double warnHigh = ipmi::mappedVariant<double>(
            warnThresholds, "WarningHigh",
            std::numeric_limits<double>::quiet_NaN());

        if (std::isfinite(warnLow))
        {
            warnLow *= std::pow(10, info.scale - info.exponentR);
            rawData = round((warnLow - info.scaledOffset) / info.coefficientM);
            resp.lowerNonCritical =
                static_cast<uint8_t>(std::clamp(rawData, minClamp, maxClamp));
            resp.validMask |= static_cast<uint8_t>(
                ipmi::sensor::ThresholdMask::NON_CRITICAL_LOW_MASK);
        }

        if (std::isfinite(warnHigh))
        {
            warnHigh *= std::pow(10, info.scale - info.exponentR);
            rawData = round((warnHigh - info.scaledOffset) / info.coefficientM);
            resp.upperNonCritical =
                static_cast<uint8_t>(std::clamp(rawData, minClamp, maxClamp));
            resp.validMask |= static_cast<uint8_t>(
                ipmi::sensor::ThresholdMask::NON_CRITICAL_HIGH_MASK);
        }
    }

    ipmi::PropertyMap critThresholds;
    ec = ipmi::getAllDbusProperties(ctx, service, info.sensorPath,
                                    criticalThreshIntf, critThresholds);
    if (!ec)
    {
        double critLow = ipmi::mappedVariant<double>(
            critThresholds, "CriticalLow",
            std::numeric_limits<double>::quiet_NaN());
        double critHigh = ipmi::mappedVariant<double>(
            critThresholds, "CriticalHigh",
            std::numeric_limits<double>::quiet_NaN());

        if (std::isfinite(critLow))
        {
            critLow *= std::pow(10, info.scale - info.exponentR);
            rawData = round((critLow - info.scaledOffset) / info.coefficientM);
            resp.lowerCritical =
                static_cast<uint8_t>(std::clamp(rawData, minClamp, maxClamp));
            resp.validMask |= static_cast<uint8_t>(
                ipmi::sensor::ThresholdMask::CRITICAL_LOW_MASK);
        }

        if (std::isfinite(critHigh))
        {
            critHigh *= std::pow(10, info.scale - info.exponentR);
            rawData = round((critHigh - info.scaledOffset) / info.coefficientM);
            resp.upperCritical =
                static_cast<uint8_t>(std::clamp(rawData, minClamp, maxClamp));
            resp.validMask |= static_cast<uint8_t>(
                ipmi::sensor::ThresholdMask::CRITICAL_HIGH_MASK);
        }
    }

    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())
    {
        sensorThresholdMap[sensorNum] = getSensorThresholds(ctx, sensorNum);
    }

    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;
    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->sensor_units_2_base = get_sdr::SENSOR_UNIT_DEGREES_C;
                break;
            case server::Value::Unit::RPMS:
                body->sensor_units_2_base = get_sdr::SENSOR_UNIT_RPM;
                break;
            case server::Value::Unit::Volts:
                body->sensor_units_2_base = get_sdr::SENSOR_UNIT_VOLTS;
                break;
            case server::Value::Unit::Meters:
                body->sensor_units_2_base = get_sdr::SENSOR_UNIT_METERS;
                break;
            case server::Value::Unit::Amperes:
                body->sensor_units_2_base = get_sdr::SENSOR_UNIT_AMPERES;
                break;
            case server::Value::Unit::Joules:
                body->sensor_units_2_base = get_sdr::SENSOR_UNIT_JOULES;
                break;
            case server::Value::Unit::Watts:
                body->sensor_units_2_base = get_sdr::SENSOR_UNIT_WATTS;
                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_ret_t populate_record_from_dbus(get_sdr::SensorDataFullRecordBody* body,
                                     const ipmi::sensor::Info* info,
                                     ipmi_data_len_t)
{
    /* Functional sensor case */
    if (isAnalogSensor(info->propertyInterfaces.begin()->first))
    {
        body->sensor_units_1 = info->sensorUnits1; // default is 0. unsigned, no
                                                   // rate, no modifier, not a %
        /* Unit info */
        setUnitFieldsForObject(info, body);

        get_sdr::body::set_b(info->coefficientB, body);
        get_sdr::body::set_m(info->coefficientM, body);
        get_sdr::body::set_b_exp(info->exponentB, body);
        get_sdr::body::set_r_exp(info->exponentR, body);
    }

    /* ID string */
    auto id_string = info->sensorName;

    if (id_string.empty())
    {
        id_string = info->sensorNameFunc(*info);
    }

    if (id_string.length() > FULL_RECORD_ID_STR_MAX_LENGTH)
    {
        get_sdr::body::set_id_strlen(FULL_RECORD_ID_STR_MAX_LENGTH, body);
    }
    else
    {
        get_sdr::body::set_id_strlen(id_string.length(), body);
    }
    get_sdr::body::set_id_type(3, body); // "8-bit ASCII + Latin 1"
    strncpy(body->id_string, id_string.c_str(),
            get_sdr::body::get_id_strlen(body));

    return IPMI_CC_OK;
};

ipmi_ret_t ipmi_fru_get_sdr(ipmi_request_t request, ipmi_response_t response,
                            ipmi_data_len_t data_len)
{
    auto req = reinterpret_cast<get_sdr::GetSdrReq*>(request);
    auto resp = reinterpret_cast<get_sdr::GetSdrResp*>(response);
    get_sdr::SensorDataFruRecord record{};
    auto dataLength = 0;

    auto fru = frus.begin();
    uint8_t fruID{};
    auto recordID = get_sdr::request::get_record_id(req);

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

    /* Header */
    get_sdr::header::set_record_id(recordID, &(record.header));
    record.header.sdr_version = SDR_VERSION; // Based on IPMI Spec v2.0 rev 1.1
    record.header.record_type = get_sdr::SENSOR_DATA_FRU_RECORD;
    record.header.record_length = 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::set_device_id_strlen(
            get_sdr::FRU_RECORD_DEVICE_ID_MAX_LENGTH, &(record.body));
    }
    else
    {
        get_sdr::body::set_device_id_strlen(deviceID.length(), &(record.body));
    }

    strncpy(record.body.deviceID, deviceID.c_str(),
            get_sdr::body::get_device_id_strlen(&(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();
        auto next_record_id =
            (entityRecords.size())
                ? entityRecords.begin()->first + ENTITY_RECORD_ID_START
                : END_OF_RECORD;
        get_sdr::response::set_next_record_id(next_record_id, resp);
    }
    else
    {
        get_sdr::response::set_next_record_id(
            (FRU_RECORD_ID_START + fru->first), resp);
    }

    // Check for invalid offset size
    if (req->offset > sizeof(record))
    {
        return IPMI_CC_PARM_OUT_OF_RANGE;
    }

    dataLength = std::min(static_cast<size_t>(req->bytes_to_read),
                          sizeof(record) - req->offset);

    std::memcpy(resp->record_data,
                reinterpret_cast<uint8_t*>(&record) + req->offset, dataLength);

    *data_len = dataLength;
    *data_len += 2; // additional 2 bytes for next record ID

    return IPMI_CC_OK;
}

ipmi_ret_t ipmi_entity_get_sdr(ipmi_request_t request, ipmi_response_t response,
                               ipmi_data_len_t data_len)
{
    auto req = reinterpret_cast<get_sdr::GetSdrReq*>(request);
    auto resp = reinterpret_cast<get_sdr::GetSdrResp*>(response);
    get_sdr::SensorDataEntityRecord record{};
    auto dataLength = 0;

    const auto& entityRecords =
        ipmi::sensor::EntityInfoMapContainer::getContainer()
            ->getIpmiEntityRecords();
    auto entity = entityRecords.begin();
    uint8_t entityRecordID;
    auto recordID = get_sdr::request::get_record_id(req);

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

    /* Header */
    get_sdr::header::set_record_id(recordID, &(record.header));
    record.header.sdr_version = SDR_VERSION; // Based on IPMI Spec v2.0 rev 1.1
    record.header.record_type = get_sdr::SENSOR_DATA_ENTITY_RECORD;
    record.header.record_length = sizeof(record.key) + sizeof(record.body);

    /* Key */
    record.key.containerEntityId = entity->second.containerEntityId;
    record.key.containerEntityInstance = entity->second.containerEntityInstance;
    get_sdr::key::set_flags(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;

    if (++entity == entityRecords.end())
    {
        get_sdr::response::set_next_record_id(END_OF_RECORD,
                                              resp); // last record
    }
    else
    {
        get_sdr::response::set_next_record_id(
            (ENTITY_RECORD_ID_START + entity->first), resp);
    }

    // Check for invalid offset size
    if (req->offset > sizeof(record))
    {
        return IPMI_CC_PARM_OUT_OF_RANGE;
    }

    dataLength = std::min(static_cast<size_t>(req->bytes_to_read),
                          sizeof(record) - req->offset);

    std::memcpy(resp->record_data,
                reinterpret_cast<uint8_t*>(&record) + req->offset, dataLength);

    *data_len = dataLength;
    *data_len += 2; // additional 2 bytes for next record ID

    return IPMI_CC_OK;
}

ipmi_ret_t ipmi_sen_get_sdr(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
                            ipmi_response_t response, ipmi_data_len_t data_len,
                            ipmi_context_t)
{
    ipmi_ret_t ret = IPMI_CC_OK;
    get_sdr::GetSdrReq* req = (get_sdr::GetSdrReq*)request;
    get_sdr::GetSdrResp* resp = (get_sdr::GetSdrResp*)response;

    // Note: we use an iterator so we can provide the next ID at the end of
    // the call.
    auto sensor = ipmi::sensor::sensors.begin();
    auto recordID = get_sdr::request::get_record_id(req);

    // 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 ipmi_entity_get_sdr(request, response, data_len);
        }
        else if (recordID >= FRU_RECORD_ID_START &&
                 recordID < ENTITY_RECORD_ID_START)
        {
            return ipmi_fru_get_sdr(request, response, data_len);
        }
        else
        {
            sensor = ipmi::sensor::sensors.find(recordID);
            if (sensor == ipmi::sensor::sensors.end())
            {
                return IPMI_CC_SENSOR_INVALID;
            }
        }
    }

    uint8_t sensor_id = sensor->first;

    auto it = sdrCacheMap.find(sensor_id);
    if (it == sdrCacheMap.end())
    {
        /* Header */
        get_sdr::SensorDataFullRecord record = {};
        get_sdr::header::set_record_id(sensor_id, &(record.header));
        record.header.sdr_version = 0x51; // Based on IPMI Spec v2.0 rev 1.1
        record.header.record_type = get_sdr::SENSOR_DATA_FULL_RECORD;
        record.header.record_length = sizeof(record.key) + sizeof(record.body);

        /* Key */
        get_sdr::key::set_owner_id_bmc(&(record.key));
        record.key.sensor_number = sensor_id;

        /* Body */
        record.body.entity_id = sensor->second.entityType;
        record.body.sensor_type = sensor->second.sensorType;
        record.body.event_reading_type = sensor->second.sensorReadingType;
        record.body.entity_instance = sensor->second.instance;
        if (ipmi::sensor::Mutability::Write ==
            (sensor->second.mutability & ipmi::sensor::Mutability::Write))
        {
            get_sdr::body::init_settable_state(true, &(record.body));
        }

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

    const auto& record = sdrCacheMap[sensor_id];

    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).
        auto next_record_id = (frus.size())
                                  ? frus.begin()->first + FRU_RECORD_ID_START
                                  : END_OF_RECORD;

        get_sdr::response::set_next_record_id(next_record_id, resp);
    }
    else
    {
        get_sdr::response::set_next_record_id(sensor->first, resp);
    }

    if (req->offset > sizeof(record))
    {
        return IPMI_CC_PARM_OUT_OF_RANGE;
    }

    // data_len will ultimately be the size of the record, plus
    // the size of the next record ID:
    *data_len = std::min(static_cast<size_t>(req->bytes_to_read),
                         sizeof(record) - req->offset);

    std::memcpy(resp->record_data,
                reinterpret_cast<const uint8_t*>(&record) + req->offset,
                *data_len);

    // data_len should include the LSB and MSB:
    *data_len += sizeof(resp->next_record_id_lsb) +
                 sizeof(resp->next_record_id_msb);

    return ret;
}

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_ret_t 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_CC_REQ_DATA_LEN_INVALID;
    }

    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_CC_REQ_DATA_LEN_INVALID;
    }

    // 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_CC_UNSPECIFIED_ERROR;
    }
    return IPMI_CC_OK;
}

void register_netfn_sen_functions()
{
    // 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_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_DEVICE_SDR, nullptr,
                           ipmi_sen_get_sdr, PRIVILEGE_USER);

#endif

    // Common Handers used by both implementation.

    // <Platform Event Message>
    ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_PLATFORM_EVENT, nullptr,
                           ipmicmdPlatformEvent, PRIVILEGE_OPERATOR);

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

    return;
}
