oem ibm: infrastructure for oem handlers

1. This commit adds the framework for an oem handler
which can be used by specific oem use-cases
for implementing various commands.

2. This commit adds implementation for getStateSensorReadings
and setStateEffecterStates commands for oem state sets.

3. Also adds implementation for inband code update.

Change-Id: Ib38a66ee381dd06b93f6a9313d51de1c23e6ee65
Signed-off-by: Sampa Misra <sampmisr@in.ibm.com>
diff --git a/common/types.hpp b/common/types.hpp
index c2b3510..254c37a 100644
--- a/common/types.hpp
+++ b/common/types.hpp
@@ -34,6 +34,7 @@
 using EntityType = uint16_t;

 using EntityInstance = uint16_t;

 using ContainerID = uint16_t;

+using StateSetId = uint16_t;

 using CompositeCount = uint8_t;

 using SensorOffset = uint8_t;

 using EventState = uint8_t;

diff --git a/common/utils.hpp b/common/utils.hpp
index 7478aab..664169d 100644
--- a/common/utils.hpp
+++ b/common/utils.hpp
@@ -4,6 +4,8 @@
 #include "libpldm/bios.h"
 #include "libpldm/platform.h"
 
+#include "types.hpp"
+
 #include <stdint.h>
 #include <systemd/sd-bus.h>
 #include <unistd.h>
@@ -136,6 +138,10 @@
                  uint64_t, double, std::string>;
 using DbusProp = std::string;
 using DbusChangedProps = std::map<DbusProp, PropertyValue>;
+using DBusInterfaceAdded = std::vector<
+    std::pair<pldm::dbus::Interface,
+              std::vector<std::pair<pldm::dbus::Property,
+                                    std::variant<pldm::dbus::Property>>>>>;
 
 /**
  * @brief The interface for DBusHandler
diff --git a/libpldm/entity.h b/libpldm/entity.h
index 600946e..3cf0a23 100644
--- a/libpldm/entity.h
+++ b/libpldm/entity.h
@@ -139,6 +139,10 @@
 

 	/* Logical */

 	PLDM_ENTITY_SYSTEM_LOGICAL = 11521,

+

+	/* OEM ranges */

+	PLDM_OEM_ENTITY_TYPE_START = 24576,

+	PLDM_OEM_ENTITY_TYPE_END = 32767,

 };

 

 #ifdef __cplusplus

diff --git a/libpldm/state_set.h b/libpldm/state_set.h
index 3a0528e..009b0df 100644
--- a/libpldm/state_set.h
+++ b/libpldm/state_set.h
@@ -162,6 +162,11 @@
 	PLDM_SW_TERM_GRACEFUL_SHUTDOWN = 7,

 	PLDM_SW_TERM_TERMINATION_REQUEST_FAILED = 8,

 };

+

+/* OEM ranges */

+#define PLDM_OEM_STATE_SET_ID_START 32768

+#define PLDM_OEM_STATE_SET_ID_END 65535

+

 #ifdef __cplusplus

 }

 #endif

diff --git a/libpldm/states.h b/libpldm/states.h
index ca20acd..a89648d 100644
--- a/libpldm/states.h
+++ b/libpldm/states.h
@@ -7,13 +7,6 @@
 
 #include "pldm_types.h"
 
-/** @brief PLDM state set ids
- */
-enum pldm_state_set_ids {
-	PLDM_BOOT_PROGRESS_STATE = 196,
-	PLDM_SYSTEM_POWER_STATE = 260,
-};
-
 /** @brief PLDM enums for the boot progress state set
  */
 enum pldm_boot_progress_states {
diff --git a/libpldmresponder/meson.build b/libpldmresponder/meson.build
index 50ca692..794a5e4 100644
--- a/libpldmresponder/meson.build
+++ b/libpldmresponder/meson.build
@@ -34,7 +34,9 @@
     '../oem/ibm/libpldmresponder/file_io_type_pel.cpp',
     '../oem/ibm/libpldmresponder/file_io_type_dump.cpp',
     '../oem/ibm/libpldmresponder/file_io_type_cert.cpp',
-    '../oem/ibm/libpldmresponder/platform_oem_ibm.cpp'
+    '../oem/ibm/libpldmresponder/platform_oem_ibm.cpp',
+    '../oem/ibm/libpldmresponder/oem_ibm_handler.cpp',
+    '../oem/ibm/libpldmresponder/inband_code_update.cpp'
   ]
 endif
 
diff --git a/libpldmresponder/oem_handler.hpp b/libpldmresponder/oem_handler.hpp
new file mode 100644
index 0000000..52d0027
--- /dev/null
+++ b/libpldmresponder/oem_handler.hpp
@@ -0,0 +1,75 @@
+#pragma once
+
+#include "common/types.hpp"
+#include "common/utils.hpp"
+#include "pldmd/handler.hpp"
+
+namespace pldm
+{
+
+using namespace pdr;
+
+namespace responder
+{
+
+namespace oem_platform
+{
+
+class Handler : public CmdHandler
+{
+  public:
+    Handler(const pldm::utils::DBusHandler* dBusIntf) : dBusIntf(dBusIntf)
+    {}
+
+    /** @brief Interface to get the state sensor readings requested by pldm
+     *  requester for OEM types. Each specific type should implement a handler
+     *  of it's own
+     *
+     *  @param[in] entityType - entity type corresponding to the sensor
+     *  @param[in] entityInstance - entity instance number
+     *  @param[in] stateSetId - state set id
+     *  @param[in] compSensorCnt - composite sensor count
+     *  @param[out] stateField - The state field data for each of the states,
+     *                           equal to composite sensor count in number
+     *
+     *  @return - Success or failure in getting the states. Returns failure in
+     *            terms of PLDM completion codes if fetching atleast one state
+     *            fails
+     */
+    virtual int getOemStateSensorReadingsHandler(
+        EntityType entityType, EntityInstance entityInstance,
+        StateSetId stateSetId, CompositeCount compSensorCnt,
+        std::vector<get_sensor_state_field>& stateField) = 0;
+
+    /** @brief Interface to set the effecter requested by pldm requester
+     *         for OEM types. Each individual oem type should implement
+     *         it's own handler.
+     *
+     *  @param[in] entityType - entity type corresponding to the effecter id
+     *  @param[in] entityInstance - entity instance
+     *  @param[in] stateSetId - state set id
+     *  @param[in] compEffecterCnt - composite effecter count
+     *  param[in] stateField - The state field data for each of the states,
+     *                         equal to compEffecterCnt in number
+     *
+     *  @return - Success or failure in setting the states.Returns failure in
+     *            terms of PLDM completion codes if atleast one state fails to
+     *            be set
+     */
+
+    virtual int oemSetStateEffecterStatesHandler(
+        EntityType entityType, EntityInstance entityInstance,
+        StateSetId stateSetId, CompositeCount compEffecterCnt,
+        const std::vector<set_effecter_state_field>& stateField) = 0;
+
+    virtual ~Handler() = default;
+
+  protected:
+    const pldm::utils::DBusHandler* dBusIntf;
+};
+
+} // namespace oem_platform
+
+} // namespace responder
+
+} // namespace pldm
diff --git a/libpldmresponder/platform.cpp b/libpldmresponder/platform.cpp
index d2d1d6e..984d79b 100644
--- a/libpldmresponder/platform.cpp
+++ b/libpldmresponder/platform.cpp
@@ -1,6 +1,9 @@
 
 #include "platform.hpp"
 
