diff --git a/dbus-sdr/sdrutils.cpp b/dbus-sdr/sdrutils.cpp
new file mode 100644
index 0000000..a6468bb
--- /dev/null
+++ b/dbus-sdr/sdrutils.cpp
@@ -0,0 +1,436 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include "dbus-sdr/sdrutils.hpp"
+
+namespace details
+{
+bool getSensorSubtree(std::shared_ptr<SensorSubTree>& subtree)
+{
+    static std::shared_ptr<SensorSubTree> sensorTreePtr;
+    std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
+    static sdbusplus::bus::match::match sensorAdded(
+        *dbus,
+        "type='signal',member='InterfacesAdded',arg0path='/xyz/openbmc_project/"
+        "sensors/'",
+        [](sdbusplus::message::message& m) { sensorTreePtr.reset(); });
+
+    static sdbusplus::bus::match::match sensorRemoved(
+        *dbus,
+        "type='signal',member='InterfacesRemoved',arg0path='/xyz/"
+        "openbmc_project/sensors/'",
+        [](sdbusplus::message::message& m) { sensorTreePtr.reset(); });
+
+    bool sensorTreeUpdated = false;
+    if (sensorTreePtr)
+    {
+        subtree = sensorTreePtr;
+        return sensorTreeUpdated;
+    }
+
+    sensorTreePtr = std::make_shared<SensorSubTree>();
+
+    auto mapperCall =
+        dbus->new_method_call("xyz.openbmc_project.ObjectMapper",
+                              "/xyz/openbmc_project/object_mapper",
+                              "xyz.openbmc_project.ObjectMapper", "GetSubTree");
+    static constexpr const int32_t depth = 2;
+    static constexpr std::array<const char*, 3> interfaces = {
+        "xyz.openbmc_project.Sensor.Value",
+        "xyz.openbmc_project.Sensor.Threshold.Warning",
+        "xyz.openbmc_project.Sensor.Threshold.Critical"};
+    mapperCall.append("/xyz/openbmc_project/sensors", depth, interfaces);
+
+    try
+    {
+        auto mapperReply = dbus->call(mapperCall);
+        mapperReply.read(*sensorTreePtr);
+    }
+    catch (sdbusplus::exception_t& e)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
+        return sensorTreeUpdated;
+    }
+    subtree = sensorTreePtr;
+    sensorTreeUpdated = true;
+    return sensorTreeUpdated;
+}
+
+bool getSensorNumMap(std::shared_ptr<SensorNumMap>& sensorNumMap)
+{
+    static std::shared_ptr<SensorNumMap> sensorNumMapPtr;
+    bool sensorNumMapUpated = false;
+
+    std::shared_ptr<SensorSubTree> sensorTree;
+    bool sensorTreeUpdated = details::getSensorSubtree(sensorTree);
+    if (!sensorTree)
+    {
+        return sensorNumMapUpated;
+    }
+
+    if (!sensorTreeUpdated && sensorNumMapPtr)
+    {
+        sensorNumMap = sensorNumMapPtr;
+        return sensorNumMapUpated;
+    }
+
+    sensorNumMapPtr = std::make_shared<SensorNumMap>();
+
+    uint16_t sensorNum = 0;
+    uint16_t sensorIndex = 0;
+    for (const auto& sensor : *sensorTree)
+    {
+        sensorNumMapPtr->insert(
+            SensorNumMap::value_type(sensorNum, sensor.first));
+        sensorIndex++;
+        if (sensorIndex == maxSensorsPerLUN)
+        {
+            sensorIndex = lun1Sensor0;
+        }
+        else if (sensorIndex == (lun1Sensor0 | maxSensorsPerLUN))
+        {
+            // Skip assigning LUN 0x2 any sensors
+            sensorIndex = lun3Sensor0;
+        }
+        else if (sensorIndex == (lun3Sensor0 | maxSensorsPerLUN))
+        {
+            // this is an error, too many IPMI sensors
+            throw std::out_of_range("Maximum number of IPMI sensors exceeded.");
+        }
+        sensorNum = sensorIndex;
+    }
+    sensorNumMap = sensorNumMapPtr;
+    sensorNumMapUpated = true;
+    return sensorNumMapUpated;
+}
+} // namespace details
+
+bool getSensorSubtree(SensorSubTree& subtree)
+{
+    std::shared_ptr<SensorSubTree> sensorTree;
+    details::getSensorSubtree(sensorTree);
+    if (!sensorTree)
+    {
+        return false;
+    }
+
+    subtree = *sensorTree;
+    return true;
+}
+
+std::string getSensorTypeStringFromPath(const std::string& path)
+{
+    // get sensor type string from path, path is defined as
+    // /xyz/openbmc_project/sensors/<type>/label
+    size_t typeEnd = path.rfind("/");
+    if (typeEnd == std::string::npos)
+    {
+        return path;
+    }
+    size_t typeStart = path.rfind("/", typeEnd - 1);
+    if (typeStart == std::string::npos)
+    {
+        return path;
+    }
+    // Start at the character after the '/'
+    typeStart++;
+    return path.substr(typeStart, typeEnd - typeStart);
+}
+
+uint8_t getSensorTypeFromPath(const std::string& path)
+{
+    uint8_t sensorType = 0;
+    std::string type = getSensorTypeStringFromPath(path);
+    auto findSensor = sensorTypes.find(type.c_str());
+    if (findSensor != sensorTypes.end())
+    {
+        sensorType = static_cast<uint8_t>(findSensor->second);
+    } // else default 0x0 RESERVED
+
+    return sensorType;
+}
+
+uint16_t getSensorNumberFromPath(const std::string& path)
+{
+    std::shared_ptr<SensorNumMap> sensorNumMapPtr;
+    details::getSensorNumMap(sensorNumMapPtr);
+    if (!sensorNumMapPtr)
+    {
+        return invalidSensorNumber;
+    }
+
+    try
+    {
+        return sensorNumMapPtr->right.at(path);
+    }
+    catch (std::out_of_range& e)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
+        return invalidSensorNumber;
+    }
+}
+
+uint8_t getSensorEventTypeFromPath(const std::string& path)
+{
+    // TODO: Add support for additional reading types as needed
+    return 0x1; // reading type = threshold
+}
+
+std::string getPathFromSensorNumber(uint16_t sensorNum)
+{
+    std::shared_ptr<SensorNumMap> sensorNumMapPtr;
+    details::getSensorNumMap(sensorNumMapPtr);
+    if (!sensorNumMapPtr)
+    {
+        return std::string();
+    }
+
+    try
+    {
+        return sensorNumMapPtr->left.at(sensorNum);
+    }
+    catch (std::out_of_range& e)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
+        return std::string();
+    }
+}
+
+namespace ipmi
+{
+
+std::map<std::string, std::vector<std::string>>
+    getObjectInterfaces(const char* path)
+{
+    std::map<std::string, std::vector<std::string>> interfacesResponse;
+    std::vector<std::string> interfaces;
+    std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
+
+    sdbusplus::message::message getObjectMessage =
+        dbus->new_method_call("xyz.openbmc_project.ObjectMapper",
+                              "/xyz/openbmc_project/object_mapper",
+                              "xyz.openbmc_project.ObjectMapper", "GetObject");
+    getObjectMessage.append(path, interfaces);
+
+    try
+    {
+        sdbusplus::message::message response = dbus->call(getObjectMessage);
+        response.read(interfacesResponse);
+    }
+    catch (const std::exception& e)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Failed to GetObject", phosphor::logging::entry("PATH=%s", path),
+            phosphor::logging::entry("WHAT=%s", e.what()));
+    }
+
+    return interfacesResponse;
+}
+
+std::map<std::string, Value> getEntityManagerProperties(const char* path,
+                                                        const char* interface)
+{
+    std::map<std::string, Value> properties;
+    std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
+
+    sdbusplus::message::message getProperties =
+        dbus->new_method_call("xyz.openbmc_project.EntityManager", path,
+                              "org.freedesktop.DBus.Properties", "GetAll");
+    getProperties.append(interface);
+
+    try
+    {
+        sdbusplus::message::message response = dbus->call(getProperties);
+        response.read(properties);
+    }
+    catch (const std::exception& e)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Failed to GetAll", phosphor::logging::entry("PATH=%s", path),
+            phosphor::logging::entry("INTF=%s", interface),
+            phosphor::logging::entry("WHAT=%s", e.what()));
+    }
+
+    return properties;
+}
+
+const std::string* getSensorConfigurationInterface(
+    const std::map<std::string, std::vector<std::string>>&
+        sensorInterfacesResponse)
+{
+    auto entityManagerService =
+        sensorInterfacesResponse.find("xyz.openbmc_project.EntityManager");
+    if (entityManagerService == sensorInterfacesResponse.end())
+    {
+        return nullptr;
+    }
+
+    // Find the fan configuration first (fans can have multiple configuration
+    // interfaces).
+    for (const auto& entry : entityManagerService->second)
+    {
+        if (entry == "xyz.openbmc_project.Configuration.AspeedFan" ||
+            entry == "xyz.openbmc_project.Configuration.I2CFan" ||
+            entry == "xyz.openbmc_project.Configuration.NuvotonFan")
+        {
+            return &entry;
+        }
+    }
+
+    for (const auto& entry : entityManagerService->second)
+    {
+        if (boost::algorithm::starts_with(entry,
+                                          "xyz.openbmc_project.Configuration."))
+        {
+            return &entry;
+        }
+    }
+
+    return nullptr;
+}
+
+// Follow Association properties for Sensor back to the Board dbus object to
+// check for an EntityId and EntityInstance property.
+void updateIpmiFromAssociation(const std::string& path,
+                               const DbusInterfaceMap& sensorMap,
+                               uint8_t& entityId, uint8_t& entityInstance)
+{
+    namespace fs = std::filesystem;
+
+    auto sensorAssociationObject =
+        sensorMap.find("xyz.openbmc_project.Association.Definitions");
+    if (sensorAssociationObject == sensorMap.end())
+    {
+        if constexpr (debug)
+        {
+            std::fprintf(stderr, "path=%s, no association interface found\n",
+                         path.c_str());
+        }
+
+        return;
+    }
+
+    auto associationObject =
+        sensorAssociationObject->second.find("Associations");
+    if (associationObject == sensorAssociationObject->second.end())
+    {
+        if constexpr (debug)
+        {
+            std::fprintf(stderr, "path=%s, no association records found\n",
+                         path.c_str());
+        }
+
+        return;
+    }
+
+    std::vector<Association> associationValues =
+        std::get<std::vector<Association>>(associationObject->second);
+
+    // loop through the Associations looking for the right one:
+    for (const auto& entry : associationValues)
+    {
+        // forward, reverse, endpoint
+        const std::string& forward = std::get<0>(entry);
+        const std::string& reverse = std::get<1>(entry);
+        const std::string& endpoint = std::get<2>(entry);
+
+        // We only currently concern ourselves with chassis+all_sensors.
+        if (!(forward == "chassis" && reverse == "all_sensors"))
+        {
+            continue;
+        }
+
+        // the endpoint is the board entry provided by
+        // Entity-Manager. so let's grab its properties if it has
+        // the right interface.
+
+        // just try grabbing the properties first.
+        std::map<std::string, Value> ipmiProperties =
+            getEntityManagerProperties(
+                endpoint.c_str(),
+                "xyz.openbmc_project.Inventory.Decorator.Ipmi");
+
+        auto entityIdProp = ipmiProperties.find("EntityId");
+        auto entityInstanceProp = ipmiProperties.find("EntityInstance");
+        if (entityIdProp != ipmiProperties.end())
+        {
+            entityId =
+                static_cast<uint8_t>(std::get<uint64_t>(entityIdProp->second));
+        }
+        if (entityInstanceProp != ipmiProperties.end())
+        {
+            entityInstance = static_cast<uint8_t>(
+                std::get<uint64_t>(entityInstanceProp->second));
+        }
+
+        // Now check the entity-manager entry for this sensor to see
+        // if it has its own value and use that instead.
+        //
+        // In theory, checking this first saves us from checking
+        // both, except in most use-cases identified, there won't be
+        // a per sensor override, so we need to always check both.
+        std::string sensorNameFromPath = fs::path(path).filename();
+
+        std::string sensorConfigPath = endpoint + "/" + sensorNameFromPath;
+
+        // Download the interfaces for the sensor from
+        // Entity-Manager to find the name of the configuration
+        // interface.
+        std::map<std::string, std::vector<std::string>>
+            sensorInterfacesResponse =
+                getObjectInterfaces(sensorConfigPath.c_str());
+
+        const std::string* configurationInterface =
+            getSensorConfigurationInterface(sensorInterfacesResponse);
+
+        // We didnt' find a configuration interface for this sensor, but we
+        // followed the Association property to get here, so we're done
+        // searching.
+        if (!configurationInterface)
+        {
+            break;
+        }
+
+        // We found a configuration interface.
+        std::map<std::string, Value> configurationProperties =
+            getEntityManagerProperties(sensorConfigPath.c_str(),
+                                       configurationInterface->c_str());
+
+        entityIdProp = configurationProperties.find("EntityId");
+        entityInstanceProp = configurationProperties.find("EntityInstance");
+        if (entityIdProp != configurationProperties.end())
+        {
+            entityId =
+                static_cast<uint8_t>(std::get<uint64_t>(entityIdProp->second));
+        }
+        if (entityInstanceProp != configurationProperties.end())
+        {
+            entityInstance = static_cast<uint8_t>(
+                std::get<uint64_t>(entityInstanceProp->second));
+        }
+
+        // stop searching Association records.
+        break;
+    } // end for Association vectors.
+
+    if constexpr (debug)
+    {
+        std::fprintf(stderr, "path=%s, entityId=%d, entityInstance=%d\n",
+                     path.c_str(), entityId, entityInstance);
+    }
+}
+
+} // namespace ipmi
diff --git a/dbus-sdr/sensorcommands.cpp b/dbus-sdr/sensorcommands.cpp
new file mode 100644
index 0000000..b6099ec
--- /dev/null
+++ b/dbus-sdr/sensorcommands.cpp
@@ -0,0 +1,1597 @@
+/*
+// Copyright (c) 2017 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include "dbus-sdr/sensorcommands.hpp"
+
+#include "dbus-sdr/sdrutils.hpp"
+#include "dbus-sdr/sensorutils.hpp"
+#include "dbus-sdr/storagecommands.hpp"
+
+#include <algorithm>
+#include <array>
+#include <boost/algorithm/string.hpp>
+#include <boost/container/flat_map.hpp>
+#include <chrono>
+#include <cmath>
+#include <cstring>
+#include <iostream>
+#include <ipmid/api.hpp>
+#include <ipmid/types.hpp>
+#include <ipmid/utils.hpp>
+#include <map>
+#include <memory>
+#include <optional>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/bus.hpp>
+#include <stdexcept>
+#include <string>
+#include <utility>
+#include <variant>
+
+namespace ipmi
+{
+using SDRObjectType =
+    boost::container::flat_map<uint16_t, std::vector<uint8_t>>;
+
+static constexpr int sensorMapUpdatePeriod = 10;
+
+constexpr size_t maxSDRTotalSize =
+    76; // Largest SDR Record Size (type 01) + SDR Overheader Size
+constexpr static const uint32_t noTimestamp = 0xFFFFFFFF;
+
+static uint16_t sdrReservationID;
+static uint32_t sdrLastAdd = noTimestamp;
+static uint32_t sdrLastRemove = noTimestamp;
+static constexpr size_t lastRecordIndex = 0xFFFF;
+static constexpr int GENERAL_ERROR = -1;
+
+SDRObjectType sensorDataRecords;
+
+static boost::container::flat_map<std::string, ObjectValueTree> SensorCache;
+
+// Specify the comparison required to sort and find char* map objects
+struct CmpStr
+{
+    bool operator()(const char* a, const char* b) const
+    {
+        return std::strcmp(a, b) < 0;
+    }
+};
+const static boost::container::flat_map<const char*, SensorUnits, CmpStr>
+    sensorUnits{{{"temperature", SensorUnits::degreesC},
+                 {"voltage", SensorUnits::volts},
+                 {"current", SensorUnits::amps},
+                 {"fan_tach", SensorUnits::rpm},
+                 {"power", SensorUnits::watts}}};
+
+void registerSensorFunctions() __attribute__((constructor));
+
+static sdbusplus::bus::match::match sensorAdded(
+    *getSdBus(),
+    "type='signal',member='InterfacesAdded',arg0path='/xyz/openbmc_project/"
+    "sensors/'",
+    [](sdbusplus::message::message& m) {
+        getSensorTree().clear();
+        sdrLastAdd = std::chrono::duration_cast<std::chrono::seconds>(
+                         std::chrono::system_clock::now().time_since_epoch())
+                         .count();
+    });
+
+static sdbusplus::bus::match::match sensorRemoved(
+    *getSdBus(),
+    "type='signal',member='InterfacesRemoved',arg0path='/xyz/openbmc_project/"
+    "sensors/'",
+    [](sdbusplus::message::message& m) {
+        getSensorTree().clear();
+        sdrLastRemove = std::chrono::duration_cast<std::chrono::seconds>(
+                            std::chrono::system_clock::now().time_since_epoch())
+                            .count();
+    });
+
+// this keeps track of deassertions for sensor event status command. A
+// deasertion can only happen if an assertion was seen first.
+static boost::container::flat_map<
+    std::string, boost::container::flat_map<std::string, std::optional<bool>>>
+    thresholdDeassertMap;
+
+static sdbusplus::bus::match::match thresholdChanged(
+    *getSdBus(),
+    "type='signal',member='PropertiesChanged',interface='org.freedesktop.DBus."
+    "Properties',arg0namespace='xyz.openbmc_project.Sensor.Threshold'",
+    [](sdbusplus::message::message& m) {
+        boost::container::flat_map<std::string, std::variant<bool, double>>
+            values;
+        m.read(std::string(), values);
+
+        auto findAssert =
+            std::find_if(values.begin(), values.end(), [](const auto& pair) {
+                return pair.first.find("Alarm") != std::string::npos;
+            });
+        if (findAssert != values.end())
+        {
+            auto ptr = std::get_if<bool>(&(findAssert->second));
+            if (ptr == nullptr)
+            {
+                phosphor::logging::log<phosphor::logging::level::ERR>(
+                    "thresholdChanged: Assert non bool");
+                return;
+            }
+            if (*ptr)
+            {
+                phosphor::logging::log<phosphor::logging::level::INFO>(
+                    "thresholdChanged: Assert",
+                    phosphor::logging::entry("SENSOR=%s", m.get_path()));
+                thresholdDeassertMap[m.get_path()][findAssert->first] = *ptr;
+            }
+            else
+            {
+                auto& value =
+                    thresholdDeassertMap[m.get_path()][findAssert->first];
+                if (value)
+                {
+                    phosphor::logging::log<phosphor::logging::level::INFO>(
+                        "thresholdChanged: deassert",
+                        phosphor::logging::entry("SENSOR=%s", m.get_path()));
+                    value = *ptr;
+                }
+            }
+        }
+    });
+
+static void getSensorMaxMin(const DbusInterfaceMap& sensorMap, double& max,
+                            double& min)
+{
+    max = 127;
+    min = -128;
+
+    auto sensorObject = sensorMap.find("xyz.openbmc_project.Sensor.Value");
+    auto critical =
+        sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
+    auto warning =
+        sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
+
+    if (sensorObject != sensorMap.end())
+    {
+        auto maxMap = sensorObject->second.find("MaxValue");
+        auto minMap = sensorObject->second.find("MinValue");
+
+        if (maxMap != sensorObject->second.end())
+        {
+            max = std::visit(VariantToDoubleVisitor(), maxMap->second);
+        }
+        if (minMap != sensorObject->second.end())
+        {
+            min = std::visit(VariantToDoubleVisitor(), minMap->second);
+        }
+    }
+    if (critical != sensorMap.end())
+    {
+        auto lower = critical->second.find("CriticalLow");
+        auto upper = critical->second.find("CriticalHigh");
+        if (lower != critical->second.end())
+        {
+            double value = std::visit(VariantToDoubleVisitor(), lower->second);
+            min = std::min(value, min);
+        }
+        if (upper != critical->second.end())
+        {
+            double value = std::visit(VariantToDoubleVisitor(), upper->second);
+            max = std::max(value, max);
+        }
+    }
+    if (warning != sensorMap.end())
+    {
+
+        auto lower = warning->second.find("WarningLow");
+        auto upper = warning->second.find("WarningHigh");
+        if (lower != warning->second.end())
+        {
+            double value = std::visit(VariantToDoubleVisitor(), lower->second);
+            min = std::min(value, min);
+        }
+        if (upper != warning->second.end())
+        {
+            double value = std::visit(VariantToDoubleVisitor(), upper->second);
+            max = std::max(value, max);
+        }
+    }
+}
+
+static bool getSensorMap(ipmi::Context::ptr ctx, std::string sensorConnection,
+                         std::string sensorPath, DbusInterfaceMap& sensorMap)
+{
+    static boost::container::flat_map<
+        std::string, std::chrono::time_point<std::chrono::steady_clock>>
+        updateTimeMap;
+
+    auto updateFind = updateTimeMap.find(sensorConnection);
+    auto lastUpdate = std::chrono::time_point<std::chrono::steady_clock>();
+    if (updateFind != updateTimeMap.end())
+    {
+        lastUpdate = updateFind->second;
+    }
+
+    auto now = std::chrono::steady_clock::now();
+
+    if (std::chrono::duration_cast<std::chrono::seconds>(now - lastUpdate)
+            .count() > sensorMapUpdatePeriod)
+    {
+        updateTimeMap[sensorConnection] = now;
+
+        ObjectValueTree managedObjects;
+        boost::system::error_code ec = getManagedObjects(
+            ctx, sensorConnection.c_str(), "/", managedObjects);
+        if (ec)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(
+                "GetMangagedObjects for getSensorMap failed",
+                phosphor::logging::entry("ERROR=%s", ec.message().c_str()));
+
+            return false;
+        }
+
+        SensorCache[sensorConnection] = managedObjects;
+    }
+    auto connection = SensorCache.find(sensorConnection);
+    if (connection == SensorCache.end())
+    {
+        return false;
+    }
+    auto path = connection->second.find(sensorPath);
+    if (path == connection->second.end())
+    {
+        return false;
+    }
+    sensorMap = path->second;
+
+    return true;
+}
+
+ipmi::RspType<> ipmiSenPlatformEvent(uint8_t generatorID, uint8_t evmRev,
+                                     uint8_t sensorType, uint8_t sensorNum,
+                                     uint8_t eventType, uint8_t eventData1,
+                                     std::optional<uint8_t> eventData2,
+                                     std::optional<uint8_t> eventData3)
+{
+    return ipmi::responseSuccess();
+}
+
+ipmi::RspType<uint8_t, uint8_t, uint8_t, std::optional<uint8_t>>
+    ipmiSenGetSensorReading(ipmi::Context::ptr ctx, uint8_t sensnum)
+{
+    std::string connection;
+    std::string path;
+
+    auto status = getSensorConnection(ctx, sensnum, connection, path);
+    if (status)
+    {
+        return ipmi::response(status);
+    }
+
+    DbusInterfaceMap sensorMap;
+    if (!getSensorMap(ctx, connection, path, sensorMap))
+    {
+        return ipmi::responseResponseError();
+    }
+    auto sensorObject = sensorMap.find("xyz.openbmc_project.Sensor.Value");
+
+    if (sensorObject == sensorMap.end() ||
+        sensorObject->second.find("Value") == sensorObject->second.end())
+    {
+        return ipmi::responseResponseError();
+    }
+    auto& valueVariant = sensorObject->second["Value"];
+    double reading = std::visit(VariantToDoubleVisitor(), valueVariant);
+
+    double max = 0;
+    double min = 0;
+    getSensorMaxMin(sensorMap, max, min);
+
+    int16_t mValue = 0;
+    int16_t bValue = 0;
+    int8_t rExp = 0;
+    int8_t bExp = 0;
+    bool bSigned = false;
+
+    if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned))
+    {
+        return ipmi::responseResponseError();
+    }
+
+    uint8_t value =
+        scaleIPMIValueFromDouble(reading, mValue, rExp, bValue, bExp, bSigned);
+    uint8_t operation =
+        static_cast<uint8_t>(IPMISensorReadingByte2::sensorScanningEnable);
+    operation |=
+        static_cast<uint8_t>(IPMISensorReadingByte2::eventMessagesEnable);
+    bool notReading = std::isnan(reading);
+
+    if (!notReading)
+    {
+        auto availableObject =
+            sensorMap.find("xyz.openbmc_project.State.Decorator.Availability");
+        if (availableObject != sensorMap.end())
+        {
+            auto findAvailable = availableObject->second.find("Available");
+            if (findAvailable != availableObject->second.end())
+            {
+                bool* available = std::get_if<bool>(&(findAvailable->second));
+                if (available && !(*available))
+                {
+                    notReading = true;
+                }
+            }
+        }
+    }
+
+    if (notReading)
+    {
+        operation |= static_cast<uint8_t>(
+            IPMISensorReadingByte2::readingStateUnavailable);
+    }
+
+    uint8_t thresholds = 0;
+
+    auto warningObject =
+        sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
+    if (warningObject != sensorMap.end())
+    {
+        auto alarmHigh = warningObject->second.find("WarningAlarmHigh");
+        auto alarmLow = warningObject->second.find("WarningAlarmLow");
+        if (alarmHigh != warningObject->second.end())
+        {
+            if (std::get<bool>(alarmHigh->second))
+            {
+                thresholds |= static_cast<uint8_t>(
+                    IPMISensorReadingByte3::upperNonCritical);
+            }
+        }
+        if (alarmLow != warningObject->second.end())
+        {
+            if (std::get<bool>(alarmLow->second))
+            {
+                thresholds |= static_cast<uint8_t>(
+                    IPMISensorReadingByte3::lowerNonCritical);
+            }
+        }
+    }
+
+    auto criticalObject =
+        sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
+    if (criticalObject != sensorMap.end())
+    {
+        auto alarmHigh = criticalObject->second.find("CriticalAlarmHigh");
+        auto alarmLow = criticalObject->second.find("CriticalAlarmLow");
+        if (alarmHigh != criticalObject->second.end())
+        {
+            if (std::get<bool>(alarmHigh->second))
+            {
+                thresholds |=
+                    static_cast<uint8_t>(IPMISensorReadingByte3::upperCritical);
+            }
+        }
+        if (alarmLow != criticalObject->second.end())
+        {
+            if (std::get<bool>(alarmLow->second))
+            {
+                thresholds |=
+                    static_cast<uint8_t>(IPMISensorReadingByte3::lowerCritical);
+            }
+        }
+    }
+
+    // no discrete as of today so optional byte is never returned
+    return ipmi::responseSuccess(value, operation, thresholds, std::nullopt);
+}
+
+/** @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 lowerNonRecoverable,
+    uint8_t upperNonCritical, uint8_t upperCritical,
+    uint8_t upperNonRecoverable)
+{
+    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();
+    }
+
+    std::string connection;
+    std::string path;
+
+    ipmi::Cc status = getSensorConnection(ctx, sensorNum, connection, path);
+    if (status)
+    {
+        return ipmi::response(status);
+    }
+    DbusInterfaceMap sensorMap;
+    if (!getSensorMap(ctx, connection, path, sensorMap))
+    {
+        return ipmi::responseResponseError();
+    }
+
+    double max = 0;
+    double min = 0;
+    getSensorMaxMin(sensorMap, max, min);
+
+    int16_t mValue = 0;
+    int16_t bValue = 0;
+    int8_t rExp = 0;
+    int8_t bExp = 0;
+    bool bSigned = false;
+
+    if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned))
+    {
+        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)
+    {
+        auto findThreshold =
+            sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
+        if (findThreshold == sensorMap.end())
+        {
+            return ipmi::responseInvalidFieldRequest();
+        }
+        if (lowerCriticalThreshMask)
+        {
+            auto findLower = findThreshold->second.find("CriticalLow");
+            if (findLower == findThreshold->second.end())
+            {
+                return ipmi::responseInvalidFieldRequest();
+            }
+            thresholdsToSet.emplace_back("CriticalLow", lowerCritical,
+                                         findThreshold->first);
+        }
+        if (upperCriticalThreshMask)
+        {
+            auto findUpper = findThreshold->second.find("CriticalHigh");
+            if (findUpper == findThreshold->second.end())
+            {
+                return ipmi::responseInvalidFieldRequest();
+            }
+            thresholdsToSet.emplace_back("CriticalHigh", upperCritical,
+                                         findThreshold->first);
+        }
+    }
+    if (lowerNonCriticalThreshMask || upperNonCriticalThreshMask)
+    {
+        auto findThreshold =
+            sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
+        if (findThreshold == sensorMap.end())
+        {
+            return ipmi::responseInvalidFieldRequest();
+        }
+        if (lowerNonCriticalThreshMask)
+        {
+            auto findLower = findThreshold->second.find("WarningLow");
+            if (findLower == findThreshold->second.end())
+            {
+                return ipmi::responseInvalidFieldRequest();
+            }
+            thresholdsToSet.emplace_back("WarningLow", lowerNonCritical,
+                                         findThreshold->first);
+        }
+        if (upperNonCriticalThreshMask)
+        {
+            auto findUpper = findThreshold->second.find("WarningHigh");
+            if (findUpper == findThreshold->second.end())
+            {
+                return ipmi::responseInvalidFieldRequest();
+            }
+            thresholdsToSet.emplace_back("WarningHigh", upperNonCritical,
+                                         findThreshold->first);
+        }
+    }
+    for (const auto& property : thresholdsToSet)
+    {
+        // from section 36.3 in the IPMI Spec, assume all linear
+        double valueToSet = ((mValue * std::get<thresholdValue>(property)) +
+                             (bValue * std::pow(10.0, bExp))) *
+                            std::pow(10.0, rExp);
+        setDbusProperty(
+            *getSdBus(), connection, path, std::get<interface>(property),
+            std::get<propertyName>(property), ipmi::Value(valueToSet));
+    }
+    return ipmi::responseSuccess();
+}
+
+IPMIThresholds getIPMIThresholds(const DbusInterfaceMap& sensorMap)
+{
+    IPMIThresholds resp;
+    auto warningInterface =
+        sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
+    auto criticalInterface =
+        sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
+
+    if ((warningInterface != sensorMap.end()) ||
+        (criticalInterface != sensorMap.end()))
+    {
+        auto sensorPair = sensorMap.find("xyz.openbmc_project.Sensor.Value");
+
+        if (sensorPair == sensorMap.end())
+        {
+            // should not have been able to find a sensor not implementing
+            // the sensor object
+            throw std::runtime_error("Invalid sensor map");
+        }
+
+        double max = 0;
+        double min = 0;
+        getSensorMaxMin(sensorMap, max, min);
+
+        int16_t mValue = 0;
+        int16_t bValue = 0;
+        int8_t rExp = 0;
+        int8_t bExp = 0;
+        bool bSigned = false;
+
+        if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned))
+        {
+            throw std::runtime_error("Invalid sensor atrributes");
+        }
+        if (warningInterface != sensorMap.end())
+        {
+            auto& warningMap = warningInterface->second;
+
+            auto warningHigh = warningMap.find("WarningHigh");
+            auto warningLow = warningMap.find("WarningLow");
+
+            if (warningHigh != warningMap.end())
+            {
+
+                double value =
+                    std::visit(VariantToDoubleVisitor(), warningHigh->second);
+                resp.warningHigh = scaleIPMIValueFromDouble(
+                    value, mValue, rExp, bValue, bExp, bSigned);
+            }
+            if (warningLow != warningMap.end())
+            {
+                double value =
+                    std::visit(VariantToDoubleVisitor(), warningLow->second);
+                resp.warningLow = scaleIPMIValueFromDouble(
+                    value, mValue, rExp, bValue, bExp, bSigned);
+            }
+        }
+        if (criticalInterface != sensorMap.end())
+        {
+            auto& criticalMap = criticalInterface->second;
+
+            auto criticalHigh = criticalMap.find("CriticalHigh");
+            auto criticalLow = criticalMap.find("CriticalLow");
+
+            if (criticalHigh != criticalMap.end())
+            {
+                double value =
+                    std::visit(VariantToDoubleVisitor(), criticalHigh->second);
+                resp.criticalHigh = scaleIPMIValueFromDouble(
+                    value, mValue, rExp, bValue, bExp, bSigned);
+            }
+            if (criticalLow != criticalMap.end())
+            {
+                double value =
+                    std::visit(VariantToDoubleVisitor(), criticalLow->second);
+                resp.criticalLow = scaleIPMIValueFromDouble(
+                    value, mValue, rExp, bValue, bExp, bSigned);
+            }
+        }
+    }
+    return resp;
+}
+
+ipmi::RspType<uint8_t, // readable
+              uint8_t, // lowerNCrit
+              uint8_t, // lowerCrit
+              uint8_t, // lowerNrecoverable
+              uint8_t, // upperNC
+              uint8_t, // upperCrit
+              uint8_t> // upperNRecoverable
+    ipmiSenGetSensorThresholds(ipmi::Context::ptr ctx, uint8_t sensorNumber)
+{
+    std::string connection;
+    std::string path;
+
+    auto status = getSensorConnection(ctx, sensorNumber, connection, path);
+    if (status)
+    {
+        return ipmi::response(status);
+    }
+
+    DbusInterfaceMap sensorMap;
+    if (!getSensorMap(ctx, connection, path, sensorMap))
+    {
+        return ipmi::responseResponseError();
+    }
+
+    IPMIThresholds thresholdData;
+    try
+    {
+        thresholdData = getIPMIThresholds(sensorMap);
+    }
+    catch (std::exception&)
+    {
+        return ipmi::responseResponseError();
+    }
+
+    uint8_t readable = 0;
+    uint8_t lowerNC = 0;
+    uint8_t lowerCritical = 0;
+    uint8_t lowerNonRecoverable = 0;
+    uint8_t upperNC = 0;
+    uint8_t upperCritical = 0;
+    uint8_t upperNonRecoverable = 0;
+
+    if (thresholdData.warningHigh)
+    {
+        readable |=
+            1 << static_cast<uint8_t>(IPMIThresholdRespBits::upperNonCritical);
+        upperNC = *thresholdData.warningHigh;
+    }
+    if (thresholdData.warningLow)
+    {
+        readable |=
+            1 << static_cast<uint8_t>(IPMIThresholdRespBits::lowerNonCritical);
+        lowerNC = *thresholdData.warningLow;
+    }
+
+    if (thresholdData.criticalHigh)
+    {
+        readable |=
+            1 << static_cast<uint8_t>(IPMIThresholdRespBits::upperCritical);
+        upperCritical = *thresholdData.criticalHigh;
+    }
+    if (thresholdData.criticalLow)
+    {
+        readable |=
+            1 << static_cast<uint8_t>(IPMIThresholdRespBits::lowerCritical);
+        lowerCritical = *thresholdData.criticalLow;
+    }
+
+    return ipmi::responseSuccess(readable, lowerNC, lowerCritical,
+                                 lowerNonRecoverable, upperNC, upperCritical,
+                                 upperNonRecoverable);
+}
+
+/** @brief implements the get Sensor event enable command
+ *  @param sensorNumber - sensor number
+ *
+ *  @returns IPMI completion code plus response data
+ *   - enabled               - Sensor Event messages
+ *   - assertionEnabledLsb   - Assertion event messages
+ *   - assertionEnabledMsb   - Assertion event messages
+ *   - deassertionEnabledLsb - Deassertion event messages
+ *   - deassertionEnabledMsb - Deassertion event messages
+ */
+
+ipmi::RspType<uint8_t, // enabled
+              uint8_t, // assertionEnabledLsb
+              uint8_t, // assertionEnabledMsb
+              uint8_t, // deassertionEnabledLsb
+              uint8_t> // deassertionEnabledMsb
+    ipmiSenGetSensorEventEnable(ipmi::Context::ptr ctx, uint8_t sensorNum)
+{
+    std::string connection;
+    std::string path;
+
+    uint8_t enabled = 0;
+    uint8_t assertionEnabledLsb = 0;
+    uint8_t assertionEnabledMsb = 0;
+    uint8_t deassertionEnabledLsb = 0;
+    uint8_t deassertionEnabledMsb = 0;
+
+    auto status = getSensorConnection(ctx, sensorNum, connection, path);
+    if (status)
+    {
+        return ipmi::response(status);
+    }
+
+    DbusInterfaceMap sensorMap;
+    if (!getSensorMap(ctx, connection, path, sensorMap))
+    {
+        return ipmi::responseResponseError();
+    }
+
+    auto warningInterface =
+        sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
+    auto criticalInterface =
+        sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
+    if ((warningInterface != sensorMap.end()) ||
+        (criticalInterface != sensorMap.end()))
+    {
+        enabled = static_cast<uint8_t>(
+            IPMISensorEventEnableByte2::sensorScanningEnable);
+        if (warningInterface != sensorMap.end())
+        {
+            auto& warningMap = warningInterface->second;
+
+            auto warningHigh = warningMap.find("WarningHigh");
+            auto warningLow = warningMap.find("WarningLow");
+            if (warningHigh != warningMap.end())
+            {
+                assertionEnabledLsb |= static_cast<uint8_t>(
+                    IPMISensorEventEnableThresholds::upperNonCriticalGoingHigh);
+                deassertionEnabledLsb |= static_cast<uint8_t>(
+                    IPMISensorEventEnableThresholds::upperNonCriticalGoingLow);
+            }
+            if (warningLow != warningMap.end())
+            {
+                assertionEnabledLsb |= static_cast<uint8_t>(
+                    IPMISensorEventEnableThresholds::lowerNonCriticalGoingLow);
+                deassertionEnabledLsb |= static_cast<uint8_t>(
+                    IPMISensorEventEnableThresholds::lowerNonCriticalGoingHigh);
+            }
+        }
+        if (criticalInterface != sensorMap.end())
+        {
+            auto& criticalMap = criticalInterface->second;
+
+            auto criticalHigh = criticalMap.find("CriticalHigh");
+            auto criticalLow = criticalMap.find("CriticalLow");
+
+            if (criticalHigh != criticalMap.end())
+            {
+                assertionEnabledMsb |= static_cast<uint8_t>(
+                    IPMISensorEventEnableThresholds::upperCriticalGoingHigh);
+                deassertionEnabledMsb |= static_cast<uint8_t>(
+                    IPMISensorEventEnableThresholds::upperCriticalGoingLow);
+            }
+            if (criticalLow != criticalMap.end())
+            {
+                assertionEnabledLsb |= static_cast<uint8_t>(
+                    IPMISensorEventEnableThresholds::lowerCriticalGoingLow);
+                deassertionEnabledLsb |= static_cast<uint8_t>(
+                    IPMISensorEventEnableThresholds::lowerCriticalGoingHigh);
+            }
+        }
+    }
+
+    return ipmi::responseSuccess(enabled, assertionEnabledLsb,
+                                 assertionEnabledMsb, deassertionEnabledLsb,
+                                 deassertionEnabledMsb);
+}
+
+/** @brief implements the get Sensor event status command
+ *  @param sensorNumber - sensor number, FFh = reserved
+ *
+ *  @returns IPMI completion code plus response data
+ *   - sensorEventStatus - Sensor Event messages state
+ *   - assertions        - Assertion event messages
+ *   - deassertions      - Deassertion event messages
+ */
+ipmi::RspType<uint8_t,         // sensorEventStatus
+              std::bitset<16>, // assertions
+              std::bitset<16>  // deassertion
+              >
+    ipmiSenGetSensorEventStatus(ipmi::Context::ptr ctx, uint8_t sensorNum)
+{
+    if (sensorNum == reservedSensorNumber)
+    {
+        return ipmi::responseInvalidFieldRequest();
+    }
+
+    std::string connection;
+    std::string path;
+    auto status = getSensorConnection(ctx, sensorNum, connection, path);
+    if (status)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "ipmiSenGetSensorEventStatus: Sensor connection Error",
+            phosphor::logging::entry("SENSOR=%d", sensorNum));
+        return ipmi::response(status);
+    }
+
+    DbusInterfaceMap sensorMap;
+    if (!getSensorMap(ctx, connection, path, sensorMap))
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "ipmiSenGetSensorEventStatus: Sensor Mapping Error",
+            phosphor::logging::entry("SENSOR=%s", path.c_str()));
+        return ipmi::responseResponseError();
+    }
+    auto warningInterface =
+        sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Warning");
+    auto criticalInterface =
+        sensorMap.find("xyz.openbmc_project.Sensor.Threshold.Critical");
+
+    uint8_t sensorEventStatus =
+        static_cast<uint8_t>(IPMISensorEventEnableByte2::sensorScanningEnable);
+
+    std::optional<bool> criticalDeassertHigh =
+        thresholdDeassertMap[path]["CriticalAlarmHigh"];
+    std::optional<bool> criticalDeassertLow =
+        thresholdDeassertMap[path]["CriticalAlarmLow"];
+    std::optional<bool> warningDeassertHigh =
+        thresholdDeassertMap[path]["WarningAlarmHigh"];
+    std::optional<bool> warningDeassertLow =
+        thresholdDeassertMap[path]["WarningAlarmLow"];
+
+    std::bitset<16> assertions = 0;
+    std::bitset<16> deassertions = 0;
+
+    if (criticalDeassertHigh && !*criticalDeassertHigh)
+    {
+        deassertions.set(static_cast<size_t>(
+            IPMIGetSensorEventEnableThresholds::upperCriticalGoingHigh));
+    }
+    if (criticalDeassertLow && !*criticalDeassertLow)
+    {
+        deassertions.set(static_cast<size_t>(
+            IPMIGetSensorEventEnableThresholds::upperCriticalGoingLow));
+    }
+    if (warningDeassertHigh && !*warningDeassertHigh)
+    {
+        deassertions.set(static_cast<size_t>(
+            IPMIGetSensorEventEnableThresholds::upperNonCriticalGoingHigh));
+    }
+    if (warningDeassertLow && !*warningDeassertLow)
+    {
+        deassertions.set(static_cast<size_t>(
+            IPMIGetSensorEventEnableThresholds::lowerNonCriticalGoingHigh));
+    }
+    if ((warningInterface != sensorMap.end()) ||
+        (criticalInterface != sensorMap.end()))
+    {
+        sensorEventStatus = static_cast<size_t>(
+            IPMISensorEventEnableByte2::eventMessagesEnable);
+        if (warningInterface != sensorMap.end())
+        {
+            auto& warningMap = warningInterface->second;
+
+            auto warningHigh = warningMap.find("WarningAlarmHigh");
+            auto warningLow = warningMap.find("WarningAlarmLow");
+            auto warningHighAlarm = false;
+            auto warningLowAlarm = false;
+
+            if (warningHigh != warningMap.end())
+            {
+                warningHighAlarm = std::get<bool>(warningHigh->second);
+            }
+            if (warningLow != warningMap.end())
+            {
+                warningLowAlarm = std::get<bool>(warningLow->second);
+            }
+            if (warningHighAlarm)
+            {
+                assertions.set(
+                    static_cast<size_t>(IPMIGetSensorEventEnableThresholds::
+                                            upperNonCriticalGoingHigh));
+            }
+            if (warningLowAlarm)
+            {
+                assertions.set(
+                    static_cast<size_t>(IPMIGetSensorEventEnableThresholds::
+                                            lowerNonCriticalGoingLow));
+            }
+        }
+        if (criticalInterface != sensorMap.end())
+        {
+            auto& criticalMap = criticalInterface->second;
+
+            auto criticalHigh = criticalMap.find("CriticalAlarmHigh");
+            auto criticalLow = criticalMap.find("CriticalAlarmLow");
+            auto criticalHighAlarm = false;
+            auto criticalLowAlarm = false;
+
+            if (criticalHigh != criticalMap.end())
+            {
+                criticalHighAlarm = std::get<bool>(criticalHigh->second);
+            }
+            if (criticalLow != criticalMap.end())
+            {
+                criticalLowAlarm = std::get<bool>(criticalLow->second);
+            }
+            if (criticalHighAlarm)
+            {
+                assertions.set(
+                    static_cast<size_t>(IPMIGetSensorEventEnableThresholds::
+                                            upperCriticalGoingHigh));
+            }
+            if (criticalLowAlarm)
+            {
+                assertions.set(static_cast<size_t>(
+                    IPMIGetSensorEventEnableThresholds::lowerCriticalGoingLow));
+            }
+        }
+    }
+
+    return ipmi::responseSuccess(sensorEventStatus, assertions, deassertions);
+}
+
+static int getSensorDataRecords(ipmi::Context::ptr ctx)
+{
+    auto& sensorTree = getSensorTree();
+    size_t recordID = 0;
+    size_t fruCount = 0;
+
+    ipmi::Cc ret = ipmi::storage::getFruSdrCount(ctx, fruCount);
+    if (ret != ipmi::ccSuccess)
+    {
+        return GENERAL_ERROR;
+    }
+
+    size_t lastRecord =
+        sensorTree.size() + fruCount + ipmi::storage::type12Count - 1;
+    if (lastRecord > lastRecordIndex)
+    {
+        return GENERAL_ERROR;
+    }
+
+    std::string connection;
+    std::string path;
+    for (const auto& sensor : sensorTree)
+    {
+
+        connection = sensor.second.begin()->first;
+        path = sensor.first;
+
+        DbusInterfaceMap sensorMap;
+        if (!getSensorMap(ctx, connection, path, sensorMap))
+        {
+            return GENERAL_ERROR;
+        }
+        uint16_t sensorNum = getSensorNumberFromPath(path);
+        if (sensorNum == invalidSensorNumber)
+        {
+            return GENERAL_ERROR;
+        }
+        uint8_t sensornumber = static_cast<uint8_t>(sensorNum);
+        uint8_t lun = static_cast<uint8_t>(sensorNum >> 8);
+
+        get_sdr::SensorDataFullRecord record = {0};
+
+        get_sdr::header::set_record_id(
+            recordID,
+            reinterpret_cast<get_sdr::SensorDataRecordHeader*>(&record));
+        record.header.sdr_version = ipmiSdrVersion;
+        record.header.record_type = get_sdr::SENSOR_DATA_FULL_RECORD;
+        record.header.record_length = sizeof(get_sdr::SensorDataFullRecord) -
+                                      sizeof(get_sdr::SensorDataRecordHeader);
+        record.key.owner_id = 0x20;
+        record.key.owner_lun = lun;
+        record.key.sensor_number = sensornumber;
+
+        record.body.sensor_capabilities = 0x68; // auto rearm - todo hysteresis
+        record.body.sensor_type = getSensorTypeFromPath(path);
+        std::string type = getSensorTypeStringFromPath(path);
+        auto typeCstr = type.c_str();
+        auto findUnits = sensorUnits.find(typeCstr);
+        if (findUnits != sensorUnits.end())
+        {
+            record.body.sensor_units_2_base =
+                static_cast<uint8_t>(findUnits->second);
+        } // else default 0x0 unspecified
+
+        record.body.event_reading_type = getSensorEventTypeFromPath(path);
+
+        auto sensorObject = sensorMap.find("xyz.openbmc_project.Sensor.Value");
+        if (sensorObject == sensorMap.end())
+        {
+            return GENERAL_ERROR;
+        }
+
+        uint8_t entityId = 0;
+        uint8_t entityInstance = 0x01;
+
+        // follow the association chain to get the parent board's entityid and
+        // entityInstance
+        updateIpmiFromAssociation(path, sensorMap, entityId, entityInstance);
+
+        record.body.entity_id = entityId;
+        record.body.entity_instance = entityInstance;
+
+        auto maxObject = sensorObject->second.find("MaxValue");
+        auto minObject = sensorObject->second.find("MinValue");
+
+        // If min and/or max are left unpopulated,
+        // then default to what a signed byte would be, namely (-128,127) range.
+        auto max = static_cast<double>(std::numeric_limits<int8_t>::max());
+        auto min = static_cast<double>(std::numeric_limits<int8_t>::lowest());
+        if (maxObject != sensorObject->second.end())
+        {
+            max = std::visit(VariantToDoubleVisitor(), maxObject->second);
+        }
+
+        if (minObject != sensorObject->second.end())
+        {
+            min = std::visit(VariantToDoubleVisitor(), minObject->second);
+        }
+
+        int16_t mValue = 0;
+        int8_t rExp = 0;
+        int16_t bValue = 0;
+        int8_t bExp = 0;
+        bool bSigned = false;
+
+        if (!getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned))
+        {
+            return GENERAL_ERROR;
+        }
+
+        // The record.body is a struct SensorDataFullRecordBody
+        // from sensorhandler.hpp in phosphor-ipmi-host.
+        // The meaning of these bits appears to come from
+        // table 43.1 of the IPMI spec.
+        // The above 5 sensor attributes are stuffed in as follows:
+        // Byte 21 = AA000000 = analog interpretation, 10 signed, 00 unsigned
+        // Byte 22-24 are for other purposes
+        // Byte 25 = MMMMMMMM = LSB of M
+        // Byte 26 = MMTTTTTT = MSB of M (signed), and Tolerance
+        // Byte 27 = BBBBBBBB = LSB of B
+        // Byte 28 = BBAAAAAA = MSB of B (signed), and LSB of Accuracy
+        // Byte 29 = AAAAEE00 = MSB of Accuracy, exponent of Accuracy
+        // Byte 30 = RRRRBBBB = rExp (signed), bExp (signed)
+
+        // apply M, B, and exponents, M and B are 10 bit values, exponents are 4
+        record.body.m_lsb = mValue & 0xFF;
+
+        uint8_t mBitSign = (mValue < 0) ? 1 : 0;
+        uint8_t mBitNine = (mValue & 0x0100) >> 8;
+
+        // move the smallest bit of the MSB into place (bit 9)
+        // the MSbs are bits 7:8 in m_msb_and_tolerance
+        record.body.m_msb_and_tolerance = (mBitSign << 7) | (mBitNine << 6);
+
+        record.body.b_lsb = bValue & 0xFF;
+
+        uint8_t bBitSign = (bValue < 0) ? 1 : 0;
+        uint8_t bBitNine = (bValue & 0x0100) >> 8;
+
+        // move the smallest bit of the MSB into place (bit 9)
+        // the MSbs are bits 7:8 in b_msb_and_accuracy_lsb
+        record.body.b_msb_and_accuracy_lsb = (bBitSign << 7) | (bBitNine << 6);
+
+        uint8_t rExpSign = (rExp < 0) ? 1 : 0;
+        uint8_t rExpBits = rExp & 0x07;
+
+        uint8_t bExpSign = (bExp < 0) ? 1 : 0;
+        uint8_t bExpBits = bExp & 0x07;
+
+        // move rExp and bExp into place
+        record.body.r_b_exponents =
+            (rExpSign << 7) | (rExpBits << 4) | (bExpSign << 3) | bExpBits;
+
+        // Set the analog reading byte interpretation accordingly
+        record.body.sensor_units_1 = (bSigned ? 1 : 0) << 7;
+
+        // TODO(): Perhaps care about Tolerance, Accuracy, and so on
+        // These seem redundant, but derivable from the above 5 attributes
+        // Original comment said "todo fill out rest of units"
+
+        // populate sensor name from path
+        std::string name;
+        size_t nameStart = path.rfind("/");
+        if (nameStart != std::string::npos)
+        {
+            name = path.substr(nameStart + 1, std::string::npos - nameStart);
+        }
+
+        std::replace(name.begin(), name.end(), '_', ' ');
+        if (name.size() > FULL_RECORD_ID_STR_MAX_LENGTH)
+        {
+            // try to not truncate by replacing common words
+            constexpr std::array<std::pair<const char*, const char*>, 2>
+                replaceWords = {std::make_pair("Output", "Out"),
+                                std::make_pair("Input", "In")};
+            for (const auto& [find, replace] : replaceWords)
+            {
+                boost::replace_all(name, find, replace);
+            }
+
+            name.resize(FULL_RECORD_ID_STR_MAX_LENGTH);
+        }
+        record.body.id_string_info = name.size();
+        std::strncpy(record.body.id_string, name.c_str(),
+                     sizeof(record.body.id_string));
+
+        IPMIThresholds thresholdData;
+        try
+        {
+            thresholdData = getIPMIThresholds(sensorMap);
+        }
+        catch (std::exception&)
+        {
+            return GENERAL_ERROR;
+        }
+
+        if (thresholdData.criticalHigh)
+        {
+            record.body.upper_critical_threshold = *thresholdData.criticalHigh;
+            record.body.supported_deassertions[1] |= static_cast<uint8_t>(
+                IPMISensorEventEnableThresholds::criticalThreshold);
+            record.body.supported_deassertions[1] |= static_cast<uint8_t>(
+                IPMISensorEventEnableThresholds::upperCriticalGoingHigh);
+            record.body.supported_assertions[1] |= static_cast<uint8_t>(
+                IPMISensorEventEnableThresholds::upperCriticalGoingHigh);
+            record.body.discrete_reading_setting_mask[0] |=
+                static_cast<uint8_t>(IPMISensorReadingByte3::upperCritical);
+        }
+        if (thresholdData.warningHigh)
+        {
+            record.body.upper_noncritical_threshold =
+                *thresholdData.warningHigh;
+            record.body.supported_deassertions[1] |= static_cast<uint8_t>(
+                IPMISensorEventEnableThresholds::nonCriticalThreshold);
+            record.body.supported_deassertions[0] |= static_cast<uint8_t>(
+                IPMISensorEventEnableThresholds::upperNonCriticalGoingHigh);
+            record.body.supported_assertions[0] |= static_cast<uint8_t>(
+                IPMISensorEventEnableThresholds::upperNonCriticalGoingHigh);
+            record.body.discrete_reading_setting_mask[0] |=
+                static_cast<uint8_t>(IPMISensorReadingByte3::upperNonCritical);
+        }
+        if (thresholdData.criticalLow)
+        {
+            record.body.lower_critical_threshold = *thresholdData.criticalLow;
+            record.body.supported_assertions[1] |= static_cast<uint8_t>(
+                IPMISensorEventEnableThresholds::criticalThreshold);
+            record.body.supported_deassertions[0] |= static_cast<uint8_t>(
+                IPMISensorEventEnableThresholds::lowerCriticalGoingLow);
+            record.body.supported_assertions[0] |= static_cast<uint8_t>(
+                IPMISensorEventEnableThresholds::lowerCriticalGoingLow);
+            record.body.discrete_reading_setting_mask[0] |=
+                static_cast<uint8_t>(IPMISensorReadingByte3::lowerCritical);
+        }
+        if (thresholdData.warningLow)
+        {
+            record.body.lower_noncritical_threshold = *thresholdData.warningLow;
+            record.body.supported_assertions[1] |= static_cast<uint8_t>(
+                IPMISensorEventEnableThresholds::nonCriticalThreshold);
+            record.body.supported_deassertions[0] |= static_cast<uint8_t>(
+                IPMISensorEventEnableThresholds::lowerNonCriticalGoingLow);
+            record.body.supported_assertions[0] |= static_cast<uint8_t>(
+                IPMISensorEventEnableThresholds::lowerNonCriticalGoingLow);
+            record.body.discrete_reading_setting_mask[0] |=
+                static_cast<uint8_t>(IPMISensorReadingByte3::lowerNonCritical);
+        }
+
+        // everything that is readable is setable
+        record.body.discrete_reading_setting_mask[1] =
+            record.body.discrete_reading_setting_mask[0];
+
+        // insert the record into the map
+        std::vector<uint8_t> sdr;
+        sdr.insert(sdr.end(), (uint8_t*)&record,
+                   ((uint8_t*)&record) + sizeof(record));
+        sensorDataRecords.insert_or_assign(recordID, sdr);
+        recordID++;
+    }
+
+    size_t nonSensorRecCount = fruCount + ipmi::storage::type12Count;
+    do
+    {
+        size_t fruIndex = recordID - sensorTree.size();
+
+        if (fruIndex >= fruCount)
+        {
+            // handle type 12 hardcoded records
+            size_t type12Index = fruIndex - fruCount;
+            if (type12Index >= ipmi::storage::type12Count)
+            {
+                return GENERAL_ERROR;
+            }
+            std::vector<uint8_t> record =
+                ipmi::storage::getType12SDRs(type12Index, recordID);
+            sensorDataRecords.insert_or_assign(recordID, record);
+        }
+        else
+        {
+            // handle fru records
+            get_sdr::SensorDataFruRecord data;
+            ret = ipmi::storage::getFruSdrs(ctx, fruIndex, data);
+            if (ret != IPMI_CC_OK)
+            {
+                return GENERAL_ERROR;
+            }
+            get_sdr::header::set_record_id(
+                recordID,
+                reinterpret_cast<get_sdr::SensorDataRecordHeader*>(&data));
+
+            std::vector<uint8_t> record;
+            record.insert(record.end(), (uint8_t*)&data,
+                          ((uint8_t*)&data) + sizeof(data));
+            sensorDataRecords.insert_or_assign(recordID, record);
+        }
+        recordID++;
+    } while (--nonSensorRecCount);
+    return 0;
+}
+
+/** @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
+ */
+static ipmi::RspType<uint8_t, // respcount
+                     uint8_t, // dynamic population flags
+                     uint32_t // last time a sensor was added
+                     >
+    ipmiSensorGetDeviceSdrInfo(ipmi::Context::ptr ctx,
+                               std::optional<uint8_t> count)
+{
+    auto& sensorTree = getSensorTree();
+    uint8_t sdrCount = 0;
+    // Sensors are dynamically allocated, and there is at least one LUN
+    uint8_t lunsAndDynamicPopulation = 0x80;
+    constexpr uint8_t getSdrCount = 0x01;
+    constexpr uint8_t getSensorCount = 0x00;
+
+    if (!getSensorSubtree(sensorTree) || sensorTree.empty())
+    {
+        return ipmi::responseResponseError();
+    }
+
+    if (sensorDataRecords.empty() && getSensorDataRecords(ctx))
+    {
+        return ipmi::responseResponseError();
+    }
+
+    uint16_t numSensors = sensorTree.size();
+    if (count.value_or(0) == getSdrCount)
+    {
+        // Count the number of Type 1 SDR entries assigned to the LUN
+        for (auto sdr : sensorDataRecords)
+        {
+            get_sdr::SensorDataRecordHeader* hdr =
+                reinterpret_cast<get_sdr::SensorDataRecordHeader*>(
+                    sdr.second.data());
+            if (hdr && hdr->record_type == get_sdr::SENSOR_DATA_FULL_RECORD)
+            {
+                get_sdr::SensorDataFullRecord* record =
+                    reinterpret_cast<get_sdr::SensorDataFullRecord*>(
+                        sdr.second.data());
+                if (ctx->lun == record->key.owner_lun)
+                {
+                    sdrCount++;
+                }
+            }
+        }
+    }
+    else if (count.value_or(0) == getSensorCount)
+    {
+        // Return the number of sensors attached to the LUN
+        if ((ctx->lun == 0) && (numSensors > 0))
+        {
+            sdrCount =
+                (numSensors > maxSensorsPerLUN) ? maxSensorsPerLUN : numSensors;
+        }
+        else if ((ctx->lun == 1) && (numSensors > maxSensorsPerLUN))
+        {
+            sdrCount = (numSensors > (2 * maxSensorsPerLUN))
+                           ? maxSensorsPerLUN
+                           : (numSensors - maxSensorsPerLUN) & maxSensorsPerLUN;
+        }
+        else if (ctx->lun == 3)
+        {
+            if (numSensors <= maxIPMISensors)
+            {
+                sdrCount =
+                    (numSensors - (2 * maxSensorsPerLUN)) & maxSensorsPerLUN;
+            }
+            else
+            {
+                // error
+                throw std::out_of_range(
+                    "Maximum number of IPMI sensors exceeded.");
+            }
+        }
+    }
+    else
+    {
+        return ipmi::responseInvalidFieldRequest();
+    }
+
+    // Get Sensor count. This returns the number of sensors
+    if (numSensors > 0)
+    {
+        lunsAndDynamicPopulation |= 1;
+    }
+    if (numSensors > maxSensorsPerLUN)
+    {
+        lunsAndDynamicPopulation |= 2;
+    }
+    if (numSensors >= (maxSensorsPerLUN * 2))
+    {
+        lunsAndDynamicPopulation |= 8;
+    }
+    if (numSensors > maxIPMISensors)
+    {
+        // error
+        throw std::out_of_range("Maximum number of IPMI sensors exceeded.");
+    }
+
+    return ipmi::responseSuccess(sdrCount, lunsAndDynamicPopulation,
+                                 sdrLastAdd);
+}
+
+/* end sensor commands */
+
+/* storage commands */
+
+ipmi::RspType<uint8_t,  // sdr version
+              uint16_t, // record count
+              uint16_t, // free space
+              uint32_t, // most recent addition
+              uint32_t, // most recent erase
+              uint8_t   // operationSupport
+              >
+    ipmiStorageGetSDRRepositoryInfo(ipmi::Context::ptr ctx)
+{
+    auto& sensorTree = getSensorTree();
+    constexpr const uint16_t unspecifiedFreeSpace = 0xFFFF;
+    if (sensorTree.empty() && !getSensorSubtree(sensorTree))
+    {
+        return ipmi::responseResponseError();
+    }
+
+    size_t fruCount = 0;
+    ipmi::Cc ret = ipmi::storage::getFruSdrCount(ctx, fruCount);
+    if (ret != ipmi::ccSuccess)
+    {
+        return ipmi::response(ret);
+    }
+
+    uint16_t recordCount =
+        sensorTree.size() + fruCount + ipmi::storage::type12Count;
+
+    uint8_t operationSupport = static_cast<uint8_t>(
+        SdrRepositoryInfoOps::overflow); // write not supported
+
+    operationSupport |=
+        static_cast<uint8_t>(SdrRepositoryInfoOps::allocCommandSupported);
+    operationSupport |= static_cast<uint8_t>(
+        SdrRepositoryInfoOps::reserveSDRRepositoryCommandSupported);
+    return ipmi::responseSuccess(ipmiSdrVersion, recordCount,
+                                 unspecifiedFreeSpace, sdrLastAdd,
+                                 sdrLastRemove, operationSupport);
+}
+
+/** @brief implements the get SDR allocation info command
+ *
+ *  @returns IPMI completion code plus response data
+ *   - allocUnits    - Number of possible allocation units
+ *   - allocUnitSize - Allocation unit size in bytes.
+ *   - allocUnitFree - Number of free allocation units
+ *   - allocUnitLargestFree - Largest free block in allocation units
+ *   - maxRecordSize    - Maximum record size in allocation units.
+ */
+ipmi::RspType<uint16_t, // allocUnits
+              uint16_t, // allocUnitSize
+              uint16_t, // allocUnitFree
+              uint16_t, // allocUnitLargestFree
+              uint8_t   // maxRecordSize
+              >
+    ipmiStorageGetSDRAllocationInfo()
+{
+    // 0000h unspecified number of alloc units
+    constexpr uint16_t allocUnits = 0;
+
+    constexpr uint16_t allocUnitFree = 0;
+    constexpr uint16_t allocUnitLargestFree = 0;
+    // only allow one block at a time
+    constexpr uint8_t maxRecordSize = 1;
+
+    return ipmi::responseSuccess(allocUnits, maxSDRTotalSize, allocUnitFree,
+                                 allocUnitLargestFree, maxRecordSize);
+}
+
+/** @brief implements the reserve SDR command
+ *  @returns IPMI completion code plus response data
+ *   - sdrReservationID
+ */
+ipmi::RspType<uint16_t> ipmiStorageReserveSDR()
+{
+    sdrReservationID++;
+    if (sdrReservationID == 0)
+    {
+        sdrReservationID++;
+    }
+
+    return ipmi::responseSuccess(sdrReservationID);
+}
+
+ipmi::RspType<uint16_t,            // next record ID
+              std::vector<uint8_t> // payload
+              >
+    ipmiStorageGetSDR(ipmi::Context::ptr ctx, uint16_t reservationID,
+                      uint16_t recordID, uint8_t offset, uint8_t bytesToRead)
+{
+    // reservation required for partial reads with non zero offset into
+    // record
+    if ((sdrReservationID == 0 || reservationID != sdrReservationID) && offset)
+    {
+        return ipmi::responseInvalidReservationId();
+    }
+
+    if (sensorDataRecords.empty() && getSensorDataRecords(ctx))
+    {
+        return ipmi::responseResponseError();
+    }
+
+    auto& sensorTree = getSensorTree();
+    if (sensorTree.empty() && !getSensorSubtree(sensorTree))
+    {
+        return ipmi::responseResponseError();
+    }
+
+    size_t fruCount = 0;
+    ipmi::Cc ret = ipmi::storage::getFruSdrCount(ctx, fruCount);
+    if (ret != ipmi::ccSuccess)
+    {
+        return ipmi::response(ret);
+    }
+
+    size_t lastRecord =
+        sensorTree.size() + fruCount + ipmi::storage::type12Count - 1;
+    if (recordID == lastRecordIndex)
+    {
+        recordID = lastRecord;
+    }
+    if (recordID > lastRecord)
+    {
+        return ipmi::responseInvalidFieldRequest();
+    }
+
+    get_sdr::SensorDataRecordHeader* hdr =
+        reinterpret_cast<get_sdr::SensorDataRecordHeader*>(
+            sensorDataRecords[recordID].data());
+
+    if (!hdr)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error: record header is null");
+        std::vector<uint8_t> emptyData;
+        uint16_t nextRecordId = lastRecord > recordID ? recordID + 1 : 0XFFFF;
+        return ipmi::responseSuccess(nextRecordId, emptyData);
+    }
+
+    size_t sdrLength =
+        sizeof(get_sdr::SensorDataRecordHeader) + hdr->record_length;
+    if (sdrLength < (offset + bytesToRead))
+    {
+        bytesToRead = sdrLength - offset;
+    }
+
+    uint8_t* respStart = reinterpret_cast<uint8_t*>(hdr) + offset;
+    if (!respStart)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Error: record is null");
+        std::vector<uint8_t> emptyData;
+        uint16_t nextRecordId = lastRecord > recordID ? recordID + 1 : 0XFFFF;
+        return ipmi::responseSuccess(nextRecordId, emptyData);
+    }
+
+    std::vector<uint8_t> recordData(respStart, respStart + bytesToRead);
+    uint16_t nextRecordId = lastRecord > recordID ? recordID + 1 : 0XFFFF;
+    return ipmi::responseSuccess(nextRecordId, recordData);
+}
+/* end storage commands */
+
+void registerSensorFunctions()
+{
+    // <Platform Event>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
+                          ipmi::sensor_event::cmdPlatformEvent,
+                          ipmi::Privilege::Operator, ipmiSenPlatformEvent);
+
+    // <Get Sensor Reading>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
+                          ipmi::sensor_event::cmdGetSensorReading,
+                          ipmi::Privilege::User, ipmiSenGetSensorReading);
+
+    // <Get Sensor Threshold>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
+                          ipmi::sensor_event::cmdGetSensorThreshold,
+                          ipmi::Privilege::User, ipmiSenGetSensorThresholds);
+
+    // <Set Sensor Threshold>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
+                          ipmi::sensor_event::cmdSetSensorThreshold,
+                          ipmi::Privilege::Operator,
+                          ipmiSenSetSensorThresholds);
+
+    // <Get Sensor Event Enable>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
+                          ipmi::sensor_event::cmdGetSensorEventEnable,
+                          ipmi::Privilege::User, ipmiSenGetSensorEventEnable);
+
+    // <Get Sensor Event Status>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
+                          ipmi::sensor_event::cmdGetSensorEventStatus,
+                          ipmi::Privilege::User, ipmiSenGetSensorEventStatus);
+
+    // register all storage commands for both Sensor and Storage command
+    // versions
+
+    // <Get SDR Repository Info>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
+                          ipmi::storage::cmdGetSdrRepositoryInfo,
+                          ipmi::Privilege::User,
+                          ipmiStorageGetSDRRepositoryInfo);
+
+    // <Get Device SDR Info>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
+                          ipmi::sensor_event::cmdGetDeviceSdrInfo,
+                          ipmi::Privilege::User, ipmiSensorGetDeviceSdrInfo);
+
+    // <Get SDR Allocation Info>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
+                          ipmi::storage::cmdGetSdrRepositoryAllocInfo,
+                          ipmi::Privilege::User,
+                          ipmiStorageGetSDRAllocationInfo);
+
+    // <Reserve SDR Repo>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
+                          ipmi::sensor_event::cmdReserveDeviceSdrRepository,
+                          ipmi::Privilege::User, ipmiStorageReserveSDR);
+
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
+                          ipmi::storage::cmdReserveSdrRepository,
+                          ipmi::Privilege::User, ipmiStorageReserveSDR);
+
+    // <Get Sdr>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor,
+                          ipmi::sensor_event::cmdGetDeviceSdr,
+                          ipmi::Privilege::User, ipmiStorageGetSDR);
+
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
+                          ipmi::storage::cmdGetSdr, ipmi::Privilege::User,
+                          ipmiStorageGetSDR);
+}
+} // namespace ipmi
diff --git a/dbus-sdr/sensorutils.cpp b/dbus-sdr/sensorutils.cpp
new file mode 100644
index 0000000..d31dbed
--- /dev/null
+++ b/dbus-sdr/sensorutils.cpp
@@ -0,0 +1,325 @@
+/*
+// Copyright (c) 2017 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include "dbus-sdr/sensorutils.hpp"
+
+#include <algorithm>
+#include <cmath>
+#include <iostream>
+
+namespace ipmi
+{
+
+// Helper function to avoid repeated complicated expression
+static bool baseInRange(double base)
+{
+    auto min10 = static_cast<double>(minInt10);
+    auto max10 = static_cast<double>(maxInt10);
+
+    return ((base >= min10) && (base <= max10));
+}
+
+// Helper function for internal use by getSensorAttributes()
+// Ensures floating-point "base" is within bounds,
+// and adjusts integer exponent "expShift" accordingly.
+// To minimize data loss when later truncating to integer,
+// the floating-point "base" will be as large as possible,
+// but still within the bounds (minInt10,maxInt10).
+// The bounds of "expShift" are (minInt4,maxInt4).
+// Consider this equation: n = base * (10.0 ** expShift)
+// This function will try to maximize "base",
+// adjusting "expShift" to keep the value "n" unchanged,
+// while keeping base and expShift within bounds.
+// Returns true if successful, modifies values in-place
+static bool scaleFloatExp(double& base, int8_t& expShift)
+{
+    // Comparing with zero should be OK, zero is special in floating-point
+    // If base is exactly zero, no adjustment of the exponent is necessary
+    if (base == 0.0)
+    {
+        return true;
+    }
+
+    // As long as base value is within allowed range, expand precision
+    // This will help to avoid loss when later rounding to integer
+    while (baseInRange(base))
+    {
+        if (expShift <= minInt4)
+        {
+            // Already at the minimum expShift, can not decrement it more
+            break;
+        }
+
+        // Multiply by 10, but shift decimal point to the left, no net change
+        base *= 10.0;
+        --expShift;
+    }
+
+    // As long as base value is *not* within range, shrink precision
+    // This will pull base value closer to zero, thus within range
+    while (!(baseInRange(base)))
+    {
+        if (expShift >= maxInt4)
+        {
+            // Already at the maximum expShift, can not increment it more
+            break;
+        }
+
+        // Divide by 10, but shift decimal point to the right, no net change
+        base /= 10.0;
+        ++expShift;
+    }
+
+    // If the above loop was not able to pull it back within range,
+    // the base value is beyond what expShift can represent, return false.
+    return baseInRange(base);
+}
+
+// Helper function for internal use by getSensorAttributes()
+// Ensures integer "ibase" is no larger than necessary,
+// by normalizing it so that the decimal point shift is in the exponent,
+// whenever possible.
+// This provides more consistent results,
+// as many equivalent solutions are collapsed into one consistent solution.
+// If integer "ibase" is a clean multiple of 10,
+// divide it by 10 (this is lossless), so it is closer to zero.
+// Also modify floating-point "dbase" at the same time,
+// as both integer and floating-point base share the same expShift.
+// Example: (ibase=300, expShift=2) becomes (ibase=3, expShift=4)
+// because the underlying value is the same: 200*(10**2) == 2*(10**4)
+// Always successful, modifies values in-place
+static void normalizeIntExp(int16_t& ibase, int8_t& expShift, double& dbase)
+{
+    for (;;)
+    {
+        // If zero, already normalized, ensure exponent also zero
+        if (ibase == 0)
+        {
+            expShift = 0;
+            break;
+        }
+
+        // If not cleanly divisible by 10, already normalized
+        if ((ibase % 10) != 0)
+        {
+            break;
+        }
+
+        // If exponent already at max, already normalized
+        if (expShift >= maxInt4)
+        {
+            break;
+        }
+
+        // Bring values closer to zero, correspondingly shift exponent,
+        // without changing the underlying number that this all represents,
+        // similar to what is done by scaleFloatExp().
+        // The floating-point base must be kept in sync with the integer base,
+        // as both floating-point and integer share the same exponent.
+        ibase /= 10;
+        dbase /= 10.0;
+        ++expShift;
+    }
+}
+
+// The IPMI equation:
+// y = (Mx + (B * 10^(bExp))) * 10^(rExp)
+// Section 36.3 of this document:
+// https://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/ipmi-second-gen-interface-spec-v2-rev1-1.pdf
+//
+// The goal is to exactly match the math done by the ipmitool command,
+// at the other side of the interface:
+// https://github.com/ipmitool/ipmitool/blob/42a023ff0726c80e8cc7d30315b987fe568a981d/lib/ipmi_sdr.c#L360
+//
+// To use with Wolfram Alpha, make all variables single letters
+// bExp becomes E, rExp becomes R
+// https://www.wolframalpha.com/input/?i=y%3D%28%28M*x%29%2B%28B*%2810%5EE%29%29%29*%2810%5ER%29
+bool getSensorAttributes(const double max, const double min, int16_t& mValue,
+                         int8_t& rExp, int16_t& bValue, int8_t& bExp,
+                         bool& bSigned)
+{
+    if (!(std::isfinite(min)))
+    {
+        std::cerr << "getSensorAttributes: Min value is unusable\n";
+        return false;
+    }
+    if (!(std::isfinite(max)))
+    {
+        std::cerr << "getSensorAttributes: Max value is unusable\n";
+        return false;
+    }
+
+    // Because NAN has already been tested for, this comparison works
+    if (max <= min)
+    {
+        std::cerr << "getSensorAttributes: Max must be greater than min\n";
+        return false;
+    }
+
+    // Given min and max, we must solve for M, B, bExp, rExp
+    // y comes in from D-Bus (the actual sensor reading)
+    // x is calculated from y by scaleIPMIValueFromDouble() below
+    // If y is min, x should equal = 0 (or -128 if signed)
+    // If y is max, x should equal 255 (or 127 if signed)
+    double fullRange = max - min;
+    double lowestX;
+
+    rExp = 0;
+    bExp = 0;
+
+    // TODO(): The IPMI document is ambiguous, as to whether
+    // the resulting byte should be signed or unsigned,
+    // essentially leaving it up to the caller.
+    // The document just refers to it as "raw reading",
+    // or "byte of reading", without giving further details.
+    // Previous code set it signed if min was less than zero,
+    // so I'm sticking with that, until I learn otherwise.
+    if (min < 0.0)
+    {
+        // TODO(): It would be worth experimenting with the range (-127,127),
+        // instead of the range (-128,127), because this
+        // would give good symmetry around zero, and make results look better.
+        // Divide by 254 instead of 255, and change -128 to -127 elsewhere.
+        bSigned = true;
+        lowestX = -128.0;
+    }
+    else
+    {
+        bSigned = false;
+        lowestX = 0.0;
+    }
+
+    // Step 1: Set y to (max - min), set x to 255, set B to 0, solve for M
+    // This works, regardless of signed or unsigned,
+    // because total range is the same.
+    double dM = fullRange / 255.0;
+
+    // Step 2: Constrain M, and set rExp accordingly
+    if (!(scaleFloatExp(dM, rExp)))
+    {
+        std::cerr << "getSensorAttributes: Multiplier range exceeds scale (M="
+                  << dM << ", rExp=" << (int)rExp << ")\n";
+        return false;
+    }
+
+    mValue = static_cast<int16_t>(std::round(dM));
+
+    normalizeIntExp(mValue, rExp, dM);
+
+    // The multiplier can not be zero, for obvious reasons
+    if (mValue == 0)
+    {
+        std::cerr << "getSensorAttributes: Multiplier range below scale\n";
+        return false;
+    }
+
+    // Step 3: set y to min, set x to min, keep M and rExp, solve for B
+    // If negative, x will be -128 (the most negative possible byte), not 0
+
+    // Solve the IPMI equation for B, instead of y
+    // https://www.wolframalpha.com/input/?i=solve+y%3D%28%28M*x%29%2B%28B*%2810%5EE%29%29%29*%2810%5ER%29+for+B
+    // B = 10^(-rExp - bExp) (y - M 10^rExp x)
+    // TODO(): Compare with this alternative solution from SageMathCell
+    // https://sagecell.sagemath.org/?z=eJyrtC1LLNJQr1TX5KqAMCuATF8I0xfIdIIwnYDMIteKAggPxAIKJMEFkiACxfk5Zaka0ZUKtrYKGhq-CloKFZoK2goaTkCWhqGBgpaWAkilpqYmQgBklmasjoKTJgDAECTH&lang=sage&interacts=eJyLjgUAARUAuQ==
+    double dB = std::pow(10.0, ((-rExp) - bExp)) *
+                (min - ((dM * std::pow(10.0, rExp) * lowestX)));
+
+    // Step 4: Constrain B, and set bExp accordingly
+    if (!(scaleFloatExp(dB, bExp)))
+    {
+        std::cerr << "getSensorAttributes: Offset (B=" << dB
+                  << ", bExp=" << (int)bExp
+                  << ") exceeds multiplier scale (M=" << dM
+                  << ", rExp=" << (int)rExp << ")\n";
+        return false;
+    }
+
+    bValue = static_cast<int16_t>(std::round(dB));
+
+    normalizeIntExp(bValue, bExp, dB);
+
+    // Unlike the multiplier, it is perfectly OK for bValue to be zero
+    return true;
+}
+
+uint8_t scaleIPMIValueFromDouble(const double value, const int16_t mValue,
+                                 const int8_t rExp, const int16_t bValue,
+                                 const int8_t bExp, const bool bSigned)
+{
+    // Avoid division by zero below
+    if (mValue == 0)
+    {
+        throw std::out_of_range("Scaling multiplier is uninitialized");
+    }
+
+    auto dM = static_cast<double>(mValue);
+    auto dB = static_cast<double>(bValue);
+
+    // Solve the IPMI equation for x, instead of y
+    // https://www.wolframalpha.com/input/?i=solve+y%3D%28%28M*x%29%2B%28B*%2810%5EE%29%29%29*%2810%5ER%29+for+x
+    // x = (10^(-rExp) (y - B 10^(rExp + bExp)))/M and M 10^rExp!=0
+    // TODO(): Compare with this alternative solution from SageMathCell
+    // https://sagecell.sagemath.org/?z=eJyrtC1LLNJQr1TX5KqAMCuATF8I0xfIdIIwnYDMIteKAggPxAIKJMEFkiACxfk5Zaka0ZUKtrYKGhq-CloKFZoK2goaTkCWhqGBgpaWAkilpqYmQgBklmasDlAlAMB8JP0=&lang=sage&interacts=eJyLjgUAARUAuQ==
+    double dX =
+        (std::pow(10.0, -rExp) * (value - (dB * std::pow(10.0, rExp + bExp)))) /
+        dM;
+
+    auto scaledValue = static_cast<int32_t>(std::round(dX));
+
+    int32_t minClamp;
+    int32_t maxClamp;
+
+    // Because of rounding and integer truncation of scaling factors,
+    // sometimes the resulting byte is slightly out of range.
+    // Still allow this, but clamp the values to range.
+    if (bSigned)
+    {
+        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();
+    }
+
+    auto clampedValue = std::clamp(scaledValue, minClamp, maxClamp);
+
+    // This works for both signed and unsigned,
+    // because it is the same underlying byte storage.
+    return static_cast<uint8_t>(clampedValue);
+}
+
+uint8_t getScaledIPMIValue(const double value, const double max,
+                           const double min)
+{
+    int16_t mValue = 0;
+    int8_t rExp = 0;
+    int16_t bValue = 0;
+    int8_t bExp = 0;
+    bool bSigned = false;
+
+    bool result =
+        getSensorAttributes(max, min, mValue, rExp, bValue, bExp, bSigned);
+    if (!result)
+    {
+        throw std::runtime_error("Illegal sensor attributes");
+    }
+
+    return scaleIPMIValueFromDouble(value, mValue, rExp, bValue, bExp, bSigned);
+}
+
+} // namespace ipmi
diff --git a/dbus-sdr/storagecommands.cpp b/dbus-sdr/storagecommands.cpp
new file mode 100644
index 0000000..5926615
--- /dev/null
+++ b/dbus-sdr/storagecommands.cpp
@@ -0,0 +1,1293 @@
+/*
+// Copyright (c) 2017-2019 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include "dbus-sdr/storagecommands.hpp"
+
+#include "dbus-sdr/sdrutils.hpp"
+#include "selutility.hpp"
+
+#include <boost/algorithm/string.hpp>
+#include <boost/container/flat_map.hpp>
+#include <boost/process.hpp>
+#include <filesystem>
+#include <functional>
+#include <iostream>
+#include <ipmid/api.hpp>
+#include <ipmid/message.hpp>
+#include <ipmid/types.hpp>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/message/types.hpp>
+#include <sdbusplus/timer.hpp>
+#include <stdexcept>
+#include <string_view>
+
+static constexpr bool DEBUG = false;
+
+namespace dynamic_sensors::ipmi::sel
+{
+static const std::filesystem::path selLogDir = "/var/log";
+static const std::string selLogFilename = "ipmi_sel";
+
+static int getFileTimestamp(const std::filesystem::path& file)
+{
+    struct stat st;
+
+    if (stat(file.c_str(), &st) >= 0)
+    {
+        return st.st_mtime;
+    }
+    return ::ipmi::sel::invalidTimeStamp;
+}
+
+namespace erase_time
+{
+static constexpr const char* selEraseTimestamp = "/var/lib/ipmi/sel_erase_time";
+
+void save()
+{
+    // open the file, creating it if necessary
+    int fd = open(selEraseTimestamp, O_WRONLY | O_CREAT | O_CLOEXEC, 0644);
+    if (fd < 0)
+    {
+        std::cerr << "Failed to open file\n";
+        return;
+    }
+
+    // update the file timestamp to the current time
+    if (futimens(fd, NULL) < 0)
+    {
+        std::cerr << "Failed to update timestamp: "
+                  << std::string(strerror(errno));
+    }
+    close(fd);
+}
+
+int get()
+{
+    return getFileTimestamp(selEraseTimestamp);
+}
+} // namespace erase_time
+} // namespace dynamic_sensors::ipmi::sel
+
+namespace ipmi
+{
+
+namespace storage
+{
+
+constexpr static const size_t maxMessageSize = 64;
+constexpr static const size_t maxFruSdrNameSize = 16;
+using ObjectType =
+    boost::container::flat_map<std::string,
+                               boost::container::flat_map<std::string, Value>>;
+using ManagedObjectType =
+    boost::container::flat_map<sdbusplus::message::object_path, ObjectType>;
+using ManagedEntry = std::pair<sdbusplus::message::object_path, ObjectType>;
+
+constexpr static const char* fruDeviceServiceName =
+    "xyz.openbmc_project.FruDevice";
+constexpr static const char* entityManagerServiceName =
+    "xyz.openbmc_project.EntityManager";
+constexpr static const size_t writeTimeoutSeconds = 10;
+constexpr static const char* chassisTypeRackMount = "23";
+
+// event direction is bit[7] of eventType where 1b = Deassertion event
+constexpr static const uint8_t deassertionEvent = 0x80;
+
+static std::vector<uint8_t> fruCache;
+static uint8_t cacheBus = 0xFF;
+static uint8_t cacheAddr = 0XFF;
+static uint8_t lastDevId = 0xFF;
+
+static uint8_t writeBus = 0xFF;
+static uint8_t writeAddr = 0XFF;
+
+std::unique_ptr<phosphor::Timer> writeTimer = nullptr;
+static std::vector<sdbusplus::bus::match::match> fruMatches;
+
+ManagedObjectType frus;
+
+// we unfortunately have to build a map of hashes in case there is a
+// collision to verify our dev-id
+boost::container::flat_map<uint8_t, std::pair<uint8_t, uint8_t>> deviceHashes;
+
+void registerStorageFunctions() __attribute__((constructor));
+
+bool writeFru()
+{
+    if (writeBus == 0xFF && writeAddr == 0xFF)
+    {
+        return true;
+    }
+    std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
+    sdbusplus::message::message writeFru = dbus->new_method_call(
+        fruDeviceServiceName, "/xyz/openbmc_project/FruDevice",
+        "xyz.openbmc_project.FruDeviceManager", "WriteFru");
+    writeFru.append(writeBus, writeAddr, fruCache);
+    try
+    {
+        sdbusplus::message::message writeFruResp = dbus->call(writeFru);
+    }
+    catch (sdbusplus::exception_t&)
+    {
+        // todo: log sel?
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "error writing fru");
+        return false;
+    }
+    writeBus = 0xFF;
+    writeAddr = 0xFF;
+    return true;
+}
+
+void createTimers()
+{
+    writeTimer = std::make_unique<phosphor::Timer>(writeFru);
+}
+
+void recalculateHashes()
+{
+
+    deviceHashes.clear();
+    // hash the object paths to create unique device id's. increment on
+    // collision
+    std::hash<std::string> hasher;
+    for (const auto& fru : frus)
+    {
+        auto fruIface = fru.second.find("xyz.openbmc_project.FruDevice");
+        if (fruIface == fru.second.end())
+        {
+            continue;
+        }
+
+        auto busFind = fruIface->second.find("BUS");
+        auto addrFind = fruIface->second.find("ADDRESS");
+        if (busFind == fruIface->second.end() ||
+            addrFind == fruIface->second.end())
+        {
+            phosphor::logging::log<phosphor::logging::level::INFO>(
+                "fru device missing Bus or Address",
+                phosphor::logging::entry("FRU=%s", fru.first.str.c_str()));
+            continue;
+        }
+
+        uint8_t fruBus = std::get<uint32_t>(busFind->second);
+        uint8_t fruAddr = std::get<uint32_t>(addrFind->second);
+        auto chassisFind = fruIface->second.find("CHASSIS_TYPE");
+        std::string chassisType;
+        if (chassisFind != fruIface->second.end())
+        {
+            chassisType = std::get<std::string>(chassisFind->second);
+        }
+
+        uint8_t fruHash = 0;
+        if (chassisType.compare(chassisTypeRackMount) != 0)
+        {
+            fruHash = hasher(fru.first.str);
+            // can't be 0xFF based on spec, and 0 is reserved for baseboard
+            if (fruHash == 0 || fruHash == 0xFF)
+            {
+                fruHash = 1;
+            }
+        }
+        std::pair<uint8_t, uint8_t> newDev(fruBus, fruAddr);
+
+        bool emplacePassed = false;
+        while (!emplacePassed)
+        {
+            auto resp = deviceHashes.emplace(fruHash, newDev);
+            emplacePassed = resp.second;
+            if (!emplacePassed)
+            {
+                fruHash++;
+                // can't be 0xFF based on spec, and 0 is reserved for
+                // baseboard
+                if (fruHash == 0XFF)
+                {
+                    fruHash = 0x1;
+                }
+            }
+        }
+    }
+}
+
+void replaceCacheFru(const std::shared_ptr<sdbusplus::asio::connection>& bus,
+                     boost::asio::yield_context& yield,
+                     const std::optional<std::string>& path = std::nullopt)
+{
+    boost::system::error_code ec;
+
+    frus = bus->yield_method_call<ManagedObjectType>(
+        yield, ec, fruDeviceServiceName, "/",
+        "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+    if (ec)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "GetMangagedObjects for replaceCacheFru failed",
+            phosphor::logging::entry("ERROR=%s", ec.message().c_str()));
+
+        return;
+    }
+    recalculateHashes();
+}
+
+ipmi::Cc getFru(ipmi::Context::ptr ctx, uint8_t devId)
+{
+    if (lastDevId == devId && devId != 0xFF)
+    {
+        return ipmi::ccSuccess;
+    }
+
+    // Set devId to 1 if devId is 0.
+    // 0 is reserved for baseboard and set to 1 in recalculateHashes().
+    if (!devId)
+        devId = 1;
+
+    auto deviceFind = deviceHashes.find(devId);
+    if (deviceFind == deviceHashes.end())
+    {
+        return IPMI_CC_SENSOR_INVALID;
+    }
+
+    fruCache.clear();
+
+    cacheBus = deviceFind->second.first;
+    cacheAddr = deviceFind->second.second;
+
+    boost::system::error_code ec;
+
+    fruCache = ctx->bus->yield_method_call<std::vector<uint8_t>>(
+        ctx->yield, ec, fruDeviceServiceName, "/xyz/openbmc_project/FruDevice",
+        "xyz.openbmc_project.FruDeviceManager", "GetRawFru", cacheBus,
+        cacheAddr);
+    if (ec)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Couldn't get raw fru",
+            phosphor::logging::entry("ERROR=%s", ec.message().c_str()));
+
+        cacheBus = 0xFF;
+        cacheAddr = 0xFF;
+        return ipmi::ccResponseError;
+    }
+
+    lastDevId = devId;
+    return ipmi::ccSuccess;
+}
+
+void writeFruIfRunning()
+{
+    if (!writeTimer->isRunning())
+    {
+        return;
+    }
+    writeTimer->stop();
+    writeFru();
+}
+
+void startMatch(void)
+{
+    if (fruMatches.size())
+    {
+        return;
+    }
+
+    fruMatches.reserve(2);
+
+    auto bus = getSdBus();
+    fruMatches.emplace_back(*bus,
+                            "type='signal',arg0path='/xyz/openbmc_project/"
+                            "FruDevice/',member='InterfacesAdded'",
+                            [](sdbusplus::message::message& message) {
+                                sdbusplus::message::object_path path;
+                                ObjectType object;
+                                try
+                                {
+                                    message.read(path, object);
+                                }
+                                catch (sdbusplus::exception_t&)
+                                {
+                                    return;
+                                }
+                                auto findType = object.find(
+                                    "xyz.openbmc_project.FruDevice");
+                                if (findType == object.end())
+                                {
+                                    return;
+                                }
+                                writeFruIfRunning();
+                                frus[path] = object;
+                                recalculateHashes();
+                                lastDevId = 0xFF;
+                            });
+
+    fruMatches.emplace_back(*bus,
+                            "type='signal',arg0path='/xyz/openbmc_project/"
+                            "FruDevice/',member='InterfacesRemoved'",
+                            [](sdbusplus::message::message& message) {
+                                sdbusplus::message::object_path path;
+                                std::set<std::string> interfaces;
+                                try
+                                {
+                                    message.read(path, interfaces);
+                                }
+                                catch (sdbusplus::exception_t&)
+                                {
+                                    return;
+                                }
+                                auto findType = interfaces.find(
+                                    "xyz.openbmc_project.FruDevice");
+                                if (findType == interfaces.end())
+                                {
+                                    return;
+                                }
+                                writeFruIfRunning();
+                                frus.erase(path);
+                                recalculateHashes();
+                                lastDevId = 0xFF;
+                            });
+
+    // call once to populate
+    boost::asio::spawn(*getIoContext(), [](boost::asio::yield_context yield) {
+        replaceCacheFru(getSdBus(), yield);
+    });
+}
+
+/** @brief implements the read FRU data command
+ *  @param fruDeviceId        - FRU Device ID
+ *  @param fruInventoryOffset - FRU Inventory Offset to write
+ *  @param countToRead        - Count to read
+ *
+ *  @returns ipmi completion code plus response data
+ *   - countWritten  - Count written
+ */
+ipmi::RspType<uint8_t,             // Count
+              std::vector<uint8_t> // Requested data
+              >
+    ipmiStorageReadFruData(ipmi::Context::ptr ctx, uint8_t fruDeviceId,
+                           uint16_t fruInventoryOffset, uint8_t countToRead)
+{
+    if (fruDeviceId == 0xFF)
+    {
+        return ipmi::responseInvalidFieldRequest();
+    }
+
+    ipmi::Cc status = getFru(ctx, fruDeviceId);
+
+    if (status != ipmi::ccSuccess)
+    {
+        return ipmi::response(status);
+    }
+
+    size_t fromFruByteLen = 0;
+    if (countToRead + fruInventoryOffset < fruCache.size())
+    {
+        fromFruByteLen = countToRead;
+    }
+    else if (fruCache.size() > fruInventoryOffset)
+    {
+        fromFruByteLen = fruCache.size() - fruInventoryOffset;
+    }
+    else
+    {
+        return ipmi::responseReqDataLenExceeded();
+    }
+
+    std::vector<uint8_t> requestedData;
+
+    requestedData.insert(
+        requestedData.begin(), fruCache.begin() + fruInventoryOffset,
+        fruCache.begin() + fruInventoryOffset + fromFruByteLen);
+
+    return ipmi::responseSuccess(static_cast<uint8_t>(requestedData.size()),
+                                 requestedData);
+}
+
+/** @brief implements the write FRU data command
+ *  @param fruDeviceId        - FRU Device ID
+ *  @param fruInventoryOffset - FRU Inventory Offset to write
+ *  @param dataToWrite        - Data to write
+ *
+ *  @returns ipmi completion code plus response data
+ *   - countWritten  - Count written
+ */
+ipmi::RspType<uint8_t>
+    ipmiStorageWriteFruData(ipmi::Context::ptr ctx, uint8_t fruDeviceId,
+                            uint16_t fruInventoryOffset,
+                            std::vector<uint8_t>& dataToWrite)
+{
+    if (fruDeviceId == 0xFF)
+    {
+        return ipmi::responseInvalidFieldRequest();
+    }
+
+    size_t writeLen = dataToWrite.size();
+
+    ipmi::Cc status = getFru(ctx, fruDeviceId);
+    if (status != ipmi::ccSuccess)
+    {
+        return ipmi::response(status);
+    }
+    size_t lastWriteAddr = fruInventoryOffset + writeLen;
+    if (fruCache.size() < lastWriteAddr)
+    {
+        fruCache.resize(fruInventoryOffset + writeLen);
+    }
+
+    std::copy(dataToWrite.begin(), dataToWrite.begin() + writeLen,
+              fruCache.begin() + fruInventoryOffset);
+
+    bool atEnd = false;
+
+    if (fruCache.size() >= sizeof(FRUHeader))
+    {
+        FRUHeader* header = reinterpret_cast<FRUHeader*>(fruCache.data());
+
+        size_t areaLength = 0;
+        size_t lastRecordStart = std::max(
+            {header->internalOffset, header->chassisOffset, header->boardOffset,
+             header->productOffset, header->multiRecordOffset});
+        lastRecordStart *= 8; // header starts in are multiples of 8 bytes
+
+        if (header->multiRecordOffset)
+        {
+            // This FRU has a MultiRecord Area
+            uint8_t endOfList = 0;
+            // Walk the MultiRecord headers until the last record
+            while (!endOfList)
+            {
+                // The MSB in the second byte of the MultiRecord header signals
+                // "End of list"
+                endOfList = fruCache[lastRecordStart + 1] & 0x80;
+                // Third byte in the MultiRecord header is the length
+                areaLength = fruCache[lastRecordStart + 2];
+                // This length is in bytes (not 8 bytes like other headers)
+                areaLength += 5; // The length omits the 5 byte header
+                if (!endOfList)
+                {
+                    // Next MultiRecord header
+                    lastRecordStart += areaLength;
+                }
+            }
+        }
+        else
+        {
+            // This FRU does not have a MultiRecord Area
+            // Get the length of the area in multiples of 8 bytes
+            if (lastWriteAddr > (lastRecordStart + 1))
+            {
+                // second byte in record area is the length
+                areaLength = fruCache[lastRecordStart + 1];
+                areaLength *= 8; // it is in multiples of 8 bytes
+            }
+        }
+        if (lastWriteAddr >= (areaLength + lastRecordStart))
+        {
+            atEnd = true;
+        }
+    }
+    uint8_t countWritten = 0;
+
+    writeBus = cacheBus;
+    writeAddr = cacheAddr;
+    if (atEnd)
+    {
+        // cancel timer, we're at the end so might as well send it
+        writeTimer->stop();
+        if (!writeFru())
+        {
+            return ipmi::responseInvalidFieldRequest();
+        }
+        countWritten = std::min(fruCache.size(), static_cast<size_t>(0xFF));
+    }
+    else
+    {
+        // start a timer, if no further data is sent  to check to see if it is
+        // valid
+        writeTimer->start(std::chrono::duration_cast<std::chrono::microseconds>(
+            std::chrono::seconds(writeTimeoutSeconds)));
+        countWritten = 0;
+    }
+
+    return ipmi::responseSuccess(countWritten);
+}
+
+/** @brief implements the get FRU inventory area info command
+ *  @param fruDeviceId  - FRU Device ID
+ *
+ *  @returns IPMI completion code plus response data
+ *   - inventorySize - Number of possible allocation units
+ *   - accessType    - Allocation unit size in bytes.
+ */
+ipmi::RspType<uint16_t, // inventorySize
+              uint8_t>  // accessType
+    ipmiStorageGetFruInvAreaInfo(ipmi::Context::ptr ctx, uint8_t fruDeviceId)
+{
+    if (fruDeviceId == 0xFF)
+    {
+        return ipmi::responseInvalidFieldRequest();
+    }
+
+    ipmi::Cc ret = getFru(ctx, fruDeviceId);
+    if (ret != ipmi::ccSuccess)
+    {
+        return ipmi::response(ret);
+    }
+
+    constexpr uint8_t accessType =
+        static_cast<uint8_t>(GetFRUAreaAccessType::byte);
+
+    return ipmi::responseSuccess(fruCache.size(), accessType);
+}
+
+ipmi_ret_t getFruSdrCount(ipmi::Context::ptr ctx, size_t& count)
+{
+    count = deviceHashes.size();
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t getFruSdrs(ipmi::Context::ptr ctx, size_t index,
+                      get_sdr::SensorDataFruRecord& resp)
+{
+    if (deviceHashes.size() < index)
+    {
+        return IPMI_CC_INVALID_FIELD_REQUEST;
+    }
+    auto device = deviceHashes.begin() + index;
+    uint8_t& bus = device->second.first;
+    uint8_t& address = device->second.second;
+
+    boost::container::flat_map<std::string, Value>* fruData = nullptr;
+    auto fru =
+        std::find_if(frus.begin(), frus.end(),
+                     [bus, address, &fruData](ManagedEntry& entry) {
+                         auto findFruDevice =
+                             entry.second.find("xyz.openbmc_project.FruDevice");
+                         if (findFruDevice == entry.second.end())
+                         {
+                             return false;
+                         }
+                         fruData = &(findFruDevice->second);
+                         auto findBus = findFruDevice->second.find("BUS");
+                         auto findAddress =
+                             findFruDevice->second.find("ADDRESS");
+                         if (findBus == findFruDevice->second.end() ||
+                             findAddress == findFruDevice->second.end())
+                         {
+                             return false;
+                         }
+                         if (std::get<uint32_t>(findBus->second) != bus)
+                         {
+                             return false;
+                         }
+                         if (std::get<uint32_t>(findAddress->second) != address)
+                         {
+                             return false;
+                         }
+                         return true;
+                     });
+    if (fru == frus.end())
+    {
+        return IPMI_CC_RESPONSE_ERROR;
+    }
+
+#ifdef USING_ENTITY_MANAGER_DECORATORS
+
+    boost::container::flat_map<std::string, Value>* entityData = nullptr;
+
+    // todo: this should really use caching, this is a very inefficient lookup
+    boost::system::error_code ec;
+    ManagedObjectType entities = ctx->bus->yield_method_call<ManagedObjectType>(
+        ctx->yield, ec, entityManagerServiceName, "/",
+        "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+
+    if (ec)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "GetMangagedObjects for ipmiStorageGetFruInvAreaInfo failed",
+            phosphor::logging::entry("ERROR=%s", ec.message().c_str()));
+
+        return ipmi::ccResponseError;
+    }
+
+    auto entity = std::find_if(
+        entities.begin(), entities.end(),
+        [bus, address, &entityData](ManagedEntry& entry) {
+            auto findFruDevice = entry.second.find(
+                "xyz.openbmc_project.Inventory.Decorator.FruDevice");
+            if (findFruDevice == entry.second.end())
+            {
+                return false;
+            }
+
+            // Integer fields added via Entity-Manager json are uint64_ts by
+            // default.
+            auto findBus = findFruDevice->second.find("Bus");
+            auto findAddress = findFruDevice->second.find("Address");
+
+            if (findBus == findFruDevice->second.end() ||
+                findAddress == findFruDevice->second.end())
+            {
+                return false;
+            }
+            if ((std::get<uint64_t>(findBus->second) != bus) ||
+                (std::get<uint64_t>(findAddress->second) != address))
+            {
+                return false;
+            }
+
+            // At this point we found the device entry and should return
+            // true.
+            auto findIpmiDevice = entry.second.find(
+                "xyz.openbmc_project.Inventory.Decorator.Ipmi");
+            if (findIpmiDevice != entry.second.end())
+            {
+                entityData = &(findIpmiDevice->second);
+            }
+
+            return true;
+        });
+
+    if (entity == entities.end())
+    {
+        if constexpr (DEBUG)
+        {
+            std::fprintf(stderr, "Ipmi or FruDevice Decorator interface "
+                                 "not found for Fru\n");
+        }
+    }
+
+#endif
+
+    std::string name;
+    auto findProductName = fruData->find("BOARD_PRODUCT_NAME");
+    auto findBoardName = fruData->find("PRODUCT_PRODUCT_NAME");
+    if (findProductName != fruData->end())
+    {
+        name = std::get<std::string>(findProductName->second);
+    }
+    else if (findBoardName != fruData->end())
+    {
+        name = std::get<std::string>(findBoardName->second);
+    }
+    else
+    {
+        name = "UNKNOWN";
+    }
+    if (name.size() > maxFruSdrNameSize)
+    {
+        name = name.substr(0, maxFruSdrNameSize);
+    }
+    size_t sizeDiff = maxFruSdrNameSize - name.size();
+
+    resp.header.record_id_lsb = 0x0; // calling code is to implement these
+    resp.header.record_id_msb = 0x0;
+    resp.header.sdr_version = ipmiSdrVersion;
+    resp.header.record_type = get_sdr::SENSOR_DATA_FRU_RECORD;
+    resp.header.record_length = sizeof(resp.body) + sizeof(resp.key) - sizeDiff;
+    resp.key.deviceAddress = 0x20;
+    resp.key.fruID = device->first;
+    resp.key.accessLun = 0x80; // logical / physical fru device
+    resp.key.channelNumber = 0x0;
+    resp.body.reserved = 0x0;
+    resp.body.deviceType = 0x10;
+    resp.body.deviceTypeModifier = 0x0;
+
+    uint8_t entityID = 0;
+    uint8_t entityInstance = 0x1;
+
+#ifdef USING_ENTITY_MANAGER_DECORATORS
+    if (entityData)
+    {
+        auto entityIdProperty = entityData->find("EntityId");
+        auto entityInstanceProperty = entityData->find("EntityInstance");
+
+        if (entityIdProperty != entityData->end())
+        {
+            entityID = static_cast<uint8_t>(
+                std::get<uint64_t>(entityIdProperty->second));
+        }
+        if (entityInstanceProperty != entityData->end())
+        {
+            entityInstance = static_cast<uint8_t>(
+                std::get<uint64_t>(entityInstanceProperty->second));
+        }
+    }
+#endif
+
+    resp.body.entityID = entityID;
+    resp.body.entityInstance = entityInstance;
+
+    resp.body.oem = 0x0;
+    resp.body.deviceIDLen = name.size();
+    name.copy(resp.body.deviceID, name.size());
+
+    return IPMI_CC_OK;
+}
+
+static bool getSELLogFiles(std::vector<std::filesystem::path>& selLogFiles)
+{
+    // Loop through the directory looking for ipmi_sel log files
+    for (const std::filesystem::directory_entry& dirEnt :
+         std::filesystem::directory_iterator(
+             dynamic_sensors::ipmi::sel::selLogDir))
+    {
+        std::string filename = dirEnt.path().filename();
+        if (boost::starts_with(filename,
+                               dynamic_sensors::ipmi::sel::selLogFilename))
+        {
+            // If we find an ipmi_sel log file, save the path
+            selLogFiles.emplace_back(dynamic_sensors::ipmi::sel::selLogDir /
+                                     filename);
+        }
+    }
+    // As the log files rotate, they are appended with a ".#" that is higher for
+    // the older logs. Since we don't expect more than 10 log files, we
+    // can just sort the list to get them in order from newest to oldest
+    std::sort(selLogFiles.begin(), selLogFiles.end());
+
+    return !selLogFiles.empty();
+}
+
+static int countSELEntries()
+{
+    // Get the list of ipmi_sel log files
+    std::vector<std::filesystem::path> selLogFiles;
+    if (!getSELLogFiles(selLogFiles))
+    {
+        return 0;
+    }
+    int numSELEntries = 0;
+    // Loop through each log file and count the number of logs
+    for (const std::filesystem::path& file : selLogFiles)
+    {
+        std::ifstream logStream(file);
+        if (!logStream.is_open())
+        {
+            continue;
+        }
+
+        std::string line;
+        while (std::getline(logStream, line))
+        {
+            numSELEntries++;
+        }
+    }
+    return numSELEntries;
+}
+
+static bool findSELEntry(const int recordID,
+                         const std::vector<std::filesystem::path>& selLogFiles,
+                         std::string& entry)
+{
+    // Record ID is the first entry field following the timestamp. It is
+    // preceded by a space and followed by a comma
+    std::string search = " " + std::to_string(recordID) + ",";
+
+    // Loop through the ipmi_sel log entries
+    for (const std::filesystem::path& file : selLogFiles)
+    {
+        std::ifstream logStream(file);
+        if (!logStream.is_open())
+        {
+            continue;
+        }
+
+        while (std::getline(logStream, entry))
+        {
+            // Check if the record ID matches
+            if (entry.find(search) != std::string::npos)
+            {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+static uint16_t
+    getNextRecordID(const uint16_t recordID,
+                    const std::vector<std::filesystem::path>& selLogFiles)
+{
+    uint16_t nextRecordID = recordID + 1;
+    std::string entry;
+    if (findSELEntry(nextRecordID, selLogFiles, entry))
+    {
+        return nextRecordID;
+    }
+    else
+    {
+        return ipmi::sel::lastEntry;
+    }
+}
+
+static int fromHexStr(const std::string& hexStr, std::vector<uint8_t>& data)
+{
+    for (unsigned int i = 0; i < hexStr.size(); i += 2)
+    {
+        try
+        {
+            data.push_back(static_cast<uint8_t>(
+                std::stoul(hexStr.substr(i, 2), nullptr, 16)));
+        }
+        catch (std::invalid_argument& e)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
+            return -1;
+        }
+        catch (std::out_of_range& e)
+        {
+            phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
+            return -1;
+        }
+    }
+    return 0;
+}
+
+ipmi::RspType<uint8_t,  // SEL version
+              uint16_t, // SEL entry count
+              uint16_t, // free space
+              uint32_t, // last add timestamp
+              uint32_t, // last erase timestamp
+              uint8_t>  // operation support
+    ipmiStorageGetSELInfo()
+{
+    constexpr uint8_t selVersion = ipmi::sel::selVersion;
+    uint16_t entries = countSELEntries();
+    uint32_t addTimeStamp = dynamic_sensors::ipmi::sel::getFileTimestamp(
+        dynamic_sensors::ipmi::sel::selLogDir /
+        dynamic_sensors::ipmi::sel::selLogFilename);
+    uint32_t eraseTimeStamp = dynamic_sensors::ipmi::sel::erase_time::get();
+    constexpr uint8_t operationSupport =
+        dynamic_sensors::ipmi::sel::selOperationSupport;
+    constexpr uint16_t freeSpace =
+        0xffff; // Spec indicates that more than 64kB is free
+
+    return ipmi::responseSuccess(selVersion, entries, freeSpace, addTimeStamp,
+                                 eraseTimeStamp, operationSupport);
+}
+
+using systemEventType = std::tuple<
+    uint32_t, // Timestamp
+    uint16_t, // Generator ID
+    uint8_t,  // EvM Rev
+    uint8_t,  // Sensor Type
+    uint8_t,  // Sensor Number
+    uint7_t,  // Event Type
+    bool,     // Event Direction
+    std::array<uint8_t, dynamic_sensors::ipmi::sel::systemEventSize>>; // Event
+                                                                       // Data
+using oemTsEventType = std::tuple<
+    uint32_t, // Timestamp
+    std::array<uint8_t, dynamic_sensors::ipmi::sel::oemTsEventSize>>; // Event
+                                                                      // Data
+using oemEventType =
+    std::array<uint8_t, dynamic_sensors::ipmi::sel::oemEventSize>; // Event Data
+
+ipmi::RspType<uint16_t, // Next Record ID
+              uint16_t, // Record ID
+              uint8_t,  // Record Type
+              std::variant<systemEventType, oemTsEventType,
+                           oemEventType>> // Record Content
+    ipmiStorageGetSELEntry(uint16_t reservationID, uint16_t targetID,
+                           uint8_t offset, uint8_t size)
+{
+    // Only support getting the entire SEL record. If a partial size or non-zero
+    // offset is requested, return an error
+    if (offset != 0 || size != ipmi::sel::entireRecord)
+    {
+        return ipmi::responseRetBytesUnavailable();
+    }
+
+    // Check the reservation ID if one is provided or required (only if the
+    // offset is non-zero)
+    if (reservationID != 0 || offset != 0)
+    {
+        if (!checkSELReservation(reservationID))
+        {
+            return ipmi::responseInvalidReservationId();
+        }
+    }
+
+    // Get the ipmi_sel log files
+    std::vector<std::filesystem::path> selLogFiles;
+    if (!getSELLogFiles(selLogFiles))
+    {
+        return ipmi::responseSensorInvalid();
+    }
+
+    std::string targetEntry;
+
+    if (targetID == ipmi::sel::firstEntry)
+    {
+        // The first entry will be at the top of the oldest log file
+        std::ifstream logStream(selLogFiles.back());
+        if (!logStream.is_open())
+        {
+            return ipmi::responseUnspecifiedError();
+        }
+
+        if (!std::getline(logStream, targetEntry))
+        {
+            return ipmi::responseUnspecifiedError();
+        }
+    }
+    else if (targetID == ipmi::sel::lastEntry)
+    {
+        // The last entry will be at the bottom of the newest log file
+        std::ifstream logStream(selLogFiles.front());
+        if (!logStream.is_open())
+        {
+            return ipmi::responseUnspecifiedError();
+        }
+
+        std::string line;
+        while (std::getline(logStream, line))
+        {
+            targetEntry = line;
+        }
+    }
+    else
+    {
+        if (!findSELEntry(targetID, selLogFiles, targetEntry))
+        {
+            return ipmi::responseSensorInvalid();
+        }
+    }
+
+    // The format of the ipmi_sel message is "<Timestamp>
+    // <ID>,<Type>,<EventData>,[<Generator ID>,<Path>,<Direction>]".
+    // First get the Timestamp
+    size_t space = targetEntry.find_first_of(" ");
+    if (space == std::string::npos)
+    {
+        return ipmi::responseUnspecifiedError();
+    }
+    std::string entryTimestamp = targetEntry.substr(0, space);
+    // Then get the log contents
+    size_t entryStart = targetEntry.find_first_not_of(" ", space);
+    if (entryStart == std::string::npos)
+    {
+        return ipmi::responseUnspecifiedError();
+    }
+    std::string_view entry(targetEntry);
+    entry.remove_prefix(entryStart);
+    // Use split to separate the entry into its fields
+    std::vector<std::string> targetEntryFields;
+    boost::split(targetEntryFields, entry, boost::is_any_of(","),
+                 boost::token_compress_on);
+    if (targetEntryFields.size() < 3)
+    {
+        return ipmi::responseUnspecifiedError();
+    }
+    std::string& recordIDStr = targetEntryFields[0];
+    std::string& recordTypeStr = targetEntryFields[1];
+    std::string& eventDataStr = targetEntryFields[2];
+
+    uint16_t recordID;
+    uint8_t recordType;
+    try
+    {
+        recordID = std::stoul(recordIDStr);
+        recordType = std::stoul(recordTypeStr, nullptr, 16);
+    }
+    catch (const std::invalid_argument&)
+    {
+        return ipmi::responseUnspecifiedError();
+    }
+    uint16_t nextRecordID = getNextRecordID(recordID, selLogFiles);
+    std::vector<uint8_t> eventDataBytes;
+    if (fromHexStr(eventDataStr, eventDataBytes) < 0)
+    {
+        return ipmi::responseUnspecifiedError();
+    }
+
+    if (recordType == dynamic_sensors::ipmi::sel::systemEvent)
+    {
+        // Get the timestamp
+        std::tm timeStruct = {};
+        std::istringstream entryStream(entryTimestamp);
+
+        uint32_t timestamp = ipmi::sel::invalidTimeStamp;
+        if (entryStream >> std::get_time(&timeStruct, "%Y-%m-%dT%H:%M:%S"))
+        {
+            timestamp = std::mktime(&timeStruct);
+        }
+
+        // Set the event message revision
+        uint8_t evmRev = dynamic_sensors::ipmi::sel::eventMsgRev;
+
+        uint16_t generatorID = 0;
+        uint8_t sensorType = 0;
+        uint16_t sensorAndLun = 0;
+        uint8_t sensorNum = 0xFF;
+        uint7_t eventType = 0;
+        bool eventDir = 0;
+        // System type events should have six fields
+        if (targetEntryFields.size() >= 6)
+        {
+            std::string& generatorIDStr = targetEntryFields[3];
+            std::string& sensorPath = targetEntryFields[4];
+            std::string& eventDirStr = targetEntryFields[5];
+
+            // Get the generator ID
+            try
+            {
+                generatorID = std::stoul(generatorIDStr, nullptr, 16);
+            }
+            catch (const std::invalid_argument&)
+            {
+                std::cerr << "Invalid Generator ID\n";
+            }
+
+            // Get the sensor type, sensor number, and event type for the sensor
+            sensorType = getSensorTypeFromPath(sensorPath);
+            sensorAndLun = getSensorNumberFromPath(sensorPath);
+            sensorNum = static_cast<uint8_t>(sensorAndLun);
+            generatorID |= sensorAndLun >> 8;
+            eventType = getSensorEventTypeFromPath(sensorPath);
+
+            // Get the event direction
+            try
+            {
+                eventDir = std::stoul(eventDirStr) ? 0 : 1;
+            }
+            catch (const std::invalid_argument&)
+            {
+                std::cerr << "Invalid Event Direction\n";
+            }
+        }
+
+        // Only keep the eventData bytes that fit in the record
+        std::array<uint8_t, dynamic_sensors::ipmi::sel::systemEventSize>
+            eventData{};
+        std::copy_n(eventDataBytes.begin(),
+                    std::min(eventDataBytes.size(), eventData.size()),
+                    eventData.begin());
+
+        return ipmi::responseSuccess(
+            nextRecordID, recordID, recordType,
+            systemEventType{timestamp, generatorID, evmRev, sensorType,
+                            sensorNum, eventType, eventDir, eventData});
+    }
+
+    return ipmi::responseUnspecifiedError();
+}
+
+ipmi::RspType<uint16_t> ipmiStorageAddSELEntry(
+    uint16_t recordID, uint8_t recordType, uint32_t timestamp,
+    uint16_t generatorID, uint8_t evmRev, uint8_t sensorType, uint8_t sensorNum,
+    uint8_t eventType, uint8_t eventData1, uint8_t eventData2,
+    uint8_t eventData3)
+{
+    // Per the IPMI spec, need to cancel any reservation when a SEL entry is
+    // added
+    cancelSELReservation();
+
+    uint16_t responseID = 0xFFFF;
+    return ipmi::responseSuccess(responseID);
+}
+
+ipmi::RspType<uint8_t> ipmiStorageClearSEL(ipmi::Context::ptr ctx,
+                                           uint16_t reservationID,
+                                           const std::array<uint8_t, 3>& clr,
+                                           uint8_t eraseOperation)
+{
+    if (!checkSELReservation(reservationID))
+    {
+        return ipmi::responseInvalidReservationId();
+    }
+
+    static constexpr std::array<uint8_t, 3> clrExpected = {'C', 'L', 'R'};
+    if (clr != clrExpected)
+    {
+        return ipmi::responseInvalidFieldRequest();
+    }
+
+    // Erasure status cannot be fetched, so always return erasure status as
+    // `erase completed`.
+    if (eraseOperation == ipmi::sel::getEraseStatus)
+    {
+        return ipmi::responseSuccess(ipmi::sel::eraseComplete);
+    }
+
+    // Check that initiate erase is correct
+    if (eraseOperation != ipmi::sel::initiateErase)
+    {
+        return ipmi::responseInvalidFieldRequest();
+    }
+
+    // Per the IPMI spec, need to cancel any reservation when the SEL is
+    // cleared
+    cancelSELReservation();
+
+    // Save the erase time
+    dynamic_sensors::ipmi::sel::erase_time::save();
+
+    // Clear the SEL by deleting the log files
+    std::vector<std::filesystem::path> selLogFiles;
+    if (getSELLogFiles(selLogFiles))
+    {
+        for (const std::filesystem::path& file : selLogFiles)
+        {
+            std::error_code ec;
+            std::filesystem::remove(file, ec);
+        }
+    }
+
+    // Reload rsyslog so it knows to start new log files
+    std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
+    sdbusplus::message::message rsyslogReload = dbus->new_method_call(
+        "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
+        "org.freedesktop.systemd1.Manager", "ReloadUnit");
+    rsyslogReload.append("rsyslog.service", "replace");
+    try
+    {
+        sdbusplus::message::message reloadResponse = dbus->call(rsyslogReload);
+    }
+    catch (sdbusplus::exception_t& e)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
+    }
+
+    return ipmi::responseSuccess(ipmi::sel::eraseComplete);
+}
+
+ipmi::RspType<uint32_t> ipmiStorageGetSELTime()
+{
+    struct timespec selTime = {};
+
+    if (clock_gettime(CLOCK_REALTIME, &selTime) < 0)
+    {
+        return ipmi::responseUnspecifiedError();
+    }
+
+    return ipmi::responseSuccess(selTime.tv_sec);
+}
+
+ipmi::RspType<> ipmiStorageSetSELTime(uint32_t selTime)
+{
+    // Set SEL Time is not supported
+    return ipmi::responseInvalidCommand();
+}
+
+std::vector<uint8_t> getType12SDRs(uint16_t index, uint16_t recordId)
+{
+    std::vector<uint8_t> resp;
+    if (index == 0)
+    {
+        Type12Record bmc = {};
+        bmc.header.record_id_lsb = recordId;
+        bmc.header.record_id_msb = recordId >> 8;
+        bmc.header.sdr_version = ipmiSdrVersion;
+        bmc.header.record_type = 0x12;
+        bmc.header.record_length = 0x1b;
+        bmc.slaveAddress = 0x20;
+        bmc.channelNumber = 0;
+        bmc.powerStateNotification = 0;
+        bmc.deviceCapabilities = 0xBF;
+        bmc.reserved = 0;
+        bmc.entityID = 0x2E;
+        bmc.entityInstance = 1;
+        bmc.oem = 0;
+        bmc.typeLengthCode = 0xD0;
+        std::string bmcName = "Basbrd Mgmt Ctlr";
+        std::copy(bmcName.begin(), bmcName.end(), bmc.name);
+        uint8_t* bmcPtr = reinterpret_cast<uint8_t*>(&bmc);
+        resp.insert(resp.end(), bmcPtr, bmcPtr + sizeof(Type12Record));
+    }
+    else if (index == 1)
+    {
+        Type12Record me = {};
+        me.header.record_id_lsb = recordId;
+        me.header.record_id_msb = recordId >> 8;
+        me.header.sdr_version = ipmiSdrVersion;
+        me.header.record_type = 0x12;
+        me.header.record_length = 0x16;
+        me.slaveAddress = 0x2C;
+        me.channelNumber = 6;
+        me.powerStateNotification = 0x24;
+        me.deviceCapabilities = 0x21;
+        me.reserved = 0;
+        me.entityID = 0x2E;
+        me.entityInstance = 2;
+        me.oem = 0;
+        me.typeLengthCode = 0xCB;
+        std::string meName = "Mgmt Engine";
+        std::copy(meName.begin(), meName.end(), me.name);
+        uint8_t* mePtr = reinterpret_cast<uint8_t*>(&me);
+        resp.insert(resp.end(), mePtr, mePtr + sizeof(Type12Record));
+    }
+    else
+    {
+        throw std::runtime_error("getType12SDRs:: Illegal index " +
+                                 std::to_string(index));
+    }
+
+    return resp;
+}
+
+void registerStorageFunctions()
+{
+    createTimers();
+    startMatch();
+
+    // <Get FRU Inventory Area Info>
+    ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnStorage,
+                          ipmi::storage::cmdGetFruInventoryAreaInfo,
+                          ipmi::Privilege::User, ipmiStorageGetFruInvAreaInfo);
+    // <READ FRU Data>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
+                          ipmi::storage::cmdReadFruData, ipmi::Privilege::User,
+                          ipmiStorageReadFruData);
+
+    // <WRITE FRU Data>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
+                          ipmi::storage::cmdWriteFruData,
+                          ipmi::Privilege::Operator, ipmiStorageWriteFruData);
+
+    // <Get SEL Info>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
+                          ipmi::storage::cmdGetSelInfo, ipmi::Privilege::User,
+                          ipmiStorageGetSELInfo);
+
+    // <Get SEL Entry>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
+                          ipmi::storage::cmdGetSelEntry, ipmi::Privilege::User,
+                          ipmiStorageGetSELEntry);
+
+    // <Add SEL Entry>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
+                          ipmi::storage::cmdAddSelEntry,
+                          ipmi::Privilege::Operator, ipmiStorageAddSELEntry);
+
+    // <Clear SEL>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
+                          ipmi::storage::cmdClearSel, ipmi::Privilege::Operator,
+                          ipmiStorageClearSEL);
+
+    // <Get SEL Time>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
+                          ipmi::storage::cmdGetSelTime, ipmi::Privilege::User,
+                          ipmiStorageGetSELTime);
+
+    // <Set SEL Time>
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
+                          ipmi::storage::cmdSetSelTime,
+                          ipmi::Privilege::Operator, ipmiStorageSetSELTime);
+}
+} // namespace storage
+} // namespace ipmi
