oem ibm: marker LID validation

This commit adds code for writing marker LID
from Host and also send a PlatformEventMessage
after validation.

This commit also subscribes for the interface added
signal to fetch the new image id and sends the relevant
sensor event to host

Change-Id: I92476beca18e6dd255f372dd82d6eaeca18e282c
Signed-off-by: Sampa Misra <sampmisr@in.ibm.com>
diff --git a/oem/ibm/libpldmresponder/file_io_by_type.cpp b/oem/ibm/libpldmresponder/file_io_by_type.cpp
index 43c2b91..bdc1332 100644
--- a/oem/ibm/libpldmresponder/file_io_by_type.cpp
+++ b/oem/ibm/libpldmresponder/file_io_by_type.cpp
@@ -142,6 +142,12 @@
             return std::make_unique<LidHandler>(fileHandle, false);
             break;
         }
+        case PLDM_FILE_TYPE_LID_MARKER:
+        {
+            return std::make_unique<LidHandler>(fileHandle, false,
+                                                PLDM_FILE_TYPE_LID_MARKER);
+            break;
+        }
         case PLDM_FILE_TYPE_DUMP:
         {
             return std::make_unique<DumpHandler>(fileHandle);
diff --git a/oem/ibm/libpldmresponder/file_io_type_lid.hpp b/oem/ibm/libpldmresponder/file_io_type_lid.hpp
index 531d762..4f42e34 100644
--- a/oem/ibm/libpldmresponder/file_io_type_lid.hpp
+++ b/oem/ibm/libpldmresponder/file_io_type_lid.hpp
@@ -16,6 +16,8 @@
 using namespace pldm::responder::dma;
 namespace fs = std::filesystem;
 
+using MarkerLIDremainingSize = uint64_t;
+
 /** @class LidHandler
  *
  *  @brief Inherits and implements FileHandler. This class is used
@@ -26,7 +28,8 @@
   public:
     /** @brief LidHandler constructor
      */
-    LidHandler(uint32_t fileHandle, bool permSide) : FileHandler(fileHandle)
+    LidHandler(uint32_t fileHandle, bool permSide, uint8_t lidType = 0) :
+        FileHandler(fileHandle), lidType(lidType)
     {
         sideToRead = permSide ? Pside : Tside;
         isPatchDir = false;
@@ -94,12 +97,16 @@
                                 uint64_t address,
                                 oem_platform::Handler* oemPlatformHandler)
     {
+        int rc = PLDM_SUCCESS;
+        bool codeUpdateInProgress = false;
         if (oemPlatformHandler != nullptr)
         {
             pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler =
                 dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>(
                     oemPlatformHandler);
-            if (oemIbmPlatformHandler->codeUpdate->isCodeUpdateInProgress())
+            codeUpdateInProgress =
+                oemIbmPlatformHandler->codeUpdate->isCodeUpdateInProgress();
+            if (codeUpdateInProgress || lidType == PLDM_FILE_TYPE_LID_MARKER)
             {
                 std::string dir = LID_STAGING_DIR;
                 std::stringstream stream;
@@ -108,9 +115,6 @@
                 lidPath = std::move(dir) + '/' + lidName;
             }
         }
-        std::cout << "got writeFromMemory() for LID " << lidPath.c_str()
-                  << " and offset " << offset << " and length " << length
-                  << "\n";
         bool fileExists = fs::exists(lidPath);
         int flags{};
         if (fileExists)
@@ -130,12 +134,34 @@
         }
         close(fd);
 
-        auto rc = transferFileData(lidPath, false, offset, length, address);
+        rc = transferFileData(lidPath, false, offset, length, address);
         if (rc != PLDM_SUCCESS)
         {
-            std::cout << "writeFileFromMemory failed with rc= " << rc << " \n";
+            std::cerr << "writeFileFromMemory failed with rc= " << rc << " \n";
             return rc;
         }
+        if (lidType == PLDM_FILE_TYPE_LID_MARKER)
+        {
+            markerLIDremainingSize -= length;
+            if (markerLIDremainingSize == 0)
+            {
+                pldm::responder::oem_ibm_platform::Handler*
+                    oemIbmPlatformHandler = dynamic_cast<
+                        pldm::responder::oem_ibm_platform::Handler*>(
+                        oemPlatformHandler);
+                auto sensorId =
+                    oemIbmPlatformHandler->codeUpdate->getMarkerLidSensor();
+                using namespace pldm::responder::oem_ibm_platform;
+                oemIbmPlatformHandler->sendStateSensorEvent(
+                    sensorId, PLDM_STATE_SENSOR_STATE, 0, VALID, VALID);
+                // rc = validate api;
+                rc = PLDM_SUCCESS;
+            }
+        }
+        else if (codeUpdateInProgress)
+        {
+            rc = processCodeUpdateLid(lidPath);
+        }
         return rc;
     }
 