+#include "libpldm/entity.h"
+#include "libpldm/state_set.h"
+
 #include "common/types.hpp"
 #include "common/utils.hpp"
 #include "event_parser.hpp"
@@ -244,9 +247,24 @@
 
     stateField.resize(compEffecterCnt);
     const pldm::utils::DBusHandler dBusIntf;
-    rc = platform_state_effecter::setStateEffecterStatesHandler<
-        pldm::utils::DBusHandler, Handler>(dBusIntf, *this, effecterId,
-                                           stateField);
+    uint16_t entityType{};
+    uint16_t entityInstance{};
+    uint16_t stateSetId{};
+
+    if (isOemStateEffecter(*this, effecterId, compEffecterCnt, entityType,
+                           entityInstance, stateSetId) &&
+        oemPlatformHandler != nullptr)
+    {
+        rc = oemPlatformHandler->oemSetStateEffecterStatesHandler(
+            entityType, entityInstance, stateSetId, compEffecterCnt,
+            stateField);
+    }
+    else
+    {
+        rc = platform_state_effecter::setStateEffecterStatesHandler<
+            pldm::utils::DBusHandler, Handler>(dBusIntf, *this, effecterId,
+                                               stateField);
+    }
     if (rc != PLDM_SUCCESS)
     {
         return CmdHandler::ccOnlyResponse(request, rc);
@@ -583,13 +601,29 @@
     }
 
     // 0x01 to 0x08
-    uint8_t sensorRearmCout = getBitfieldCount(sensorRearm);
-    std::vector<get_sensor_state_field> stateField(sensorRearmCout);
+    uint8_t sensorRearmCount = getBitfieldCount(sensorRearm);
+    std::vector<get_sensor_state_field> stateField(sensorRearmCount);
     uint8_t comSensorCnt{};
     const pldm::utils::DBusHandler dBusIntf;
-    rc = platform_state_sensor::getStateSensorReadingsHandler<
-        pldm::utils::DBusHandler, Handler>(
-        dBusIntf, *this, sensorId, sensorRearmCout, comSensorCnt, stateField);
+
+    uint16_t entityType{};
+    uint16_t entityInstance{};
+    uint16_t stateSetId{};
+
+    if (isOemStateSensor(*this, sensorId, sensorRearmCount, comSensorCnt,
+                         entityType, entityInstance, stateSetId) &&
+        oemPlatformHandler != nullptr)
+    {
+        rc = oemPlatformHandler->getOemStateSensorReadingsHandler(
+            entityType, entityInstance, stateSetId, comSensorCnt, stateField);
+    }
+    else
+    {
+        rc = platform_state_sensor::getStateSensorReadingsHandler<
+            pldm::utils::DBusHandler, Handler>(dBusIntf, *this, sensorId,
+                                               sensorRearmCount, comSensorCnt,
+                                               stateField);
+    }
 
     if (rc != PLDM_SUCCESS)
     {
@@ -611,6 +645,134 @@
     return response;
 }
 
+bool isOemStateSensor(Handler& handler, uint16_t sensorId,
+                      uint8_t sensorRearmCount, uint8_t& compSensorCnt,
+                      uint16_t& entityType, uint16_t& entityInstance,
+                      uint16_t& stateSetId)
+{
+    pldm_state_sensor_pdr* pdr = nullptr;
+
+    std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> stateSensorPdrRepo(
+        pldm_pdr_init(), pldm_pdr_destroy);
+    Repo stateSensorPDRs(stateSensorPdrRepo.get());
+    getRepoByType(handler.getRepo(), stateSensorPDRs, PLDM_STATE_SENSOR_PDR);
+    if (stateSensorPDRs.empty())
+    {
+        std::cerr << "Failed to get record by PDR type\n";
+        return false;
+    }
+
+    PdrEntry pdrEntry{};
+    auto pdrRecord = stateSensorPDRs.getFirstRecord(pdrEntry);
+    while (pdrRecord)
+    {
+        pdr = reinterpret_cast<pldm_state_sensor_pdr*>(pdrEntry.data);
+        assert(pdr != NULL);
+        if (pdr->sensor_id != sensorId)
+        {
+            pdr = nullptr;
+            pdrRecord = stateSensorPDRs.getNextRecord(pdrRecord, pdrEntry);
+            continue;
+        }
+        auto tmpEntityType = pdr->entity_type;
+        auto tmpEntityInstance = pdr->entity_instance;
+        auto tmpCompSensorCnt = pdr->composite_sensor_count;
+        auto tmpPossibleStates =
+            reinterpret_cast<state_sensor_possible_states*>(
+                pdr->possible_states);
+        auto tmpStateSetId = tmpPossibleStates->state_set_id;
+
+        if (sensorRearmCount > tmpCompSensorCnt)
+        {
+            std::cerr << "The requester sent wrong sensorRearm"
+                      << " count for the sensor, SENSOR_ID=" << sensorId
+                      << "SENSOR_REARM_COUNT=" << (uint16_t)sensorRearmCount
+                      << "\n";
+            break;
+        }
+
+        if ((tmpEntityType >= PLDM_OEM_ENTITY_TYPE_START &&
+             tmpEntityType <= PLDM_OEM_ENTITY_TYPE_END) ||
+            (tmpStateSetId >= PLDM_OEM_STATE_SET_ID_START &&
+             tmpStateSetId < PLDM_OEM_STATE_SET_ID_END))
+        {
+            entityType = tmpEntityType;
+            entityInstance = tmpEntityInstance;
+            stateSetId = tmpStateSetId;
+            compSensorCnt = tmpCompSensorCnt;
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+    return false;
+}
+
+bool isOemStateEffecter(Handler& handler, uint16_t effecterId,
+                        uint8_t compEffecterCnt, uint16_t& entityType,
+                        uint16_t& entityInstance, uint16_t& stateSetId)
+{
+    pldm_state_effecter_pdr* pdr = nullptr;
+
+    std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> stateEffecterPdrRepo(
+        pldm_pdr_init(), pldm_pdr_destroy);
+    Repo stateEffecterPDRs(stateEffecterPdrRepo.get());
+    getRepoByType(handler.getRepo(), stateEffecterPDRs,
+                  PLDM_STATE_EFFECTER_PDR);
+    if (stateEffecterPDRs.empty())
+    {
+        std::cerr << "Failed to get record by PDR type\n";
+        return false;
+    }
+
+    PdrEntry pdrEntry{};
+    auto pdrRecord = stateEffecterPDRs.getFirstRecord(pdrEntry);
+    while (pdrRecord)
+    {
+        pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrEntry.data);
+        assert(pdr != NULL);
+        if (pdr->effecter_id != effecterId)
+        {
+            pdr = nullptr;
+            pdrRecord = stateEffecterPDRs.getNextRecord(pdrRecord, pdrEntry);
+            continue;
+        }
+
+        auto tmpEntityType = pdr->entity_type;
+        auto tmpEntityInstance = pdr->entity_instance;
+        auto tmpPossibleStates =
+            reinterpret_cast<state_effecter_possible_states*>(
+                pdr->possible_states);
+        auto tmpStateSetId = tmpPossibleStates->state_set_id;
+
+        if (compEffecterCnt > pdr->composite_effecter_count)
+        {
+            std::cerr << "The requester sent wrong composite effecter"
+                      << " count for the effecter, EFFECTER_ID=" << effecterId
+                      << "COMP_EFF_CNT=" << (uint16_t)compEffecterCnt << "\n";
+            return false;
+        }
+
+        if ((tmpEntityType >= PLDM_OEM_ENTITY_TYPE_START &&
+             tmpEntityType <= PLDM_OEM_ENTITY_TYPE_END) ||
+            (tmpStateSetId >= PLDM_OEM_STATE_SET_ID_START &&
+             tmpStateSetId < PLDM_OEM_STATE_SET_ID_END))
+        {
+            entityType = tmpEntityType;
+            entityInstance = tmpEntityInstance;
+            stateSetId = tmpStateSetId;
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+    return false;
+}
+
 } // namespace platform
 } // namespace responder
 } // namespace pldm
