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/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