@@ -153,12 +179,16 @@
     virtual int write(const char* buffer, uint32_t offset, uint32_t& length,
                       oem_platform::Handler* oemPlatformHandler)
     {
+        int rc = PLDM_SUCCESS;
+        bool codeUpdateInProgress = false;
         if (oemPlatformHandler != nullptr)
         {
             pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler =
                 dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>(
                     oemPlatformHandler);
-            if (oemIbmPlatformHandler->codeUpdate->isCodeUpdateInProgress())
+            codeUpdateInProgress =
+                oemIbmPlatformHandler->codeUpdate->isCodeUpdateInProgress();
+            if (codeUpdateInProgress || lidType == PLDM_FILE_TYPE_LID_MARKER)
             {
                 std::string dir = LID_STAGING_DIR;
                 std::stringstream stream;
@@ -167,9 +197,6 @@
                 lidPath = std::move(dir) + '/' + lidName;
             }
         }
-        std::cout << "got write() call for LID " << lidPath.c_str()
-                  << " and offset " << offset << " and length " << length
-                  << "\n";
         bool fileExists = fs::exists(lidPath);
         int flags{};
         if (fileExists)
@@ -198,14 +225,13 @@
             std::cerr << "could not open file " << lidPath.c_str() << "\n";
             return PLDM_ERROR;
         }
-        auto rc = lseek(fd, offset, SEEK_SET);
+        rc = lseek(fd, offset, SEEK_SET);
         if (rc == -1)
         {
             std::cerr << "lseek failed, ERROR=" << errno
                       << ", OFFSET=" << offset << "\n";
             return PLDM_ERROR;
         }
-        std::cout << "lseek returned " << rc << "\n";
         rc = ::write(fd, buffer, length);
         if (rc == -1)
         {
@@ -214,6 +240,30 @@
             return PLDM_ERROR;
         }
         close(fd);
+
+        if (lidType == PLDM_FILE_TYPE_LID_MARKER)
+        {
+            markerLIDremainingSize -= length;
+            if (markerLIDremainingSize == 0)
+            {
+                pldm::responder::oem_ibm_platform::Handler*
+                    oemIbmPlatformHandler = dynamic_cast<
+                        pldm::responder::oem_ibm_platform::Handler*>(
+                        oemPlatformHandler);
+                auto sensorId =
+                    oemIbmPlatformHandler->codeUpdate->getMarkerLidSensor();
+                using namespace pldm::responder::oem_ibm_platform;
+                oemIbmPlatformHandler->sendStateSensorEvent(
+                    sensorId, PLDM_STATE_SENSOR_STATE, 0, VALID, VALID);
+                // validate api
+                rc = PLDM_SUCCESS;
+            }
+        }
+        else if (codeUpdateInProgress)
+        {
+            rc = processCodeUpdateLid(lidPath);
+        }
+
         return rc;
     }
 
@@ -232,9 +282,14 @@
         return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
     }
 