diff --git a/libpldmresponder/platform.hpp b/libpldmresponder/platform.hpp
index ef2434d..09418cd 100644
--- a/libpldmresponder/platform.hpp
+++ b/libpldmresponder/platform.hpp
@@ -13,6 +13,7 @@
 #include "host-bmc/host_pdr_handler.hpp"
 #include "libpldmresponder/pdr.hpp"
 #include "libpldmresponder/pdr_utils.hpp"
+#include "oem_handler.hpp"
 #include "pldmd/handler.hpp"
 
 #include <stdint.h>
@@ -55,12 +56,14 @@
             const std::string& pdrJsonsDir, pldm_pdr* repo,
             HostPDRHandler* hostPDRHandler,
             DbusToPLDMEvent* dbusToPLDMEventHandler, fru::Handler* fruHandler,
+            pldm::responder::oem_platform::Handler* oemPlatformHandler,
             bool buildPDRLazily = false,
             const std::optional<EventMap>& addOnHandlersMap = std::nullopt) :
         pdrRepo(repo),
         hostPDRHandler(hostPDRHandler),
         dbusToPLDMEventHandler(dbusToPLDMEventHandler), fruHandler(fruHandler),
-        dBusIntf(dBusIntf), pdrJsonsDir(pdrJsonsDir), pdrCreated(false)
+        dBusIntf(dBusIntf), oemPlatformHandler(oemPlatformHandler),
+        pdrJsonsDir(pdrJsonsDir), pdrCreated(false)
     {
         if (!buildPDRLazily)
         {
@@ -441,10 +444,49 @@
     DbusToPLDMEvent* dbusToPLDMEventHandler;
     fru::Handler* fruHandler;
     const pldm::utils::DBusHandler* dBusIntf;
+    pldm::responder::oem_platform::Handler* oemPlatformHandler;
     std::string pdrJsonsDir;
     bool pdrCreated;
 };
 
+/** @brief Function to check if a sensor falls in OEM range
+ *         A sensor is considered to be oem if either of entity
+ *         type or state set or both falls in oem range
+ *
+ *  @param[in] handler - the interface object
+ *  @param[in] sensorId - sensor id
+ *  @param[in] sensorRearmCount - sensor rearm count
+ *  @param[out] compSensorCnt - composite sensor count
+ *  @param[out] entityType - entity type
+ *  @param[out] entityInstance - entity instance number
+ *  @param[out] stateSetId - state set id
+ *
+ *  @return true if the sensor is OEM. All out parameters are invalid
+ *               for a non OEM sensor
+ */
+bool isOemStateSensor(Handler& handler, uint16_t sensorId,
+                      uint8_t sensorRearmCount, uint8_t& compSensorCnt,
+                      uint16_t& entityType, uint16_t& entityInstance,
+                      uint16_t& stateSetId);
+
+/** @brief Function to check if an effecter falls in OEM range
+ *         An effecter is considered to be oem if either of entity
+ *         type or state set or both falls in oem range
+ *
+ *  @param[in] handler - the interface object
+ *  @param[in] effecterId - effecter id
+ *  @param[in] compEffecterCnt - composite effecter count
+ *  @param[out] entityType - entity type
+ *  @param[out] entityInstance - entity instance number
+ *  @param[out] stateSetId - state set id
+ *
+ *  @return true if the effecter is OEM. All out parameters are invalid
+ *               for a non OEM effecter
+ */
+bool isOemStateEffecter(Handler& handler, uint16_t effecterId,
+                        uint8_t compEffecterCnt, uint16_t& entityType,
+                        uint16_t& entityInstance, uint16_t& stateSetId);
+
 } // namespace platform
 } // namespace responder
 } // namespace pldm
diff --git a/oem/ibm/libpldmresponder/file_io.hpp b/oem/ibm/libpldmresponder/file_io.hpp
index 771d038..9f6492c 100644
--- a/oem/ibm/libpldmresponder/file_io.hpp
+++ b/oem/ibm/libpldmresponder/file_io.hpp
@@ -7,6 +7,7 @@
 #include "oem/ibm/libpldm/host.h"
 
 #include "common/utils.hpp"
+#include "oem_ibm_handler.hpp"
 #include "pldmd/handler.hpp"
 
 #include <fcntl.h>
