bmc-reset: ensure chassis power on target complete

This logic will potentially launch the obmc-host-quiesce@.target so
ensure the transition to chassis power on has completed before
initiating this new target.

Its a fairly complex scenario but basically this service is only
launched in scenarios where the BMC comes out of reset and pgood is on.
In that situation, the state management code creates a file,
/run/openbmc/obmc-chassis@0-on, and starts the
obmc-chassis-poweron@.target. Once all services have started as a part
of this target, the /run/openbmc/obmc-chassis@0-on file is deleted and
the CurrentPowerState is set to On. At this point, we want this new
logic to check if a host firmware boot was occurring prior to reboot and
if so, log an error and put system in Quiesce state to run recovery.

Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
Change-Id: Id477557e2bd0bf0ad9ae3486338562961da153b5
diff --git a/host_reset_recovery.cpp b/host_reset_recovery.cpp
index b965ad8..529e298 100644
--- a/host_reset_recovery.cpp
+++ b/host_reset_recovery.cpp
@@ -1,3 +1,5 @@
+#include "config.h"
+
 #include <unistd.h>
 
 #include <phosphor-logging/elog.hpp>
@@ -8,6 +10,7 @@
 #include <xyz/openbmc_project/Logging/Entry/server.hpp>
 
 #include <cstdlib>
+#include <fstream>
 #include <string>
 
 constexpr auto HOST_STATE_SVC = "xyz.openbmc_project.State.Host";
@@ -97,14 +100,38 @@
     }
 }
 
+// Once CHASSIS_ON_FILE is removed, the obmc-chassis-poweron@.target has
+// completed and the phosphor-chassis-state-manager code has processed it.
+bool isChassisTargetComplete()
+{
+    auto size = std::snprintf(nullptr, 0, CHASSIS_ON_FILE, 0);
+    size++; // null
+    std::unique_ptr<char[]> buf(new char[size]);
+    std::snprintf(buf.get(), size, CHASSIS_ON_FILE, 0);
+
+    std::ifstream f(buf.get());
+    return !f.good();
+}
+
 int main()
 {
 
     auto bus = sdbusplus::bus::new_default();
 
-    // This application will only be started if chassis power is on and the
-    // host is not responding after a BMC reboot.
-    // TODO Wait for chassis power on target to complete
+    // Chassis power is on if this service starts but need to wait for the
+    // obmc-chassis-poweron@.target to complete before potentially initiating
+    // another systemd target transition (i.e. Quiesce->Reboot)
+    while (!isChassisTargetComplete())
+    {
+        log<level::DEBUG>("Waiting for chassis on target to complete");
+        std::this_thread::sleep_for(std::chrono::seconds(1));
+
+        // There is no timeout here, wait until it happens or until system
+        // is powered off and this service is stopped
+    }
+
+    log<level::INFO>("Chassis power on has completed, checking if host is "
+                     "still running after the BMC reboot");
 
     // Check the last BootProgeress to see if the host was booting before
     // the BMC reboot occurred