-    virtual int newFileAvailable(uint64_t /*length*/)
+    virtual int newFileAvailable(uint64_t length)
 
     {
+        if (lidType == PLDM_FILE_TYPE_LID_MARKER)
+        {
+            markerLIDremainingSize = length;
+            return PLDM_SUCCESS;
+        }
         return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
     }
 
@@ -247,6 +302,8 @@
     std::string lidPath;
     std::string sideToRead;
     bool isPatchDir;
+    static inline MarkerLIDremainingSize markerLIDremainingSize;
+    uint8_t lidType;
 };
 
 } // namespace responder
diff --git a/oem/ibm/libpldmresponder/inband_code_update.cpp b/oem/ibm/libpldmresponder/inband_code_update.cpp
index bb06882..fab3023 100644
--- a/oem/ibm/libpldmresponder/inband_code_update.cpp
+++ b/oem/ibm/libpldmresponder/inband_code_update.cpp
@@ -211,8 +211,40 @@
                 if (interface.first ==
                     "xyz.openbmc_project.Software.Activation")
                 {
-                    newImageId = path.str;
-                    break;
+                    auto imageInterface =
+                        "xyz.openbmc_project.Software.Activation";
+                    auto imageObjPath = path.str.c_str();
+                    try
+                    {
+                        auto propVal = dBusIntf->getDbusPropertyVariant(
+                            imageObjPath, "Activation", imageInterface);
+                        const auto& imageProp = std::get<std::string>(propVal);
+                        if (imageProp == "xyz.openbmc_project.Software."
+                                         "Activation.Activations.Ready" &&
+                            isCodeUpdateInProgress())
+                        {
+                            newImageId = path.str;
+                            auto rc = setRequestedActivation();
+                            CodeUpdateState state = CodeUpdateState::END;
+                            if (rc != PLDM_SUCCESS)
+                            {
+                                state = CodeUpdateState::FAIL;
+                                std::cerr
+                                    << "could not set RequestedActivation \n";
+                            }
+                            setCodeUpdateProgress(false);
+                            auto sensorId = getFirmwareUpdateSensor();
+                            sendStateSensorEvent(
+                                sensorId, PLDM_STATE_SENSOR_STATE, 0,
+                                uint8_t(state),
+                                uint8_t(CodeUpdateState::START));
+                            break;
+                        }
+                    }
+                    catch (const sdbusplus::exception::SdBusError& e)
+                    {
+                        std::cerr << "Error in getting Activation status \n";
+                    }
                 }
             }
         });
@@ -247,6 +279,39 @@
     return;
 }
 