@@ -157,7 +158,8 @@
 class Handler : public CmdHandler
 {
   public:
-    Handler()
+    Handler(oem_platform::Handler* oemPlatformHandler) :
+        oemPlatformHandler(oemPlatformHandler)
     {
         handlers.emplace(PLDM_READ_FILE_INTO_MEMORY,
                          [this](const pldm_msg* request, size_t payloadLength) {
@@ -312,6 +314,9 @@
      *  @return PLDM response message
      */
     Response newFileAvailable(const pldm_msg* request, size_t payloadLength);
+
+  private:
+    oem_platform::Handler* oemPlatformHandler;
 };
 
 } // namespace oem_ibm
diff --git a/oem/ibm/libpldmresponder/inband_code_update.cpp b/oem/ibm/libpldmresponder/inband_code_update.cpp
new file mode 100644
index 0000000..f17b209
--- /dev/null
+++ b/oem/ibm/libpldmresponder/inband_code_update.cpp
@@ -0,0 +1,217 @@
+#include "inband_code_update.hpp"
+
+#include "oem_ibm_handler.hpp"
+#include "xyz/openbmc_project/Common/error.hpp"
+
+#include <sdbusplus/server.hpp>
+#include <xyz/openbmc_project/Dump/NewDump/server.hpp>
+
+#include <exception>
+
+namespace pldm
+{
+
+namespace responder
+{
+using namespace oem_ibm_platform;
+
+std::string CodeUpdate::fetchCurrentBootSide()
+{
+    return currBootSide;
+}
+
+std::string CodeUpdate::fetchNextBootSide()
+{
+    return nextBootSide;
+}
+
+int CodeUpdate::setCurrentBootSide(const std::string& currSide)
+{
+    currBootSide = currSide;
+    return PLDM_SUCCESS;
+}
+
+int CodeUpdate::setNextBootSide(const std::string& nextSide)
+{
+    nextBootSide = nextSide;
+    std::string objPath{};
+    if (nextBootSide == currBootSide)
+    {
+        objPath = runningVersion;
+    }
+    else
+    {
+        objPath = nonRunningVersion;
+    }
+    if (objPath.empty())
+    {
+        std::cerr << "no nonRunningVersion present \n";
+        return PLDM_PLATFORM_INVALID_STATE_VALUE;
+    }
+
+    pldm::utils::DBusMapping dbusMapping{objPath, redundancyIntf, "Priority",
+                                         "uint8_t"};
+    uint8_t val = 0;
+    pldm::utils::PropertyValue value = static_cast<uint8_t>(val);
+    try
+    {
+        dBusIntf->setDbusProperty(dbusMapping, value);
+    }
+    catch (const std::exception& e)
+    {
+        std::cerr << "failed to set the next boot side to " << objPath.c_str()
+                  << " ERROR=" << e.what() << "\n";
+        return PLDM_ERROR;
+    }
+    return PLDM_SUCCESS;
+}
+
+void CodeUpdate::setVersions()
+{
+    static constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper";
+    static constexpr auto functionalObjPath =
+        "/xyz/openbmc_project/software/functional";
+    static constexpr auto activeObjPath =
+        "/xyz/openbmc_project/software/active";
+    static constexpr auto propIntf = "org.freedesktop.DBus.Properties";
+
+    auto& bus = dBusIntf->getBus();
+
+    try
+    {
+        auto method = bus.new_method_call(mapperService, functionalObjPath,
+                                          propIntf, "Get");
+        method.append("xyz.openbmc_project.Association", "endpoints");
+        std::variant<std::vector<std::string>> paths;
+
+        auto reply = bus.call(method);
+        reply.read(paths);
+
+        runningVersion = std::get<std::vector<std::string>>(paths)[0];
+
+        auto method1 =
+            bus.new_method_call(mapperService, activeObjPath, propIntf, "Get");
+        method1.append("xyz.openbmc_project.Association", "endpoints");
+
+        auto reply1 = bus.call(method1);
+        reply1.read(paths);
+        for (const auto& path : std::get<std::vector<std::string>>(paths))
+        {
+            if (path != runningVersion)
+            {
+                nonRunningVersion = path;
+                break;
+            }
+        }
+    }
+    catch (const std::exception& e)
+    {
+        std::cerr << "failed to make a d-bus call to Object Mapper "
+                     "Association, ERROR="
+                  << e.what() << "\n";
+        return;
+    }
+
+    using namespace sdbusplus::bus::match::rules;
+    captureNextBootSideChange.push_back(
+        std::make_unique<sdbusplus::bus::match::match>(
+            pldm::utils::DBusHandler::getBus(),
+            propertiesChanged(runningVersion, redundancyIntf),
+            [this](sdbusplus::message::message& msg) {
+                DbusChangedProps props;
+                std::string iface;
+                msg.read(iface, props);
+                processPriorityChangeNotification(props);
+            }));
+    fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
+        pldm::utils::DBusHandler::getBus(),
+        "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
+        "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
+        [this](sdbusplus::message::message& msg) {
+            DBusInterfaceAdded interfaces;
+            sdbusplus::message::object_path path;
+            msg.read(path, interfaces);
+            for (auto& interface : interfaces)
+            {
+                if (interface.first ==
+                    "xyz.openbmc_project.Software.Activation")
+                {
+                    newImageId = path.str;
+                    break;
+                }
+            }
+        });
+}
+
+void CodeUpdate::processPriorityChangeNotification(
+    const DbusChangedProps& chProperties)
+{
+    static constexpr auto propName = "Priority";
+    const auto it = chProperties.find(propName);
+    if (it == chProperties.end())
+    {
+        return;
+    }
+    uint8_t newVal = std::get<uint8_t>(it->second);
+    nextBootSide = (newVal == 0) ? currBootSide
+                                 : ((currBootSide == Tside) ? Pside : Tside);
+}
+
+void CodeUpdate::setOemPlatformHandler(
+    pldm::responder::oem_platform::Handler* handler)
+{
+    oemPlatformHandler = handler;
+}
+
+uint8_t fetchBootSide(uint16_t entityInstance, CodeUpdate* codeUpdate)
+{
+    uint8_t sensorOpState = tSideNum;
+
+    if (entityInstance == 0)
+    {
+        auto currSide = codeUpdate->fetchCurrentBootSide();
+        if (currSide == Pside)
+        {
+            sensorOpState = pSideNum;
+        }
+    }
+    else if (entityInstance == 1)
+    {
+        auto nextSide = codeUpdate->fetchNextBootSide();
+        if (nextSide == Pside)
+        {
+            sensorOpState = pSideNum;
+        }
+    }
+    else
+    {
+        sensorOpState = PLDM_SENSOR_UNKNOWN;
+    }
+
+    return sensorOpState;
+}
+
+int setBootSide(uint16_t entityInstance, uint8_t currState,
+                const std::vector<set_effecter_state_field>& stateField,
+                CodeUpdate* codeUpdate)
+{
+    int rc = PLDM_SUCCESS;
+    auto side = (stateField[currState].effecter_state == pSideNum) ? "P" : "T";
+
+    if (entityInstance == 0)
+    {
+        rc = codeUpdate->setCurrentBootSide(side);
+    }
+    else if (entityInstance == 1)
+    {
+        rc = codeUpdate->setNextBootSide(side);
+    }
+    else
+    {
+        rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
+    }
+    return rc;
+}
+
+} // namespace responder
+} // namespace pldm
diff --git a/oem/ibm/libpldmresponder/inband_code_update.hpp b/oem/ibm/libpldmresponder/inband_code_update.hpp
new file mode 100644
index 0000000..6607de0
--- /dev/null
+++ b/oem/ibm/libpldmresponder/inband_code_update.hpp
@@ -0,0 +1,128 @@
+#pragma once
+
+#include "common/utils.hpp"
+#include "libpldmresponder/platform.hpp"
+
+#include <string>
+
+using namespace pldm::utils;
+namespace pldm
+{
+namespace responder
+{
+
+static constexpr uint8_t pSideNum = 1;
+static constexpr uint8_t tSideNum = 2;
+static constexpr auto Pside = "P";
+static constexpr auto Tside = "T";
+
+static constexpr auto redundancyIntf =
+    "xyz.openbmc_project.Software.RedundancyPriority";
+
+/** @class CodeUpdate
+ *
+ *  @brief This class performs the necessary operation in pldm for
+ *         inband code update. That includes taking actions on the
+ *         setStateEffecterStates calls from Host and also sending
+ *         notification to phosphor-software-manager app
+ */
+class CodeUpdate
+{
+  public:
+    /** @brief Constructor to create an inband codeupdate object
+     *  @param[in] dBusIntf - D-Bus handler pointer
+     */
+    CodeUpdate(const pldm::utils::DBusHandler* dBusIntf) : dBusIntf(dBusIntf)
+    {
+        currBootSide = Tside;
+        nextBootSide = Tside;
+    }
+
+    /* @brief Method to return the current boot side
+     */
+    std::string fetchCurrentBootSide();
+
+    /* @brief Method to return the next boot side
+     */
+    std::string fetchNextBootSide();
+
+    /* @brief Method to set the current boot side or
+     *        perform a rename operation on current boot side
+     * @param[in] currSide - current side to be set to
+     * @return PLDM_SUCCESS codes
+     */
+    int setCurrentBootSide(const std::string& currSide);
+
+    /* @brief Method to set the next boot side
+     * @param[in] nextSide - next boot side to be set to
+     * @return PLDM_SUCCESS codes
+     */
+    int setNextBootSide(const std::string& nextSide);
+
+    /* @brief Method to set the running and non-running
+     *        images
+     */
+    virtual void setVersions();
+
+    /* @brief Method to return the newly upoaded image id in
+     *        /tmp
+     */
+    std::string fetchnewImageId()
+    {
+        return newImageId;
+    }
+
+    /* @brief Method to set the oem platform handler in CodeUpdate class */
+    void setOemPlatformHandler(pldm::responder::oem_platform::Handler* handler);
+
+    virtual ~CodeUpdate()
+    {}
+
+  private:
+    std::string currBootSide;      //!< current boot side
+    std::string nextBootSide;      //!< next boot side
+    std::string runningVersion;    //!< currently running image
+    std::string nonRunningVersion; //!< alternate image
+    std::string newImageId;        //!< new image id
+    bool codeUpdateInProgress =
+        false; //!< indicates whether codeupdate is going on
+    const pldm::utils::DBusHandler* dBusIntf; //!< D-Bus handler
+    std::vector<std::unique_ptr<sdbusplus::bus::match::match>>
+        captureNextBootSideChange; //!< vector to catch the D-Bus property
+                                   //!< change for next boot side
+    std::unique_ptr<sdbusplus::bus::match::match>
+        fwUpdateMatcher; //!< pointer to capture the interface added signal for
+                         //!< new image
+    pldm::responder::oem_platform::Handler*
+        oemPlatformHandler; //!< oem platform handler
+
+    /* @brief Method to take action when the subscribed D-Bus property is
+     *        changed
+     * @param[in] chProperties - list of properties which have changed
+     * @return - none
+     */
+
+    void
+        processPriorityChangeNotification(const DbusChangedProps& chProperties);
+};
+
+/* @brief Method to fetch current or next boot side
+ * @param[in] entityInstance - entity instance for the sensor
+ * @param[in] codeUpdate - pointer to the CodeUpdate object
+ *
+ * @return - boot side
+ */
+uint8_t fetchBootSide(uint16_t entityInstance, CodeUpdate* codeUpdate);
+
+/* @brief Method to set current or next  boot side
+ * @param[in] entityInstance - entity instance for the effecter
+ * @param[in] currState - state to be set
+ * @param[in] stateField - state field set as sent by Host
+ * @return - PLDM_SUCCESS codes
+ */
+int setBootSide(uint16_t entityInstance, uint8_t currState,
+                const std::vector<set_effecter_state_field>& stateField,
+                CodeUpdate* codeUpdate);
+
+} // namespace responder
+} // namespace pldm
diff --git a/oem/ibm/libpldmresponder/oem_ibm_handler.cpp b/oem/ibm/libpldmresponder/oem_ibm_handler.cpp
new file mode 100644
index 0000000..2e6bd4c
--- /dev/null
+++ b/oem/ibm/libpldmresponder/oem_ibm_handler.cpp
@@ -0,0 +1,83 @@
+#include "oem_ibm_handler.hpp"
+
+#include "libpldm/entity.h"
+
+namespace pldm
+{
+
+namespace responder
+{
+
+namespace oem_ibm_platform
+{
+
+int pldm::responder::oem_ibm_platform::Handler::
+    getOemStateSensorReadingsHandler(
+        EntityType entityType, EntityInstance entityInstance,
+        StateSetId stateSetId, CompositeCount compSensorCnt,
+        std::vector<get_sensor_state_field>& stateField)
+{
+    int rc = PLDM_SUCCESS;
+    stateField.clear();
+
+    for (size_t i = 0; i < compSensorCnt; i++)
+    {
+        uint8_t sensorOpState{};
+        if (entityType == PLDM_ENTITY_VIRTUAL_MACHINE_MANAGER &&
+            stateSetId == PLDM_OEM_IBM_BOOT_STATE)
+        {
+            sensorOpState = fetchBootSide(entityInstance, codeUpdate);
+        }
+        else
+        {
+            rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
+            break;
+        }
+        stateField.push_back({PLDM_SENSOR_ENABLED, PLDM_SENSOR_UNKNOWN,
+                              PLDM_SENSOR_UNKNOWN, sensorOpState});
+    }
+    return rc;
+}
+
+int pldm::responder::oem_ibm_platform::Handler::
+    oemSetStateEffecterStatesHandler(
+        EntityType entityType, EntityInstance entityInstance,
+        StateSetId stateSetId, CompositeCount compEffecterCnt,
+        const std::vector<set_effecter_state_field>& stateField)
+{
+    int rc = PLDM_SUCCESS;
+
+    for (uint8_t currState = 0; currState < compEffecterCnt; ++currState)
+    {
+        if (stateField[currState].set_request == PLDM_REQUEST_SET)
+        {
+            if (entityType == PLDM_ENTITY_VIRTUAL_MACHINE_MANAGER &&
+                stateSetId == PLDM_OEM_IBM_BOOT_STATE)
+            {
+                rc = setBootSide(entityInstance, currState, stateField,
+                                 codeUpdate);
+            }
+            else
+            {
+                rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
+            }
+        }
+        if (rc != PLDM_SUCCESS)
+        {
+            break;
+        }
+    }
+    return rc;
+}
+
+void pldm::responder::oem_ibm_platform::Handler::setPlatformHandler(
+    pldm::responder::platform::Handler* handler)
+{
+    platformHandler = handler;
+}
+
+} // namespace oem_ibm_platform
+
+} // namespace responder
+
+} // namespace pldm
diff --git a/oem/ibm/libpldmresponder/oem_ibm_handler.hpp b/oem/ibm/libpldmresponder/oem_ibm_handler.hpp
new file mode 100644
index 0000000..2d294f0
--- /dev/null
+++ b/oem/ibm/libpldmresponder/oem_ibm_handler.hpp
@@ -0,0 +1,57 @@
+#pragma once
+
+#include "inband_code_update.hpp"
+#include "libpldmresponder/oem_handler.hpp"
+#include "libpldmresponder/platform.hpp"
+
+namespace pldm
+{
+
+namespace responder
+{
+
+namespace oem_ibm_platform
+{
+
+#define PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE 32768
+#define PLDM_OEM_IBM_BOOT_STATE 32769
+
+class Handler : public oem_platform::Handler
+{
+  public:
+    Handler(const pldm::utils::DBusHandler* dBusIntf,
+            pldm::responder::CodeUpdate* codeUpdate) :
+        oem_platform::Handler(dBusIntf),
+        codeUpdate(codeUpdate), platformHandler(nullptr)
+    {
+        codeUpdate->setVersions();
+    }
+
+    int getOemStateSensorReadingsHandler(
+        EntityType entityType, EntityInstance entityInstance,
+        StateSetId stateSetId, CompositeCount compSensorCnt,
+        std::vector<get_sensor_state_field>& stateField);
+
+    int oemSetStateEffecterStatesHandler(
+        EntityType entityType, EntityInstance entityInstance,
+        StateSetId stateSetId, CompositeCount compEffecterCnt,
+        const std::vector<set_effecter_state_field>& stateField);
+
+    /** @brief Method to set the platform handler in the
+     *         oem_ibm_handler class
+     *  @param[in] handler - pointer to PLDM platform handler
+     */
+    void setPlatformHandler(pldm::responder::platform::Handler* handler);
+
+    ~Handler() = default;
+
+    pldm::responder::CodeUpdate* codeUpdate; //!< pointer to CodeUpdate object
+    pldm::responder::platform::Handler*
+        platformHandler; //!< pointer to PLDM platform handler
+};
+
+} // namespace oem_ibm_platform
+
+} // namespace responder
+
+} // namespace pldm
diff --git a/oem/ibm/test/libpldmresponder_fileio_test.cpp b/oem/ibm/test/libpldmresponder_fileio_test.cpp
index e425a9a..65998a7 100644
--- a/oem/ibm/test/libpldmresponder_fileio_test.cpp
+++ b/oem/ibm/test/libpldmresponder_fileio_test.cpp
@@ -222,7 +222,8 @@
            &address, sizeof(address));
 
     // Pass invalid payload length
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto response = handler.readFileIntoMemory(request, 0);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
@@ -252,7 +253,8 @@
     // Initialise the file table with 2 valid file handles 0 & 1.
     auto& table = buildFileTable(fileTableConfig.c_str());
 
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto response = handler.readFileIntoMemory(request, requestPayloadLength);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
     ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_FILE_HANDLE);
