phosphor-state-manager: Add reset cause logic

This change will allow BMC graceful reboots to be tracked differently
from crashes.

Tested:
busctl set-property xyz.openbmc_project.State.BMC /xyz/openbmc_project/state/bmc0 xyz.openbmc_project.State.BMC RequestedBMCTransition s xyz.openbmc_project.State.BMC.Transition.Reboot
...
<bmc reboots>
...
Jan 24 22:27:58 <>-nfd01.prod.google.com phosphor-bmc-state-manager[435]: Rest flag file found

openbmc review for ref:
https://gerrit.openbmc.org/c/openbmc/phosphor-state-manager/+/77551

Fusion-Link:
https://fusion2.corp.google.com/3e6b34e0-7051-3d66-850b-35203e3520f0
Google-Bug-Id: 388883002
Change-Id: I85b415dbdbf6babb1bc262a230303d6c860450eb
Signed-off-by: John Edward Broadbent <jebr@google.com>
diff --git a/recipes-phosphor/state/phosphor-state-manager/0001-Adds-bmc-reboot-flag-identify-reboot-types.patch b/recipes-phosphor/state/phosphor-state-manager/0001-Adds-bmc-reboot-flag-identify-reboot-types.patch
new file mode 100644
index 0000000..0c0b219
--- /dev/null
+++ b/recipes-phosphor/state/phosphor-state-manager/0001-Adds-bmc-reboot-flag-identify-reboot-types.patch
@@ -0,0 +1,127 @@
+From eb587dd9a2650fdd351653d9c905d2691fb6d851 Mon Sep 17 00:00:00 2001
+From: John Edward Broadbent <jebr@google.com>
+Date: Sat, 18 Jan 2025 03:34:41 +0000
+Subject: [PATCH] Adds bmc reboot flag, identify reboot types
+
+This change adds a flag that bmc_state_manager writes when it shutsdown
+gracefully. This flag is read when the system starts, and it used to
+confirm the cause of the reboot is not unknown.
+
+Signed-off-by: John Edward Broadbent <jebr@google.com>
+---
+ bmc_state_manager.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++
+ bmc_state_manager.hpp | 13 ++++++++++++
+ 2 files changed, 59 insertions(+)
+
+diff --git a/bmc_state_manager.cpp b/bmc_state_manager.cpp
+index 22f2a42..2828d76 100644
+--- a/bmc_state_manager.cpp
++++ b/bmc_state_manager.cpp
+@@ -12,6 +12,8 @@
+ #include <filesystem>
+ #include <fstream>
+ #include <iostream>
++#include <optional>
++
+ 
+ namespace phosphor
+ {
+@@ -20,6 +22,8 @@ namespace state
+ namespace manager
+ {
+ 
++constexpr std::string_view flag_file =
++    "/var/google/phosphor-state-manager-reboot.flag";
+ PHOSPHOR_LOG2_USING;
+ 
+ // When you see server:: you know we're referencing our base class
+@@ -152,6 +156,16 @@ void BMC::executeTransition(const Transition tranReq)
+ 
+         method.append(sysdUnit, "replace-irreversibly");
+ 
++        // Explain cause of reboot to be discovered
++       try
++       {
++           writeResetFlag();
++       }
++       catch (const std::exception& e)
++       {
++           info("Unable to write flag file {ERROR}", "ERROR", e);
++       }
++
+         // Put BMC state not NotReady when issuing a BMC reboot
+         // and stop monitoring for state changes
+         this->currentBMCState(BMCState::NotReady);
+@@ -328,9 +342,41 @@ void BMC::discoverLastRebootCause()
+         this->lastRebootCause(RebootCause::POR);
+     }
+ 
++    // If the reason is not above check the rwfs file for a reason
++    try
++    {
++        auto res = readResetFlag();
++        this->lastRebootCause(res.value_or(RebootCause::Unknown));
++    }
++    catch (const std::exception& e)
++    {
++        info("Unable to read flag file {ERROR}", "ERROR", e);
++    }
+     return;
+ }
+ 
++void BMC::writeResetFlag()
++{
++    if(std::filesystem::exists(flag_file))
++    {
++        error("Reset flag is already present");
++        return;
++    }
++    // create a symlink to dev null to show graceful intent
++    std::filesystem::create_symlink("/dev/null", flag_file);
++}
++
++std::optional<BMC::RebootCause> BMC::readResetFlag()
++{
++    if(!std::filesystem::exists(flag_file))
++    {
++       return std::nullopt;
++    }
++    info("Rest flag file found");
++    std::filesystem::remove(flag_file);
++    return RebootCause::Software;
++}
++
+ } // namespace manager
+ } // namespace state
+ } // namespace phosphor
+diff --git a/bmc_state_manager.hpp b/bmc_state_manager.hpp
+index 8781e3f..66f7dbd 100644
+--- a/bmc_state_manager.hpp
++++ b/bmc_state_manager.hpp
+@@ -10,6 +10,7 @@
+ 
+ #include <cassert>
+ #include <chrono>
++#include <optional>
+ 
+ namespace phosphor
+ {
+@@ -144,6 +145,18 @@ class BMC : public BMCInherit
+      * @brief the lastRebootTime calcuated at startup.
+      **/
+     uint64_t rebootTime;
++
++    /**
++     * @brief check for the existance of readResetFlag
++     **/
++    std::optional<RebootCause> readResetFlag();
++
++    /**
++     * @brief writes the ResetFlag
++     **/
++    void writeResetFlag();
++
++
+ };
+ 
+ } // namespace manager
diff --git a/recipes-phosphor/state/phosphor-state-manager_git.bb_append b/recipes-phosphor/state/phosphor-state-manager_git.bb_append
new file mode 100644
index 0000000..c91b406
--- /dev/null
+++ b/recipes-phosphor/state/phosphor-state-manager_git.bb_append
@@ -0,0 +1,4 @@
+FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
+
+SRC_URI:append = "file://0001-Adds-bmc-reboot-flag-identify-reboot-types.patch"
+