+void CodeUpdate::sendStateSensorEvent(
+    uint16_t sensorId, enum sensor_event_class_states sensorEventClass,
+    uint8_t sensorOffset, uint8_t eventState, uint8_t prevEventState)
+{
+    pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler =
+        dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>(
+            oemPlatformHandler);
+    oemIbmPlatformHandler->sendStateSensorEvent(
+        sensorId, sensorEventClass, sensorOffset, eventState, prevEventState);
+}
+
+void CodeUpdate::deleteImage()
+{
+    static constexpr auto UPDATER_SERVICE =
+        "xyz.openbmc_project.Software.BMC.Updater";
+    static constexpr auto SW_OBJ_PATH = "/xyz/openbmc_project/software";
+    static constexpr auto DELETE_INTF =
+        "xyz.openbmc_project.Collection.DeleteAll";
+
+    auto& bus = dBusIntf->getBus();
+    try
+    {
+        auto method = bus.new_method_call(UPDATER_SERVICE, SW_OBJ_PATH,
+                                          DELETE_INTF, "DeleteAll");
+        bus.call_noreply(method);
+    }
+    catch (const std::exception& e)
+    {
+        std::cerr << "Failed to delete image, ERROR=" << e.what() << "\n";
+        return;
+    }
+}
+
 uint8_t fetchBootSide(uint16_t entityInstance, CodeUpdate* codeUpdate)
 {
     uint8_t sensorOpState = tSideNum;
diff --git a/oem/ibm/libpldmresponder/inband_code_update.hpp b/oem/ibm/libpldmresponder/inband_code_update.hpp
index 77ada56..77f55f1 100644
--- a/oem/ibm/libpldmresponder/inband_code_update.hpp
+++ b/oem/ibm/libpldmresponder/inband_code_update.hpp
@@ -37,6 +37,8 @@
     {
         currBootSide = Tside;
         nextBootSide = Tside;
+        markerLidSensorId = PLDM_INVALID_EFFECTER_ID;
+        firmwareUpdateSensorId = PLDM_INVALID_EFFECTER_ID;
     }
 
     /* @brief Method to return the current boot side
@@ -115,6 +117,57 @@
      */
     int setRequestedActivation();
 
+    /* @brief Method to fetch the sensor id for marker lid
+     * validation PDR
+     * @return - sensor id
+     */
+    uint16_t getMarkerLidSensor()
+    {
+        return markerLidSensorId;
+    }
+
+    /* @brief Method to set the sensor id for marker lid
+     * validation
+     * @param[in] sensorId - sensor id for marker lid validation
+     */
+    void setMarkerLidSensor(uint16_t sensorId)
+    {
+        markerLidSensorId = sensorId;
+    }
+
+    /* @brief Method to set the sensor id for firmware update state
+     * @param[in] sensorId - sensor id for firmware update state
+     */
+    void setFirmwareUpdateSensor(uint16_t sensorId)
+    {
+        firmwareUpdateSensorId = sensorId;
+    }
+
+    /* @brief Method to fetch the sensor id for firmware update state
+     * @return - sensor id
+     */
+    uint16_t getFirmwareUpdateSensor()
+    {
+        return firmwareUpdateSensorId;
+    }
+
+    /* @brief Method to send a state sensor event to Host from CodeUpdate class
+     * @param[in] sensorId - sensor id for the event
+     * @param[in] sensorEventClass - sensor event class wrt DSP0248
+     * @param[in] sensorOffset - sensor offset
+     * @param[in] eventState - new event state
+     * @param[in] prevEventState - previous state
+     */
+    void sendStateSensorEvent(uint16_t sensorId,
+                              enum sensor_event_class_states sensorEventClass,
+                              uint8_t sensorOffset, uint8_t eventState,
+                              uint8_t prevEventState);
+
+    /* @brief Method to delete the image from non running side prior to
+     * an inband code update
+     */
+    void deleteImage();
+
     virtual ~CodeUpdate()
     {}
 
@@ -135,13 +188,14 @@
                          //!< new image
     pldm::responder::oem_platform::Handler*
         oemPlatformHandler; //!< oem platform handler
+    uint16_t markerLidSensorId;
+    uint16_t firmwareUpdateSensorId;
 
     /* @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);
 };
diff --git a/oem/ibm/libpldmresponder/oem_ibm_handler.cpp b/oem/ibm/libpldmresponder/oem_ibm_handler.cpp
index 09a46a5..2f06bc5 100644
--- a/oem/ibm/libpldmresponder/oem_ibm_handler.cpp
+++ b/oem/ibm/libpldmresponder/oem_ibm_handler.cpp
@@ -42,7 +42,7 @@
 }
 
 int pldm::responder::oem_ibm_platform::Handler::
-    OemSetStateEffecterStatesHandler(
+    oemSetStateEffecterStatesHandler(
         uint16_t entityType, uint16_t entityInstance, uint16_t stateSetId,
         uint8_t compEffecterCnt,
         std::vector<set_effecter_state_field>& stateField,
@@ -67,28 +67,57 @@
                     uint8_t(CodeUpdateState::START))
                 {
                     codeUpdate->setCodeUpdateProgress(true);
-                    rc = codeUpdate->setRequestedApplyTime();
+                    startUpdateEvent =
+                        std::make_unique<sdeventplus::source::Defer>(
+                            event,
+                            std::bind(std::mem_fn(&oem_ibm_platform::Handler::
+                                                      _processStartUpdate),
+                                      this, std::placeholders::_1));
                 }
                 else if (stateField[currState].effecter_state ==
                          uint8_t(CodeUpdateState::END))
                 {
-                    codeUpdate->setCodeUpdateProgress(false);
+                    rc = PLDM_SUCCESS;
+                    assembleImageEvent = std::make_unique<
+                        sdeventplus::source::Defer>(
+                        event,
+                        std::bind(
+                            std::mem_fn(
+                                &oem_ibm_platform::Handler::_processEndUpdate),
+                            this, std::placeholders::_1));
+
+                    // sendCodeUpdateEvent(effecterId, END, START);
                 }
                 else if (stateField[currState].effecter_state ==
                          uint8_t(CodeUpdateState::ABORT))
                 {
                     codeUpdate->setCodeUpdateProgress(false);
                     codeUpdate->clearDirPath(LID_STAGING_DIR);
+                    auto sensorId = codeUpdate->getFirmwareUpdateSensor();
+                    sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
+                                         uint8_t(CodeUpdateState::ABORT),
+                                         uint8_t(CodeUpdateState::START));
+                    // sendCodeUpdateEvent(effecterId, ABORT, END);
                 }
                 else if (stateField[currState].effecter_state ==
                          uint8_t(CodeUpdateState::ACCEPT))
                 {
+                    auto sensorId = codeUpdate->getFirmwareUpdateSensor();
+                    sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
+                                         uint8_t(CodeUpdateState::ACCEPT),
+                                         uint8_t(CodeUpdateState::END));
                     // TODO Set new Dbus property provided by code update app
+                    // sendCodeUpdateEvent(effecterId, ACCEPT, END);
                 }
                 else if (stateField[currState].effecter_state ==
                          uint8_t(CodeUpdateState::REJECT))
                 {
+                    auto sensorId = codeUpdate->getFirmwareUpdateSensor();
+                    sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
+                                         uint8_t(CodeUpdateState::REJECT),
+                                         uint8_t(CodeUpdateState::END));
                     // TODO Set new Dbus property provided by code update app
+                    // sendCodeUpdateEvent(effecterId, REJECT, END);
                 }
             }
             else
@@ -153,8 +182,8 @@
 }
 
 void buildAllCodeUpdateSensorPDR(platform::Handler* platformHandler,
-                                 uint16_t entityInstance, uint16_t stateSetID,
-                                 pdr_utils::Repo& repo)
+                                 uint16_t entityType, uint16_t entityInstance,
+                                 uint16_t stateSetID, pdr_utils::Repo& repo)
 {
     size_t pdrSize = 0;
     pdrSize =
@@ -175,7 +204,7 @@
     pdr->hdr.length = sizeof(pldm_state_sensor_pdr) - sizeof(pldm_pdr_hdr);
     pdr->terminus_handle = pdr::BmcPldmTerminusHandle;
     pdr->sensor_id = platformHandler->getNextSensorId();
-    pdr->entity_type = PLDM_ENTITY_VIRTUAL_MACHINE_MANAGER;
+    pdr->entity_type = entityType;
     pdr->entity_instance = entityInstance;
     pdr->container_id = 0;
     pdr->sensor_init = PLDM_NO_INIT;
@@ -189,7 +218,8 @@
     possibleStates->possible_states_size = 2;
     auto state =
         reinterpret_cast<state_sensor_possible_states*>(possibleStates);
-    if (stateSetID == PLDM_OEM_IBM_BOOT_STATE)
+    if ((stateSetID == PLDM_OEM_IBM_BOOT_STATE) ||
+        (stateSetID == oem_ibm_platform::PLDM_OEM_IBM_VERIFICATION_STATE))
         state->states[0].byte = 6;
     else if (stateSetID == PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE)
         state->states[0].byte = 126;
@@ -209,12 +239,26 @@
     buildAllCodeUpdateEffecterPDR(platformHandler, ENTITY_INSTANCE_0,
                                   PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE, repo);
 
-    buildAllCodeUpdateSensorPDR(platformHandler, ENTITY_INSTANCE_0,
-                                PLDM_OEM_IBM_BOOT_STATE, repo);
-    buildAllCodeUpdateSensorPDR(platformHandler, ENTITY_INSTANCE_1,
-                                PLDM_OEM_IBM_BOOT_STATE, repo);
-    buildAllCodeUpdateSensorPDR(platformHandler, ENTITY_INSTANCE_0,
-                                PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE, repo);
+    buildAllCodeUpdateSensorPDR(
+        platformHandler, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE, ENTITY_INSTANCE_0,
+        PLDM_OEM_IBM_BOOT_STATE, repo);
+    buildAllCodeUpdateSensorPDR(
+        platformHandler, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE, ENTITY_INSTANCE_1,
+        PLDM_OEM_IBM_BOOT_STATE, repo);
+    buildAllCodeUpdateSensorPDR(
+        platformHandler, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE, ENTITY_INSTANCE_0,
+        PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE, repo);
+    buildAllCodeUpdateSensorPDR(
+        platformHandler, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE, ENTITY_INSTANCE_0,
+        PLDM_OEM_IBM_VERIFICATION_STATE, repo);
+    auto sensorId = findStateSensorId(
+        repo.getPdr(), 0, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
+        ENTITY_INSTANCE_0, 0, PLDM_OEM_IBM_VERIFICATION_STATE);
+    codeUpdate->setMarkerLidSensor(sensorId);
+    sensorId = findStateSensorId(
+        repo.getPdr(), 0, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE,
+        ENTITY_INSTANCE_0, 0, PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE);
+    codeUpdate->setFirmwareUpdateSensor(sensorId);
 }
 
 void pldm::responder::oem_ibm_platform::Handler::setPlatformHandler(
@@ -265,7 +309,18 @@
                   << "\n";
         return rc;
     }
-    std::cout << "returning rc= " << rc << " from sendEventToHost \n";
+    return rc;
+}
+
+int encodeEventMsg(uint8_t eventType, const std::vector<uint8_t>& eventDataVec,
+                   std::vector<uint8_t>& requestMsg, uint8_t instanceId)
+{
+    auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+    auto rc = encode_platform_event_message_req(
+        instanceId, 1 /*formatVersion*/, 0 /*tId*/, eventType,
+        eventDataVec.data(), eventDataVec.size(), request,
+        eventDataVec.size() + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
 
     return rc;
 }