@@ -283,7 +285,8 @@
     using namespace pldm::filetable;
     auto& table = buildFileTable(fileTableConfig.c_str());
 
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto response = handler.readFileIntoMemory(request, requestPayloadLength);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
     ASSERT_EQ(responsePtr->payload[0], PLDM_DATA_OUT_OF_RANGE);
@@ -314,7 +317,8 @@
     using namespace pldm::filetable;
     auto& table = buildFileTable(fileTableConfig.c_str());
 
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto response = handler.readFileIntoMemory(request, requestPayloadLength);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
@@ -348,7 +352,8 @@
     using namespace pldm::filetable;
     auto& table = buildFileTable(fileTableConfig.c_str());
 
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto response = handler.readFileIntoMemory(request, requestPayloadLength);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
@@ -376,7 +381,8 @@
            &address, sizeof(address));
 
     // Pass invalid payload length
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto response = handler.writeFileFromMemory(request, 0);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
@@ -411,7 +417,8 @@
     // Initialise the file table with 2 valid file handles 0 & 1.
     auto& table = buildFileTable(fileTableConfig.c_str());
 
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto response = handler.writeFileFromMemory(request, requestPayloadLength);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
     ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_FILE_HANDLE);
@@ -443,7 +450,8 @@
     // Initialise the file table with 2 valid file handles 0 & 1.
     auto& table = buildFileTable(TestFileTable::fileTableConfig.c_str());
 
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto response = handler.writeFileFromMemory(request, requestPayloadLength);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
     ASSERT_EQ(responsePtr->payload[0], PLDM_DATA_OUT_OF_RANGE);
