Add safe mode to user interface

putting in code that puts safe mode onto dbus.
Tested: inject error that puts in safe mode, dbus CMD
to read dbus safeMode.
Signed-off-by: Sheldon Bailey <baileysh@us.ibm.com>
Change-Id: I48c5b41a48d0883a8d1e2916da8725391a7bcbc2
diff --git a/occ_manager.cpp b/occ_manager.cpp
index 1efb1e5..2ea0b5b 100644
--- a/occ_manager.cpp
+++ b/occ_manager.cpp
@@ -502,6 +502,14 @@
     }
 }
 
+// Called upon pldm event To set powermode Safe Mode State for system.
+void Manager::updateOccSafeMode(bool safeMode)
+{
+#ifdef POWER10
+    pmode->updateDbusSafeMode(safeMode);
+#endif
+}
+
 void Manager::sbeHRESETResult(instanceID instance, bool success)
 {
     if (success)
@@ -1309,6 +1317,9 @@
             fmt::format("validateOccMaster: OCC{} is master of {} OCCs",
                         masterInstance, activeCount)
                 .c_str());
+#ifdef POWER10
+        pmode->updateDbusSafeMode(false);
+#endif
     }
 }
 
diff --git a/occ_manager.hpp b/occ_manager.hpp
index 65d7545..d0b01b3 100644
--- a/occ_manager.hpp
+++ b/occ_manager.hpp
@@ -95,6 +95,8 @@
                       std::placeholders::_1, std::placeholders::_2),
             std::bind(std::mem_fn(&Manager::sbeHRESETResult), this,
                       std::placeholders::_1, std::placeholders::_2),
+            std::bind(std::mem_fn(&Manager::updateOccSafeMode), this,
+                      std::placeholders::_1),
             event))
 #endif
 #ifdef POWER10
@@ -268,6 +270,11 @@
      */
     bool updateOCCActive(instanceID instance, bool status);
 
+    /** @brief Callback handler invoked by the PLDM event handler when mode of
+     *         the OCC SAFE MODE is inacted or cleared.
+     */
+    void updateOccSafeMode(bool safeState);
+
     /** @brief Callback handler invoked by PLDM sensor change when
      *         the HRESET succeeds or fails.
      *
diff --git a/pldm.cpp b/pldm.cpp
index 41552ef..6e3dfe6 100644
--- a/pldm.cpp
+++ b/pldm.cpp
@@ -165,6 +165,7 @@
                 log<level::INFO>(
                     fmt::format("PLDM: OCC{} is RUNNING", sensorEntry->second)
                         .c_str());
+
                 callBack(sensorEntry->second, true);
             }
             else if (eventState ==
@@ -185,6 +186,10 @@
                         "PLDM: OCC{} has now STOPPED and system is in SAFE MODE",
                         sensorEntry->second)
                         .c_str());
+
+                // Setting safe mode true
+                safeModeCallBack(true);
+
                 callBack(sensorEntry->second, false);
             }
             else
@@ -718,6 +723,10 @@
                 "pldmRspCallback: OCC{} has now STOPPED and system is in SAFE MODE",
                 instance)
                 .c_str());
+
+        // Setting safe mode true
+        pldmIface->safeModeCallBack(true);
+
         pldmIface->callBack(instance, false);
     }
     else
diff --git a/pldm.hpp b/pldm.hpp
index 945d7a1..40bc78b 100644
--- a/pldm.hpp
+++ b/pldm.hpp
@@ -58,9 +58,10 @@
     explicit Interface(
         std::function<bool(open_power::occ::instanceID, bool)> callBack,
         std::function<void(open_power::occ::instanceID, bool)> sbeCallBack,
-        EventPtr& event) :
+        std::function<void(bool)> safeModeCallBack, EventPtr& event) :
         callBack(callBack),
-        sbeCallBack(sbeCallBack), event(event),
+        sbeCallBack(sbeCallBack), safeModeCallBack(safeModeCallBack),
+        event(event),
         pldmEventSignal(
             open_power::occ::utils::getBus(),
             MatchRules::type::signal() +
@@ -154,6 +155,11 @@
     std::function<void(open_power::occ::instanceID, bool)> sbeCallBack =
         nullptr;
 
+    /** @brief Callback handler to be invoked when the OCC is in SAFE Mode =
+     *         true or when OCCs are in_service = false.
+     */
+    std::function<void(bool)> safeModeCallBack = nullptr;
+
     /** @brief reference to sd_event wrapped in unique_ptr */
     EventPtr& event;
 
diff --git a/powermode.cpp b/powermode.cpp
index f091088..5d2e258 100644
--- a/powermode.cpp
+++ b/powermode.cpp
@@ -1062,6 +1062,18 @@
 }
 #endif
 
+/*  Set dbus property to SAFE mode(true) or clear(false) only if different */
+void PowerMode::updateDbusSafeMode(const bool safeModeReq)
+{
+    log<level::DEBUG>(
+        fmt::format("PowerMode:updateDbusSafeMode: Update dbus state ({})",
+                    safeModeReq)
+            .c_str());
+
+    // Note; this function checks and only updates if different.
+    Mode::safeMode(safeModeReq);
+}
+
 } // namespace powermode
 
 } // namespace occ
diff --git a/powermode.hpp b/powermode.hpp
index dbd68eb..f0aca51 100644
--- a/powermode.hpp
+++ b/powermode.hpp
@@ -35,6 +35,7 @@
 constexpr auto PMODE_PATH = "/xyz/openbmc_project/control/host0/power_mode";
 constexpr auto PMODE_INTERFACE = "xyz.openbmc_project.Control.Power.Mode";
 constexpr auto POWER_MODE_PROP = "PowerMode";
+constexpr auto POWER_SAFE_MODE_PROP = "SafeMode";
 
 constexpr auto PIPS_PATH = "/xyz/openbmc_project/control/host0/power_ips";
 constexpr auto PIPS_INTERFACE =
@@ -331,6 +332,9 @@
     void removeIpsWatch();
 #endif
 
+    /** @brief Set dbus property to SAFE Mode(true) or clear SAFE Mode(false)*/
+    void updateDbusSafeMode(const bool safeMode);
+
   private:
     /** @brief OCC manager object */
     const Manager& manager;