@@ -311,21 +366,37 @@
     return;
 }
 
-int encodeEventMsg(uint8_t eventType, const std::vector<uint8_t>& eventDataVec,
-                   std::vector<uint8_t>& requestMsg, uint8_t instanceId)
+void pldm::responder::oem_ibm_platform::Handler::_processEndUpdate(
+    sdeventplus::source::EventBase& /*source */)
 {
-    auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+    assembleImageEvent.reset();
+    int retc = assembleCodeUpdateImage();
+    if (retc != PLDM_SUCCESS)
+    {
+        codeUpdate->setCodeUpdateProgress(false);
+        auto sensorId = codeUpdate->getFirmwareUpdateSensor();
+        sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0,
+                             uint8_t(CodeUpdateState::FAIL),
+                             uint8_t(CodeUpdateState::START));
+    }
+}
 
-    auto rc = encode_platform_event_message_req(
-        instanceId, 1 /*formatVersion*/, pldm::responder::pdr::BmcTerminusId,
-        eventType, eventDataVec.data(), eventDataVec.size(), request,
-        eventDataVec.size() + PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES);
-
-    return rc;
+void pldm::responder::oem_ibm_platform::Handler::_processStartUpdate(
+    sdeventplus::source::EventBase& /*source */)
+{
+    codeUpdate->deleteImage();
+    CodeUpdateState state = CodeUpdateState::START;
+    auto rc = codeUpdate->setRequestedApplyTime();
+    if (rc != PLDM_SUCCESS)
+    {
+        std::cerr << "setRequestedApplyTime failed \n";
+        state = CodeUpdateState::FAIL;
+    }
+    auto sensorId = codeUpdate->getFirmwareUpdateSensor();
+    sendStateSensorEvent(sensorId, PLDM_STATE_SENSOR_STATE, 0, uint8_t(state),
+                         uint8_t(CodeUpdateState::END));
 }
 
 } // 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