@@ -512,7 +520,8 @@
     request->operation_flag = opFlag;
     request->table_type = type;
 
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto response = handler.getFileTable(requestMsgPtr, requestPayloadLength);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
     ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS);
@@ -535,7 +544,8 @@
     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
 
     // Pass invalid command payload length
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto response = handler.getFileTable(request, 0);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
@@ -557,7 +567,8 @@
     request->operation_flag = opFlag;
     request->table_type = type;
 
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto response = handler.getFileTable(requestMsgPtr, requestPayloadLength);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
     ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_FILE_TABLE_TYPE);
@@ -585,7 +596,8 @@
     auto& table = buildFileTable(fileTableConfig.c_str());
 
     // Invalid payload length
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto response = handler.readFile(requestMsgPtr, 0);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
@@ -635,7 +647,8 @@
     std::vector<char> buffer(length);
     stream.read(buffer.data(), length);
 
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto responseMsg = handler.readFile(requestMsgPtr, payload_length);
     auto response = reinterpret_cast<pldm_read_file_resp*>(
         responseMsg.data() + sizeof(pldm_msg_hdr));
@@ -685,7 +698,8 @@
     request->length = length;
 
     // Invalid payload length
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto response = handler.writeFile(requestMsgPtr, 0);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
@@ -732,7 +746,8 @@
     request->length = length;
     memcpy(request->file_data, fileData.data(), fileData.size());
 
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto responseMsg = handler.writeFile(requestMsgPtr, payload_length);
     auto response = reinterpret_cast<pldm_read_file_resp*>(
         responseMsg.data() + sizeof(pldm_msg_hdr));
@@ -765,7 +780,8 @@
     request->length = 17;
     request->address = 0;
 
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto response = handler.writeFileByTypeFromMemory(req, 0);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
 
@@ -833,7 +849,8 @@
     request->length = 17;
     request->address = 0;
 
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto response = handler.readFileByTypeIntoMemory(req, 0);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
     struct pldm_read_write_file_by_type_memory_resp* resp =
@@ -871,7 +888,8 @@
     request->offset = 0;
     request->length = 13;
 
-    oem_ibm::Handler handler;
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+    oem_ibm::Handler handler(oemPlatformHandler.get());
     auto response = handler.readFileByType(req, 0);
     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
     struct pldm_read_write_file_by_type_resp* resp =
