Add option to use PLT_RST for warm reset detection

To support platforms that provide a PLT_RST eSPI signal,
this change adds an option to detect warm resets from the
eSPI PLT_RST signal instead of POST Complete.

The eSPI PLT_RST signal is provided by the
xyz.openbmc_project.Host.Misc.Manager service.

Tested:
Confirmed that warm reset can be detected based on PLT_RST
changes.

Change-Id: I8ac2c260280cf4edec8800e8e2ee12159748f24e
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
diff --git a/power-control-x86/src/power_control.cpp b/power-control-x86/src/power_control.cpp
index 987a76f..0379c4c 100644
--- a/power-control-x86/src/power_control.cpp
+++ b/power-control-x86/src/power_control.cpp
@@ -219,6 +219,8 @@
     sioPowerGoodDeAssert,
     sioS5Assert,
     sioS5DeAssert,
+    pltRstAssert,
+    pltRstDeAssert,
     postCompleteAssert,
     postCompleteDeAssert,
     powerButtonPressed,
@@ -257,6 +259,12 @@
         case Event::sioS5DeAssert:
             return "SIO S5 de-assert";
             break;
+        case Event::pltRstAssert:
+            return "PLT_RST assert";
+            break;
+        case Event::pltRstDeAssert:
+            return "PLT_RST de-assert";
+            break;
         case Event::postCompleteAssert:
             return "POST Complete assert";
             break;
@@ -1416,7 +1424,11 @@
             setPowerState(PowerState::transitionToOff);
             addRestartCause(RestartCause::softReset);
             break;
+#if USE_PLT_RST
+        case Event::pltRstAssert:
+#else
         case Event::postCompleteDeAssert:
+#endif
             setPowerState(PowerState::checkForWarmReset);
             addRestartCause(RestartCause::softReset);
             warmResetCheckTimerStart();
@@ -2032,6 +2044,55 @@
                              });
 }
 
+static void pltRstHandler(bool pltRst)
+{
+    if (pltRst)
+    {
+        sendPowerControlEvent(Event::pltRstDeAssert);
+    }
+    else
+    {
+        sendPowerControlEvent(Event::pltRstAssert);
+    }
+}
+
+static void hostMiscHandler(sdbusplus::message::message& msg)
+{
+    std::string interfaceName;
+    boost::container::flat_map<std::string, std::variant<bool>>
+        propertiesChanged;
+    bool pltRst;
+    try
+    {
+        msg.read(interfaceName, propertiesChanged);
+    }
+    catch (std::exception& e)
+    {
+        std::cerr << "Unable to read Host Misc status\n";
+        return;
+    }
+    if (propertiesChanged.empty())
+    {
+        std::cerr
+            << "ERROR: Empty Host.Misc PropertiesChanged signal received\n";
+        return;
+    }
+
+    for (auto& [property, value] : propertiesChanged)
+    {
+        if (property == "ESpiPlatformReset")
+        {
+            bool* pltRst = std::get_if<bool>(&value);
+            if (pltRst == nullptr)
+            {
+                std::cerr << property << " property invalid\n";
+                return;
+            }
+            pltRstHandler(*pltRst);
+        }
+    }
+}
+
 static void postCompleteHandler()
 {
     gpiod::line_event gpioLineEvent = postCompleteLine.event_read();
@@ -2274,6 +2335,14 @@
             power_control::idButtonLine, power_control::idButtonEvent);
     }
 
+#ifdef USE_PLT_RST
+    sdbusplus::bus::match::match pltRstMatch(
+        *power_control::conn,
+        "type='signal',interface='org.freedesktop.DBus.Properties',member='"
+        "PropertiesChanged',arg0='xyz.openbmc_project.State.Host.Misc'",
+        power_control::hostMiscHandler);
+#endif
+
     // Request POST_COMPLETE GPIO events
     if (!power_control::postCompleteName.empty())
     {