index f8d261d..854c96b 100644
--- a/oem/ibm/libpldmresponder/oem_ibm_handler.hpp
+++ b/oem/ibm/libpldmresponder/oem_ibm_handler.hpp
@@ -17,6 +17,7 @@
 #define PLDM_OEM_IBM_BOOT_STATE 32769
 
 static constexpr auto PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE = 24577;
+static constexpr auto PLDM_OEM_IBM_VERIFICATION_STATE = 32770;
 constexpr uint16_t ENTITY_INSTANCE_0 = 0;
 constexpr uint16_t ENTITY_INSTANCE_1 = 1;
 
@@ -30,15 +31,23 @@
     REJECT = 0x6
 };
 
+enum VerificationStateValues
+{
+    VALID = 0x0,
+    ENTITLEMENT_FAIL = 0x1,
+    BANNED_PLATFORM_FAIL = 0x2,
+    MIN_MIF_FAIL = 0x4,
+};
+
 class Handler : public oem_platform::Handler
 {
   public:
     Handler(const pldm::utils::DBusHandler* dBusIntf,
             pldm::responder::CodeUpdate* codeUpdate, int mctp_fd,
-            uint8_t mctp_eid, Requester& requester) :
+            uint8_t mctp_eid, Requester& requester, sdeventplus::Event& event) :
         oem_platform::Handler(dBusIntf),
         codeUpdate(codeUpdate), platformHandler(nullptr), mctp_fd(mctp_fd),