diff --git a/oem/ibm/test/libpldmresponder_oem_platform_test.cpp b/oem/ibm/test/libpldmresponder_oem_platform_test.cpp
new file mode 100644
index 0000000..6b837dd
--- /dev/null
+++ b/oem/ibm/test/libpldmresponder_oem_platform_test.cpp
@@ -0,0 +1,103 @@
+#include "libpldm/entity.h"
+
+#include "common/utils.hpp"
+#include "libpldmresponder/event_parser.hpp"
+#include "libpldmresponder/pdr.hpp"
+#include "libpldmresponder/pdr_utils.hpp"
+#include "libpldmresponder/platform.hpp"
+#include "oem/ibm/libpldmresponder/inband_code_update.hpp"
+#include "oem/ibm/libpldmresponder/oem_ibm_handler.hpp"
+#include "test/mocked_utils.hpp"
+
+#include <iostream>
+
+using namespace pldm::utils;
+using namespace pldm::responder;
+using namespace pldm::responder::pdr;
+using namespace pldm::responder::pdr_utils;
+using namespace pldm::responder::oem_ibm_platform;
+
+class MockCodeUpdate : public CodeUpdate
+{
+  public:
+    MockCodeUpdate(const pldm::utils::DBusHandler* dBusIntf) :
+        CodeUpdate(dBusIntf)
+    {}
+
+    MOCK_METHOD(void, setVersions, (), (override));
+};
+
+TEST(oemSetStateEffecterStatesHandler, testGoodRequest)
+{
+    uint16_t entityID_ = PLDM_ENTITY_VIRTUAL_MACHINE_MANAGER;
+    uint16_t stateSetId_ = PLDM_OEM_IBM_BOOT_STATE;
+    uint16_t entityInstance_ = 0;
+    uint8_t compSensorCnt_ = 1;
+
+    std::vector<get_sensor_state_field> stateField;
+
+    auto mockDbusHandler = std::make_unique<MockdBusHandler>();
+    std::unique_ptr<CodeUpdate> mockCodeUpdate =
+        std::make_unique<MockCodeUpdate>(mockDbusHandler.get());
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+
+    oemPlatformHandler = std::make_unique<oem_ibm_platform::Handler>(
+        mockDbusHandler.get(), mockCodeUpdate.get());
+
+    auto rc = oemPlatformHandler->getOemStateSensorReadingsHandler(
+        entityID_, entityInstance_, stateSetId_, compSensorCnt_, stateField);
+
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+    ASSERT_EQ(stateField.size(), 1);
+    ASSERT_EQ(stateField[0].event_state, tSideNum);
+    ASSERT_EQ(stateField[0].sensor_op_state, PLDM_SENSOR_ENABLED);
+    ASSERT_EQ(stateField[0].present_state, PLDM_SENSOR_UNKNOWN);
+    ASSERT_EQ(stateField[0].previous_state, PLDM_SENSOR_UNKNOWN);
+
+    entityInstance_ = 1;
+
+    std::vector<get_sensor_state_field> stateField1;
+    rc = oemPlatformHandler->getOemStateSensorReadingsHandler(
+        entityID_, entityInstance_, stateSetId_, compSensorCnt_, stateField1);
+    ASSERT_EQ(stateField1.size(), 1);
+    ASSERT_EQ(stateField1[0].event_state, tSideNum);
+
+    entityInstance_ = 2;
+    rc = oemPlatformHandler->getOemStateSensorReadingsHandler(
+        entityID_, entityInstance_, stateSetId_, compSensorCnt_, stateField1);
+    ASSERT_EQ(stateField1[0].event_state, PLDM_SENSOR_UNKNOWN);
+
+    entityID_ = 40;
+    stateSetId_ = 50;
+    rc = oemPlatformHandler->getOemStateSensorReadingsHandler(
+        entityID_, entityInstance_, stateSetId_, compSensorCnt_, stateField1);
+    ASSERT_EQ(rc, PLDM_PLATFORM_INVALID_STATE_VALUE);
+
+    entityID_ = PLDM_ENTITY_VIRTUAL_MACHINE_MANAGER;
+    entityInstance_ = 0;
+    stateSetId_ = PLDM_OEM_IBM_BOOT_STATE;
+    compSensorCnt_ = 1;
+
+    std::vector<set_effecter_state_field> setEffecterStateField;
+    setEffecterStateField.push_back({PLDM_REQUEST_SET, pSideNum});
+
+    rc = oemPlatformHandler->oemSetStateEffecterStatesHandler(
+        entityID_, entityInstance_, stateSetId_, compSensorCnt_,
+        setEffecterStateField);
+    ASSERT_EQ(rc, PLDM_SUCCESS);
+
+    entityInstance_ = 2;
+    rc = oemPlatformHandler->oemSetStateEffecterStatesHandler(
+        entityID_, entityInstance_, stateSetId_, compSensorCnt_,
+        setEffecterStateField);
+
+    ASSERT_EQ(rc, PLDM_PLATFORM_INVALID_STATE_VALUE);
+
+    entityID_ = 34;
+    stateSetId_ = 99;
+    entityInstance_ = 0;
+    rc = oemPlatformHandler->oemSetStateEffecterStatesHandler(
+        entityID_, entityInstance_, stateSetId_, compSensorCnt_,
+        setEffecterStateField);
+    ASSERT_EQ(rc, PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE);
+}
diff --git a/pldmd/pldmd.cpp b/pldmd/pldmd.cpp
index c99ab18..7bf2aa4 100644
--- a/pldmd/pldmd.cpp
+++ b/pldmd/pldmd.cpp
@@ -13,6 +13,7 @@
 #include "libpldmresponder/base.hpp"
 #include "libpldmresponder/bios.hpp"
 #include "libpldmresponder/fru.hpp"
+#include "libpldmresponder/oem_handler.hpp"
 #include "libpldmresponder/platform.hpp"
 #include "xyz/openbmc_project/PLDM/Event/server.hpp"
 
@@ -42,6 +43,7 @@
 
 #ifdef OEM_IBM
 #include "libpldmresponder/file_io.hpp"
+#include "libpldmresponder/oem_ibm_handler.hpp"
 #endif
 
 constexpr uint8_t MCTP_MSG_TYPE_PLDM = 1;
@@ -193,6 +195,18 @@
     }
 
     Invoker invoker{};
+    std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
+
+#ifdef OEM_IBM
+    std::unique_ptr<pldm::responder::CodeUpdate> codeUpdate =
+        std::make_unique<pldm::responder::CodeUpdate>(dbusHandler.get());
+    oemPlatformHandler = std::make_unique<oem_ibm_platform::Handler>(
+        dbusHandler.get(), codeUpdate.get());
+
+    codeUpdate->setOemPlatformHandler(oemPlatformHandler.get());
+    invoker.registerHandler(
+        PLDM_OEM, std::make_unique<oem_ibm::Handler>(oemPlatformHandler.get()));
+#endif
     invoker.registerHandler(PLDM_BASE, std::make_unique<base::Handler>());
     invoker.registerHandler(PLDM_BIOS, std::make_unique<bios::Handler>(
                                            sockfd, hostEID, &dbusImplReq));
@@ -201,17 +215,20 @@
     // FRU table is built lazily when a FRU command or Get PDR command is
     // handled. To enable building FRU table, the FRU handler is passed to the
     // Platform handler.
