Wait for OCC Active PDR to become available

occ-control was attempting to communicate with OCCs before the OCC
Active sensor PDR was available. This commit will wait until all PDRs
are available before allowing communication with the OCCs.
It will also read the OCC Active sensor to determine the state before
allowing communication.

When Hostboot moves a system to safe mode it will set the PLDM state of
the OCC Active sensor to PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT
This commit will also handle processing of that DORMANT status.

Change-Id: I348cf14455d9373898deec2ac4a04b3752e81c4a
Signed-off-by: Chris Cain <cjcain@us.ibm.com>
diff --git a/utils.cpp b/utils.cpp
index e79bc5a..78b4234 100644
--- a/utils.cpp
+++ b/utils.cpp
@@ -1,10 +1,14 @@
 #include "utils.hpp"
 
 #include <fmt/core.h>
+#include <systemd/sd-event.h>
+#include <unistd.h>
 
 #include <phosphor-logging/elog-errors.hpp>
 #include <sdbusplus/bus.hpp>
 #include <xyz/openbmc_project/Common/error.hpp>
+#include <xyz/openbmc_project/State/Boot/Progress/server.hpp>
+#include <xyz/openbmc_project/State/Host/server.hpp>
 
 #include <string>
 namespace open_power
@@ -18,6 +22,10 @@
 using InternalFailure =
     sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
 
+using BootProgress = sdbusplus::xyz::openbmc_project::State::Boot::server::
+    Progress::ProgressStages;
+constexpr auto HOST_STATE_OBJ_PATH = "/xyz/openbmc_project/state/host0";
+
 const std::string getService(const std::string& path,
                              const std::string& interface)
 {
@@ -179,6 +187,79 @@
     return service;
 }
 
+std::string getStateValue(const std::string& intf, const std::string& objPath,
+                          const std::string& state)
+{
+    std::string stateVal;
+    try
+    {
+        auto& bus = getBus();
+        auto service = getService(objPath, intf);
+        if (service.empty())
+        {
+            throw std::runtime_error("getStateValue: Failed to get service");
+        }
+
+        auto method =
+            bus.new_method_call(service.c_str(), objPath.c_str(),
+                                "org.freedesktop.DBus.Properties", "Get");
+
+        method.append(intf, state);
+
+        auto reply = bus.call(method);
+
+        std::variant<std::string> propertyVal;
+
+        reply.read(propertyVal);
+
+        stateVal = std::get<std::string>(propertyVal);
+    }
+    catch (const sdbusplus::exception::exception& e)
+    {
+        log<level::ERR>(fmt::format("D-Bus call exception, OBJPATH({}), "
+                                    "INTERFACE({}), PROPERTY({}) EXCEPTION({})",
+                                    objPath, intf, state, e.what())
+                            .c_str());
+        throw std::runtime_error("Failed to get host state property");
+    }
+    catch (const std::bad_variant_access& e)
+    {
+        log<level::ERR>(
+            fmt::format("Exception raised while read host state({}) property "
+                        "value,  OBJPATH({}), INTERFACE({}), EXCEPTION({})",
+                        state, objPath, intf, e.what())
+                .c_str());
+        throw std::runtime_error("Failed to get host state property");
+    }
+
+    return stateVal;
+}
+
+BootProgress getBootProgress()
+{
+    BootProgress bootProgessStage;
+    constexpr auto bootProgressInterface =
+        "xyz.openbmc_project.State.Boot.Progress";
+    std::string value = getStateValue(bootProgressInterface,
+                                      HOST_STATE_OBJ_PATH, "BootProgress");
+    bootProgessStage = sdbusplus::xyz::openbmc_project::State::Boot::server::
+        Progress::convertProgressStagesFromString(value);
+    return bootProgessStage;
+}
+
+bool isHostRunning()
+{
+    BootProgress bootProgressStatus = getBootProgress();
+    if ((bootProgressStatus == BootProgress::SystemInitComplete) ||
+        (bootProgressStatus == BootProgress::SystemSetup) ||
+        (bootProgressStatus == BootProgress::OSStart) ||
+        (bootProgressStatus == BootProgress::OSRunning))
+    {
+        return true;
+    }
+    return false;
+}
+
 } // namespace utils
 } // namespace occ
 } // namespace open_power