-        mctp_eid(mctp_eid), requester(requester)
+        mctp_eid(mctp_eid), requester(requester), event(event)
     {
         codeUpdate->setVersions();
     }
@@ -48,7 +57,7 @@
         StateSetId stateSetId, CompositeCount compSensorCnt,
         std::vector<get_sensor_state_field>& stateField);
 
-    int OemSetStateEffecterStatesHandler(
+    int oemSetStateEffecterStatesHandler(
         uint16_t entityType, uint16_t entityInstance, uint16_t stateSetId,
         uint8_t compEffecterCnt,
         std::vector<set_effecter_state_field>& stateField, uint16_t effecterId);
@@ -104,6 +113,20 @@
      */
     int sendEventToHost(std::vector<uint8_t>& requestMsg);
 
+    /** @brief _processEndUpdate processes the actual work that needs
+     *  to be carried out after EndUpdate effecter is set. This is done async
+     *  after sending response for EndUpdate set effecter
+     *  @param[in] source - sdeventplus event source
+     */
+    void _processEndUpdate(sdeventplus::source::EventBase& source);
+
+    /** @brief _processStartUpdate processes the actual work that needs
+     *  to be carried out after StartUpdate effecter is set. This is done async
+     *  after sending response for StartUpdate set effecter
+     *  @param[in] source - sdeventplus event source
+     */
+    void _processStartUpdate(sdeventplus::source::EventBase& source);
+
     ~Handler() = default;
 
     pldm::responder::CodeUpdate* codeUpdate; //!< pointer to CodeUpdate object
@@ -120,6 +143,14 @@
      *  obtain PLDM instance id.
      */
     Requester& requester;
+    /** @brief sdeventplus event source */
+    std::unique_ptr<sdeventplus::source::Defer> assembleImageEvent;
+    std::unique_ptr<sdeventplus::source::Defer> startUpdateEvent;
+
+    /** @brief reference of main event loop of pldmd, primarily used to schedule
+     *  work
+     */
+    sdeventplus::Event& event;
 };
 
 /** @brief Method to encode code update event msg