-    invoker.registerHandler(
-        PLDM_PLATFORM, std::make_unique<platform::Handler>(
-                           dbusHandler.get(), PDR_JSONS_DIR, pdrRepo.get(),
-                           hostPDRHandler.get(), dbusToPLDMEventHandler.get(),
-                           fruHandler.get(), true));
-    invoker.registerHandler(PLDM_FRU, std::move(fruHandler));
-
+    auto platformHandler = std::make_unique<platform::Handler>(
+        dbusHandler.get(), PDR_JSONS_DIR, pdrRepo.get(), hostPDRHandler.get(),
+        dbusToPLDMEventHandler.get(), fruHandler.get(),
+        oemPlatformHandler.get(), true);
 #ifdef OEM_IBM
-    invoker.registerHandler(PLDM_OEM, std::make_unique<oem_ibm::Handler>());
+    pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler =
+        dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>(
+            oemPlatformHandler.get());
+    oemIbmPlatformHandler->setPlatformHandler(platformHandler.get());
 #endif
 
+    invoker.registerHandler(PLDM_PLATFORM, std::move(platformHandler));
+    invoker.registerHandler(PLDM_FRU, std::move(fruHandler));
+
     pldm::utils::CustomFD socketFd(sockfd);
 
     struct sockaddr_un addr
diff --git a/test/libpldmresponder_pdr_effecter_test.cpp b/test/libpldmresponder_pdr_effecter_test.cpp
index 77f59a5..0b91ee8 100644
--- a/test/libpldmresponder_pdr_effecter_test.cpp
+++ b/test/libpldmresponder_pdr_effecter_test.cpp
@@ -28,7 +28,7 @@
     auto outPDRRepo = pldm_pdr_init();
     Repo outRepo(outPDRRepo);
     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
 
@@ -127,7 +127,7 @@
     auto outPDRRepo = pldm_pdr_init();
     Repo outRepo(outPDRRepo);
     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, outRepo, PLDM_NUMERIC_EFFECTER_PDR);
 
@@ -173,7 +173,7 @@
     auto outPDRRepo = pldm_pdr_init();
     Repo outRepo(outPDRRepo);
     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
 
@@ -194,7 +194,7 @@
 
     auto inPDRRepo = pldm_pdr_init();
     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     uint16_t entityType = 33;
     uint16_t entityInstance = 0;
     uint16_t containerId = 0;
diff --git a/test/libpldmresponder_pdr_sensor_test.cpp b/test/libpldmresponder_pdr_sensor_test.cpp
index 6429fc6..ad844c1 100644
--- a/test/libpldmresponder_pdr_sensor_test.cpp
+++ b/test/libpldmresponder_pdr_sensor_test.cpp
@@ -33,7 +33,7 @@
     auto outPDRRepo = pldm_pdr_init();
     Repo outRepo(outPDRRepo);
     Handler handler(&mockedUtils, "./pdr_jsons/state_sensor/good", inPDRRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     handler.getPDR(req, requestPayloadLength);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
@@ -83,7 +83,7 @@
     auto outPDRRepo = pldm_pdr_init();
     Repo outRepo(outPDRRepo);
     Handler handler(&mockedUtils, "./pdr_jsons/state_sensor/good", inPDRRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     handler.getPDR(req, requestPayloadLength);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
diff --git a/test/libpldmresponder_platform_test.cpp b/test/libpldmresponder_platform_test.cpp
index 71fec26..0e6164b 100644
--- a/test/libpldmresponder_platform_test.cpp
+++ b/test/libpldmresponder_platform_test.cpp
@@ -40,7 +40,7 @@
 
     auto pdrRepo = pldm_pdr_init();
     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", pdrRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     Repo repo(pdrRepo);
     ASSERT_EQ(repo.empty(), false);
     auto response = handler.getPDR(req, requestPayloadLength);
@@ -77,7 +77,7 @@
 
     auto pdrRepo = pldm_pdr_init();
     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", pdrRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     Repo repo(pdrRepo);
     ASSERT_EQ(repo.empty(), false);
     auto response = handler.getPDR(req, requestPayloadLength);
@@ -108,7 +108,7 @@
 
     auto pdrRepo = pldm_pdr_init();
     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", pdrRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     Repo repo(pdrRepo);
     ASSERT_EQ(repo.empty(), false);
     auto response = handler.getPDR(req, requestPayloadLength);
@@ -137,7 +137,7 @@
 
     auto pdrRepo = pldm_pdr_init();
     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", pdrRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     Repo repo(pdrRepo);
     ASSERT_EQ(repo.empty(), false);
     auto response = handler.getPDR(req, requestPayloadLength);
@@ -168,7 +168,7 @@
 
     auto pdrRepo = pldm_pdr_init();
     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", pdrRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     Repo repo(pdrRepo);
     ASSERT_EQ(repo.empty(), false);
     auto response = handler.getPDR(req, requestPayloadLength);
@@ -230,7 +230,7 @@
     auto outPDRRepo = pldm_pdr_init();
     Repo outRepo(outPDRRepo);
     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     handler.getPDR(req, requestPayloadLength);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
@@ -276,7 +276,7 @@
     auto outPDRRepo = pldm_pdr_init();
     Repo outRepo(outPDRRepo);
     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     handler.getPDR(req, requestPayloadLength);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
@@ -321,7 +321,7 @@
     auto numericEffecterPdrRepo = pldm_pdr_init();
     Repo numericEffecterPDRs(numericEffecterPdrRepo);
     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
 
@@ -363,7 +363,7 @@
     auto numericEffecterPdrRepo = pldm_pdr_init();
     Repo numericEffecterPDRs(numericEffecterPdrRepo);
     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
 
@@ -535,7 +535,8 @@
     auto outPDRRepo = pldm_pdr_init();
     Repo outRepo(outPDRRepo);
     MockdBusHandler mockedUtils;
-    Handler handler(&mockedUtils, "", inPDRRepo, nullptr, nullptr, nullptr);
+    Handler handler(&mockedUtils, "", inPDRRepo, nullptr, nullptr, nullptr,
+                    nullptr);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, outRepo, PLDM_TERMINUS_LOCATOR_PDR);
 
@@ -579,7 +580,7 @@
     auto outPDRRepo = pldm_pdr_init();
     Repo outRepo(outPDRRepo);
     Handler handler(&mockedUtils, "./pdr_jsons/state_sensor/good", inPDRRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
     pdr_utils::PdrEntry e;
@@ -625,7 +626,7 @@
     auto outPDRRepo = pldm_pdr_init();
     Repo outRepo(outPDRRepo);
     Handler handler(&mockedUtils, "./pdr_jsons/state_sensor/good", inPDRRepo,
-                    nullptr, nullptr, nullptr);
+                    nullptr, nullptr, nullptr, nullptr);
     Repo inRepo(inPDRRepo);
     getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
     pdr_utils::PdrEntry e;
diff --git a/test/meson.build b/test/meson.build
index fd1a2ec..43de609 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -42,7 +42,8 @@
 
 if get_option('oem-ibm').enabled()
   tests += [
-    '../oem/ibm/test/libpldmresponder_fileio_test'
+    '../oem/ibm/test/libpldmresponder_fileio_test',
+    '../oem/ibm/test/libpldmresponder_oem_platform_test'
   ]
 endif