summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/state
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/state')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0001-Modify-dbus-interface-for-power-control.patch38
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0002-Capture-host-restart-cause.patch338
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0003-Use-warm-reboot-for-the-Reboot-host-state-transition.patch71
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0004-Add-Power-Restore-delay-support.patch141
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reboot-host@.service18
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-check@.service19
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-reboot-attempts@.service14
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend10
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager/0001-Implement-post-code-manager.patch499
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager_git.bb34
10 files changed, 1182 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0001-Modify-dbus-interface-for-power-control.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0001-Modify-dbus-interface-for-power-control.patch
new file mode 100644
index 000000000..fac9b52f1
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0001-Modify-dbus-interface-for-power-control.patch
@@ -0,0 +1,38 @@
+From d34a2a5f6ca0564275ed0e2664624525cad64585 Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Fri, 13 Jul 2018 09:08:52 +0800
+Subject: [PATCH] Modify dbus interface for power control
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Switch power control service namespace from “org” to “xyz”,
+to compatible with new intel-chassis services
+
+Change-Id: I1bf5e218f72eb9fd4fb6f203c35479818d12b1fa
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ chassis_state_manager.cpp | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/chassis_state_manager.cpp b/chassis_state_manager.cpp
+index 03dd176..05e2440 100644
+--- a/chassis_state_manager.cpp
++++ b/chassis_state_manager.cpp
+@@ -63,10 +63,11 @@ void Chassis::determineInitialState()
+ {
+ sdbusplus::message::variant<int> pgood = -1;
+ auto method = this->bus.new_method_call(
+- "org.openbmc.control.Power", "/org/openbmc/control/power0",
++ "xyz.openbmc_project.Chassis.Control.Power",
++ "/xyz/openbmc_project/Chassis/Control/Power0",
+ "org.freedesktop.DBus.Properties", "Get");
+
+- method.append("org.openbmc.control.Power", "pgood");
++ method.append("xyz.openbmc_project.Chassis.Control.Power", "pgood");
+ try
+ {
+ auto reply = this->bus.call(method);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0002-Capture-host-restart-cause.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0002-Capture-host-restart-cause.patch
new file mode 100644
index 000000000..2adff372e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0002-Capture-host-restart-cause.patch
@@ -0,0 +1,338 @@
+From ed64fe7379a259a822aca69e70426a2b07aad25d Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Tue, 7 Aug 2018 16:43:00 +0800
+Subject: [PATCH] Capture host restart cause
+
+Capture host restart cause on power/reset button pressed,
+ipmi command/webui, host OS reboot(Ctrl-Alt-Del),
+and power restore policy settings.
+Save the restart cause into file system,
+and restore it when BMC boot up.
+
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ configure.ac | 4 +-
+ discover_system_state.cpp | 14 +++++
+ host_state_manager.cpp | 17 ++++++
+ host_state_manager.hpp | 148 +++++++++++++++++++++++++++++++++++++++++++++-
+ 4 files changed, 178 insertions(+), 5 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 7919ec5..051a0c0 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -52,9 +52,9 @@ AC_ARG_VAR(HOST_RUNNING_FILE, [File to create if host is running])
+ AS_IF([test "x$HOST_RUNNING_FILE" == "x"], [HOST_RUNNING_FILE="/run/openbmc/host@%u-on"])
+ AC_DEFINE_UNQUOTED([HOST_RUNNING_FILE], ["$HOST_RUNNING_FILE"], [File to create if host is running])
+
+-AC_ARG_VAR(HOST_STATE_PERSIST_PATH, [Path of file for storing requested host state.])
++AC_ARG_VAR(HOST_STATE_PERSIST_PATH, [Path of file for storing host state.])
+ AS_IF([test "x$HOST_STATE_PERSIST_PATH" == "x"], \
+- [HOST_STATE_PERSIST_PATH="/var/lib/phosphor-state-manager/requestedHostTransition"])
++ [HOST_STATE_PERSIST_PATH="/var/lib/phosphor-state-manager/hostState"])
+ AC_DEFINE_UNQUOTED([HOST_STATE_PERSIST_PATH], ["$HOST_STATE_PERSIST_PATH"], \
+ [Path of file for storing requested host state.])
+
+diff --git a/discover_system_state.cpp b/discover_system_state.cpp
+index 3a38152..0b5798a 100644
+--- a/discover_system_state.cpp
++++ b/discover_system_state.cpp
+@@ -12,6 +12,7 @@
+ #include "settings.hpp"
+ #include "xyz/openbmc_project/Common/error.hpp"
+ #include "xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp"
++#include <xyz/openbmc_project/State/Host/server.hpp>
+
+ namespace phosphor
+ {
+@@ -181,6 +182,10 @@ int main(int argc, char** argv)
+ log<level::INFO>("power_policy=ALWAYS_POWER_ON, powering host on");
+ setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
+ convertForMessage(server::Host::Transition::On));
++
++ setProperty(
++ bus, hostPath, HOST_BUSNAME, "HostRestartCause",
++ convertForMessage(server::Host::RestartCause::PowerPolicyAlwaysOn));
+ }
+ else if (RestorePolicy::Policy::Restore ==
+ RestorePolicy::convertPolicyFromString(powerPolicy))
+@@ -192,6 +197,15 @@ int main(int argc, char** argv)
+ getProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition");
+ setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
+ hostReqState);
++
++ if (server::Host::convertTransitionFromString(hostReqState) ==
++ server::Host::Transition::On)
++ {
++ setProperty(
++ bus, hostPath, HOST_BUSNAME, "HostRestartCause",
++ convertForMessage(
++ server::Host::RestartCause::PowerPolicyPreviousState));
++ }
+ }
+
+ return 0;
+diff --git a/host_state_manager.cpp b/host_state_manager.cpp
+index 7d661dd..0e00e78 100644
+--- a/host_state_manager.cpp
++++ b/host_state_manager.cpp
+@@ -308,6 +308,15 @@ bool Host::deserialize(const fs::path& path)
+ }
+ }
+
++void Host::restoreHostRestartCause()
++{
++ if (!deserialize(HOST_STATE_PERSIST_PATH))
++ {
++ // set to default value
++ server::Host::hostRestartCause(server::Host::RestartCause::Unknown);
++ }
++}
++
+ Host::Transition Host::requestedHostTransition(Transition value)
+ {
+ log<level::INFO>("Host State transaction request",
+@@ -321,6 +330,7 @@ Host::Transition Host::requestedHostTransition(Transition value)
+ // check of this count will occur
+ if (value != server::Host::Transition::Off)
+ {
++ hostRestartCause(RestartCause::IpmiCommand);
+ decrementRebootCount();
+ }
+
+@@ -353,6 +363,13 @@ Host::HostState Host::currentHostState(HostState value)
+ return server::Host::currentHostState(value);
+ }
+
++Host::RestartCause Host::hostRestartCause(RestartCause value)
++{
++ auto retVal = server::Host::hostRestartCause(value);
++ serialize();
++ return retVal;
++}
++
+ } // namespace manager
+ } // namespace state
+ } // namespace phosphor
+diff --git a/host_state_manager.hpp b/host_state_manager.hpp
+index 2b00777..afd8aa3 100644
+--- a/host_state_manager.hpp
++++ b/host_state_manager.hpp
+@@ -32,6 +32,22 @@ using namespace phosphor::logging;
+ namespace sdbusRule = sdbusplus::bus::match::rules;
+ namespace fs = std::experimental::filesystem;
+
++const static constexpr char* powerButtonPath =
++ "/xyz/openbmc_project/Chassis/Buttons/Power0";
++const static constexpr char* powerButtonIntf =
++ "xyz.openbmc_project.Chassis.Buttons.Power";
++const static constexpr char* resetButtonPath =
++ "/xyz/openbmc_project/Chassis/Buttons/Reset0";
++const static constexpr char* resetButtonIntf =
++ "xyz.openbmc_project.Chassis.Buttons.Reset";
++
++const static constexpr char* powerControlService =
++ "xyz.openbmc_project.Chassis.Control.Power";
++const static constexpr char* powerControlPath =
++ "/xyz/openbmc_project/Chassis/Control/Power0";
++const static constexpr char* powerControlInterface =
++ "xyz.openbmc_project.Chassis.Control.Power";
++
+ /** @class Host
+ * @brief OpenBMC host state management implementation.
+ * @details A concrete implementation for xyz.openbmc_project.State.Host
+@@ -59,8 +75,93 @@ class Host : public HostInherit
+ sdbusRule::interface("org.freedesktop.systemd1.Manager"),
+ std::bind(std::mem_fn(&Host::sysStateChange), this,
+ std::placeholders::_1)),
+- settings(bus)
++ settings(bus),
++ powerButtonPressedSignal(
++ bus,
++ sdbusRule::type::signal() + sdbusRule::member("Pressed") +
++ sdbusRule::path(powerButtonPath) +
++ sdbusRule::interface(powerButtonIntf),
++ [this](sdbusplus::message::message& msg) {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "powerButtonPressedSignal callback function is called...");
++ this->hostRestartCause(this->RestartCause::PowerButton);
++ this->powerButtonPressed = true;
++ return;
++ }),
++ resetButtonPressedSignal(
++ bus,
++ sdbusRule::type::signal() + sdbusRule::member("Pressed") +
++ sdbusRule::path(resetButtonPath) +
++ sdbusRule::interface(resetButtonIntf),
++ [this](sdbusplus::message::message& msg) {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "resetButtonPressedSignal callback function is called...");
++ this->hostRestartCause(this->RestartCause::ResetButton);
++ this->resetButtonPressed = true;
++ return;
++ }),
++ postCompletePropSignal(
++ bus,
++ sdbusplus::bus::match::rules::propertiesChanged(
++ powerControlPath, powerControlInterface),
++ [this](sdbusplus::message::message& msg) {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "postCompletePropSignal callback function is called...");
++
++ using DbusVariant = sdbusplus::message::variant<
++ std::string, bool, uint8_t, uint16_t, int16_t, uint32_t,
++ int32_t, uint64_t, int64_t, double>;
++
++ std::map<std::string, DbusVariant> props;
++ std::vector<std::string> inval;
++ std::string iface;
++ msg.read(iface, props, inval);
++
++ for (const auto& t : props)
++ {
++ auto key = t.first;
++ auto value = t.second;
++
++ if (key == "state")
++ {
++ this->powerStateChanged = true;
++ }
++
++ else if (key == "pgood")
++ {
++ this->pgood =
++ sdbusplus::message::variant_ns::get<int32_t>(value);
++ }
++
++ else if (key == "post_complete")
++ {
++ bool postState =
++ sdbusplus::message::variant_ns::get<bool>(value);
++
++ if (!postState && this->pgood)
++ {
++ if (!this->resetButtonPressed &&
++ !this->powerButtonPressed &&
++ !this->powerStateChanged)
++ {
++ phosphor::logging::log<
++ phosphor::logging::level::INFO>(
++ "OEM Reset");
++ this->hostRestartCause(this->RestartCause::OEM);
++ }
++ this->powerButtonPressed = false;
++ this->powerStateChanged = false;
++ this->resetButtonPressed = false;
++ }
++ }
++ }
++ })
+ {
++ powerButtonPressed = false;
++ powerStateChanged = false;
++ resetButtonPressed = false;
++ pgood = 0;
++
+ // Enable systemd signals
+ subscribeToSystemdSignals();
+
+@@ -69,8 +170,29 @@ class Host : public HostInherit
+
+ attemptsLeft(BOOT_COUNT_MAX_ALLOWED);
+
++ restoreHostRestartCause(); // restore host restart cause from persisted
++ // file
++
+ // We deferred this until we could get our property correct
+ this->emit_object_added();
++ sdbusplus::message::variant<int32_t> pgoodProp = -1;
++ auto method =
++ this->bus.new_method_call(powerControlService, powerControlPath,
++ "org.freedesktop.DBus.Properties", "Get");
++
++ method.append(powerControlInterface, "pgood");
++ try
++ {
++ auto reply = this->bus.call(method);
++ reply.read(pgoodProp);
++ pgood = sdbusplus::message::variant_ns::get<int>(pgoodProp);
++ }
++ catch (const sdbusplus::exception::SdBusError& e)
++ {
++ log<level::ERR>("Error performing call to get pgood",
++ entry("NAME=%s", e.name()),
++ entry("ERROR=%s", e.what()));
++ }
+ }
+
+ /** @brief Set value of HostTransition */
+@@ -85,6 +207,9 @@ class Host : public HostInherit
+ /** @brief Set value of CurrentHostState */
+ HostState currentHostState(HostState value) override;
+
++ /** @brief Set value of HostRestartCause */
++ RestartCause hostRestartCause(RestartCause value) override;
++
+ /**
+ * @brief Set host reboot count to default
+ *
+@@ -192,7 +317,9 @@ class Host : public HostInherit
+ server::Progress::bootProgress()),
+ convertForMessage(
+ sdbusplus::xyz::openbmc_project::State::OperatingSystem::
+- server::Status::operatingSystemState()));
++ server::Status::operatingSystemState()),
++ convertForMessage(sdbusplus::xyz::openbmc_project::State::
++ server::Host::hostRestartCause()));
+ }
+
+ /** @brief Function required by Cereal to perform deserialization.
+@@ -208,7 +335,8 @@ class Host : public HostInherit
+ std::string reqTranState;
+ std::string bootProgress;
+ std::string osState;
+- archive(reqTranState, bootProgress, osState);
++ std::string restartCause;
++ archive(reqTranState, bootProgress, osState, restartCause);
+ auto reqTran = Host::convertTransitionFromString(reqTranState);
+ // When restoring, set the requested state with persistent value
+ // but don't call the override which would execute it
+@@ -219,6 +347,8 @@ class Host : public HostInherit
+ sdbusplus::xyz::openbmc_project::State::OperatingSystem::server::
+ Status::operatingSystemState(
+ Host::convertOSStatusFromString(osState));
++ sdbusplus::xyz::openbmc_project::State::server::Host::hostRestartCause(
++ Host::convertRestartCauseFromString(restartCause));
+ }
+
+ /** @brief Serialize and persist requested host state
+@@ -239,6 +369,9 @@ class Host : public HostInherit
+ */
+ bool deserialize(const fs::path& path);
+
++ /** @brief Used to restore HostRestartCause value from persisted file */
++ void restoreHostRestartCause();
++
+ /** @brief Persistent sdbusplus DBus bus connection. */
+ sdbusplus::bus::bus& bus;
+
+@@ -247,6 +380,15 @@ class Host : public HostInherit
+
+ // Settings objects of interest
+ settings::Objects settings;
++
++ bool resetButtonPressed;
++ bool powerButtonPressed;
++ bool powerStateChanged;
++ int32_t pgood;
++
++ sdbusplus::bus::match_t powerButtonPressedSignal;
++ sdbusplus::bus::match_t resetButtonPressedSignal;
++ sdbusplus::bus::match_t postCompletePropSignal;
+ };
+
+ } // namespace manager
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0003-Use-warm-reboot-for-the-Reboot-host-state-transition.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0003-Use-warm-reboot-for-the-Reboot-host-state-transition.patch
new file mode 100644
index 000000000..40722c3c9
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0003-Use-warm-reboot-for-the-Reboot-host-state-transition.patch
@@ -0,0 +1,71 @@
+From 8a7f73a0688524c71023da89e8cb5578dac16f5d Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Fri, 8 Mar 2019 17:21:49 +0800
+Subject: [PATCH] Use warm-reboot for the Reboot host state transition
+
+The same as reset button pressing, the pgood signal will keep on during the reboot
+
+Tested By:
+ipmitool chassis power reset
+The pgood(gpio219) will be keep high during the reset process
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ host_state_manager.cpp | 20 +++++++++++++-------
+ 1 file changed, 13 insertions(+), 7 deletions(-)
+
+diff --git a/host_state_manager.cpp b/host_state_manager.cpp
+index 03d210d..8fac348 100644
+--- a/host_state_manager.cpp
++++ b/host_state_manager.cpp
+@@ -44,8 +44,9 @@ constexpr auto HOST_STATE_SOFT_POWEROFF_TGT = "obmc-host-shutdown@0.target";
+ constexpr auto HOST_STATE_POWEROFF_TGT = "obmc-host-stop@0.target";
+ constexpr auto HOST_STATE_POWERON_TGT = "obmc-host-start@0.target";
+ constexpr auto HOST_STATE_POWERON_MIN_TGT = "obmc-host-startmin@0.target";
+-constexpr auto HOST_STATE_REBOOT_TGT = "obmc-host-reboot@0.target";
++constexpr auto HOST_STATE_REBOOT_TGT = "obmc-host-warm-reset@0.target";
+ constexpr auto HOST_STATE_QUIESCE_TGT = "obmc-host-quiesce@0.target";
++constexpr auto hostStateRebootService = "intel-power-warm-reset@0.service";
+
+ constexpr auto ACTIVE_STATE = "active";
+ constexpr auto ACTIVATING_STATE = "activating";
+@@ -168,6 +169,7 @@ bool Host::stateActive(const std::string& target)
+
+ const auto& currentStateStr =
+ sdbusplus::message::variant_ns::get<std::string>(currentState);
++
+ return currentStateStr == ACTIVE_STATE ||
+ currentStateStr == ACTIVATING_STATE;
+ }
+@@ -236,18 +238,22 @@ void Host::sysStateChange(sdbusplus::message::message& msg)
+ // Read the msg and populate each variable
+ msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
+
+- if ((newStateUnit == HOST_STATE_POWEROFF_TGT) &&
+- (newStateResult == "done") &&
+- (!stateActive(HOST_STATE_POWERON_MIN_TGT)))
++ if (((newStateUnit == HOST_STATE_POWEROFF_TGT) &&
++ (newStateResult == "done") &&
++ (!stateActive(HOST_STATE_POWERON_MIN_TGT))) ||
++ ((newStateUnit == hostStateRebootService) &&
++ (newStateResult == "done")))
+ {
+ log<level::INFO>("Received signal that host is off");
+ this->currentHostState(server::Host::HostState::Off);
+ this->bootProgress(bootprogress::Progress::ProgressStages::Unspecified);
+ this->operatingSystemState(osstatus::Status::OSStatus::Inactive);
+ }
+- else if ((newStateUnit == HOST_STATE_POWERON_MIN_TGT) &&
+- (newStateResult == "done") &&
+- (stateActive(HOST_STATE_POWERON_MIN_TGT)))
++ else if (((newStateUnit == HOST_STATE_POWERON_MIN_TGT) &&
++ (newStateResult == "done") &&
++ (stateActive(HOST_STATE_POWERON_MIN_TGT))) ||
++ ((newStateUnit == HOST_STATE_REBOOT_TGT) &&
++ (newStateResult == "done")))
+ {
+ log<level::INFO>("Received signal that host is running");
+ this->currentHostState(server::Host::HostState::Running);
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0004-Add-Power-Restore-delay-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0004-Add-Power-Restore-delay-support.patch
new file mode 100644
index 000000000..31cb31079
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/0004-Add-Power-Restore-delay-support.patch
@@ -0,0 +1,141 @@
+From 0edff651156ae63b6a73d9cb81e5e76cc6ae501a Mon Sep 17 00:00:00 2001
+From: Yong Li <yong.b.li@linux.intel.com>
+Date: Fri, 12 Apr 2019 18:43:06 +0800
+Subject: [PATCH] Add Power Restore delay support
+
+That takes effect whenever the BMC
+automatically turns on the system due
+to the Power Restore Policy setting
+
+Tested:
+Set power restore delay:
+ipmitool raw 0x30 0x54 0 7
+Set restore policy as always-on:
+ipmitool chassis policy always-on
+AC off/on, check the journal log, the host will start boot after 7 seconds delay
+
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+---
+ discover_system_state.cpp | 71 +++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 68 insertions(+), 3 deletions(-)
+
+diff --git a/discover_system_state.cpp b/discover_system_state.cpp
+index 0b5798a..298ae5b 100644
+--- a/discover_system_state.cpp
++++ b/discover_system_state.cpp
+@@ -1,5 +1,4 @@
+ #include <getopt.h>
+-#include <iostream>
+ #include <map>
+ #include <string>
+ #include <config.h>
+@@ -114,6 +113,49 @@ void setProperty(sdbusplus::bus::bus& bus, const std::string& path,
+ return;
+ }
+
++int getPowerRestoreDelay(sdbusplus::bus::bus& bus, uint16_t& delay)
++{
++ static constexpr const char* powerRestoreDelayObjPath =
++ "/xyz/openbmc_project/control/power_restore_delay";
++ static constexpr const char* powerRestoreDelayIntf =
++ "xyz.openbmc_project.Control.Power.RestoreDelay";
++ static constexpr const char* powerRestoreDelayProp = "PowerRestoreDelay";
++
++ std::string service =
++ getService(bus, powerRestoreDelayObjPath, powerRestoreDelayIntf);
++
++ sdbusplus::message::message method = bus.new_method_call(
++ service.c_str(), powerRestoreDelayObjPath, PROPERTY_INTERFACE, "Get");
++
++ method.append(powerRestoreDelayIntf, powerRestoreDelayProp);
++
++ try
++ {
++ auto reply = bus.call(method);
++ sdbusplus::message::variant<uint16_t> variant;
++ reply.read(variant);
++ delay = sdbusplus::message::variant_ns::get<uint16_t>(variant);
++ }
++ catch (sdbusplus::exception_t&)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Failed to get property",
++ phosphor::logging::entry("PROPERTY=%s", powerRestoreDelayProp),
++ phosphor::logging::entry("PATH=%s", powerRestoreDelayObjPath),
++ phosphor::logging::entry("INTERFACE=%s", powerRestoreDelayIntf));
++ return -1;
++ }
++ return 0;
++}
++
++void applyPowerRestoreDelay(uint16_t delay)
++{
++ if (delay > 0)
++ {
++ log<level::INFO>("Apply Power Restore Delay", entry("DELAY=%d", delay));
++ std::this_thread::sleep_for(std::chrono::milliseconds(1000 * delay));
++ }
++}
+ } // namespace manager
+ } // namespace state
+ } // namespace phosphor
+@@ -176,13 +218,27 @@ int main(int argc, char** argv)
+ log<level::INFO>("Host power is off, checking power policy",
+ entry("POWER_POLICY=%s", powerPolicy.c_str()));
+
++ uint16_t delay = 0;
++ int ret = getPowerRestoreDelay(bus, delay);
++
++ if (ret != 0)
++ {
++ log<level::WARNING>("getPowerRestoreDelay failed!");
++ delay = 0;
++ }
++
+ if (RestorePolicy::Policy::AlwaysOn ==
+ RestorePolicy::convertPolicyFromString(powerPolicy))
+ {
++ applyPowerRestoreDelay(delay);
++
+ log<level::INFO>("power_policy=ALWAYS_POWER_ON, powering host on");
++
+ setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
+ convertForMessage(server::Host::Transition::On));
+
++ // Host on, needs to set the restart cause after host transition
++ // since host transition will change the restart cause
+ setProperty(
+ bus, hostPath, HOST_BUSNAME, "HostRestartCause",
+ convertForMessage(server::Host::RestartCause::PowerPolicyAlwaysOn));
+@@ -195,17 +251,26 @@ int main(int argc, char** argv)
+ // Read last requested state and re-request it to execute it
+ auto hostReqState =
+ getProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition");
+- setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
+- hostReqState);
+
+ if (server::Host::convertTransitionFromString(hostReqState) ==
+ server::Host::Transition::On)
+ {
++ applyPowerRestoreDelay(delay);
++ setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
++ hostReqState);
++
++ // Host on, needs to set the restart cause after host transition
++ // since host transition will change the restart cause
+ setProperty(
+ bus, hostPath, HOST_BUSNAME, "HostRestartCause",
+ convertForMessage(
+ server::Host::RestartCause::PowerPolicyPreviousState));
+ }
++ else
++ {
++ setProperty(bus, hostPath, HOST_BUSNAME, "RequestedHostTransition",
++ hostReqState);
++ }
+ }
+
+ return 0;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reboot-host@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reboot-host@.service
new file mode 100644
index 000000000..ffde01ca3
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reboot-host@.service
@@ -0,0 +1,18 @@
+[Unit]
+Description=Reboot host%i
+Wants=obmc-host-stop@%i.target
+After=obmc-host-stop@%i.target
+
+[Service]
+#ExecStart={base_bindir}/systemctl start obmc-host-start@%i.target
+# This service is starting another target that conflicts with the
+# target this service is running in. OpenBMC needs a refactor of
+# how it does its host reset path. Until then, this short term
+# solution does the job.
+# Since this is a part of the reboot target, call the startmin
+# target which does the minimum required to start the host.
+ExecStart=/bin/sh -c "sleep 10 && systemctl start obmc-host-startmin@%i.target"
+
+
+[Install]
+WantedBy=obmc-host-reboot@%i.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-check@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-check@.service
new file mode 100644
index 000000000..13b8f0fca
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-check@.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=Check Host%i status on BMC reset
+Wants=mapper-wait@-xyz-openbmc_project-control-host%i.service
+After=mapper-wait@-xyz-openbmc_project-control-host%i.service
+Wants=obmc-host-reset-running@%i.target
+Before=obmc-host-reset-running@%i.target
+Wants=op-reset-chassis-on@%i.service
+After=op-reset-chassis-on@%i.service
+Conflicts=obmc-host-stop@%i.target
+ConditionPathExists=/run/openbmc/chassis@%i-on
+
+[Service]
+RemainAfterExit=yes
+Type=oneshot
+ExecStart=/bin/sh -c "if [ $(busctl get-property `mapper get-service /xyz/openbmc_project/Chassis/Control/Power%i` /xyz/openbmc_project/Chassis/Control/Power%i xyz.openbmc_project.Chassis.Control.Power vrd_good | sed 's/i\s*[1]/on/' | grep on | wc -l) != 0 ]; then mkdir -p /run/openbmc/ && touch /run/openbmc/host@%i-on; fi"
+SyslogIdentifier=phosphor-host-check
+
+[Install]
+WantedBy=obmc-host-reset@%i.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-reboot-attempts@.service b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-reboot-attempts@.service
new file mode 100644
index 000000000..87c750c57
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager/phosphor-reset-host-reboot-attempts@.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Reset host reboot counter
+Wants=mapper-wait@-xyz-openbmc_project-state-host%i.service
+After=mapper-wait@-xyz-openbmc_project-state-host%i.service
+ConditionPathExists=!/run/openbmc/host@%i-on
+
+[Service]
+Restart=no
+Type=oneshot
+ExecStart=/bin/sh -c "busctl set-property `mapper get-service /xyz/openbmc_project/state/host%i` /xyz/openbmc_project/state/host%i xyz.openbmc_project.Control.Boot.RebootAttempts AttemptsLeft u 3"
+StartLimitInterval=0
+
+[Install]
+WantedBy=obmc-host-start@%i.target
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend
new file mode 100644
index 000000000..63155ce0d
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/phosphor-state-manager_%.bbappend
@@ -0,0 +1,10 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0001-Modify-dbus-interface-for-power-control.patch \
+ file://phosphor-reboot-host@.service \
+ file://phosphor-reset-host-reboot-attempts@.service \
+ file://phosphor-reset-host-check@.service \
+ file://0002-Capture-host-restart-cause.patch \
+ file://0003-Use-warm-reboot-for-the-Reboot-host-state-transition.patch \
+ file://0004-Add-Power-Restore-delay-support.patch \
+ "
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager/0001-Implement-post-code-manager.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager/0001-Implement-post-code-manager.patch
new file mode 100644
index 000000000..8915484cd
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager/0001-Implement-post-code-manager.patch
@@ -0,0 +1,499 @@
+From 7d78e70735e1bce51ef34cfe128be68758de3447 Mon Sep 17 00:00:00 2001
+From: Kuiying Wang <kuiying.wang@intel.com>
+Date: Tue, 19 Feb 2019 15:00:11 +0800
+Subject: [PATCH] Implement post code manager
+
+Implement method and properties defined in PostCode.interface.yaml
+under phosphor-dbus-interfaces/xyz/openbmc_project/State/Boot
+1. Method: std::vector<uint64_t> PostCode::getPostCodes(uint16_t index)
+2. Properties: CurrentBootCycleIndex/MaxBootCycleNum
+
+Test-By:
+ Every cycle post codes is saved in "/var/lib/phosphor-post-code-manager"
+ "1" file is saved all post codes for cycle 1
+ "2" file is saved all post codes for cycle 2
+ "CurrentBootCycleIndex" file is saved the current boot cycle number.
+ root@wolfpass:/var/lib/phosphor-post-code-manager# ls
+ 1 2 CurrentBootCycleIndex
+
+Change-Id: Ia89b9121983261fef5573092d890beb84626ceeb
+Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
+---
+ CMakeLists.txt | 45 ++++++
+ MAINTAINERS | 45 ++++++
+ inc/post_code.hpp | 152 ++++++++++++++++++
+ ...penbmc_project.State.Boot.PostCode.service | 11 ++
+ src/main.cpp | 61 +++++++
+ src/post_code.cpp | 109 +++++++++++++
+ 6 files changed, 423 insertions(+)
+ create mode 100644 CMakeLists.txt
+ create mode 100644 MAINTAINERS
+ create mode 100644 inc/post_code.hpp
+ create mode 100644 service_files/xyz.openbmc_project.State.Boot.PostCode.service
+ create mode 100644 src/main.cpp
+ create mode 100644 src/post_code.cpp
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+new file mode 100644
+index 0000000..594d839
+--- /dev/null
++++ b/CMakeLists.txt
+@@ -0,0 +1,45 @@
++cmake_minimum_required(VERSION 2.8.10 FATAL_ERROR)
++project(post-code-manager CXX)
++set(CMAKE_CXX_STANDARD 17)
++set(CMAKE_CXX_STANDARD_REQUIRED ON)
++
++set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
++include(GNUInstallDirs)
++include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)
++include_directories(${CMAKE_CURRENT_BINARY_DIR})
++
++set(DBUS_OBJECT_NAME "xyz/openbmc_project/State/Boot/PostCode")
++set(DBUS_INTF_NAME "xyz.openbmc_project.State.Boot.PostCode")
++
++add_definitions(-DDBUS_OBJECT_NAME="/${DBUS_OBJECT_NAME}")
++add_definitions(-DDBUS_INTF_NAME="${DBUS_INTF_NAME}")
++set(SRC_FILES src/post_code.cpp
++ src/main.cpp )
++set ( SERVICE_FILES
++ service_files/xyz.openbmc_project.State.Boot.PostCode.service )
++
++# import sdbusplus
++find_package(PkgConfig REQUIRED)
++pkg_check_modules(SDBUSPLUSPLUS sdbusplus REQUIRED)
++include_directories(${SDBUSPLUSPLUS_INCLUDE_DIRS})
++link_directories(${SDBUSPLUSPLUS_LIBRARY_DIRS})
++find_program(SDBUSPLUSPLUS sdbus++)
++
++# import phosphor-logging
++find_package(PkgConfig REQUIRED)
++pkg_check_modules(LOGGING phosphor-logging REQUIRED)
++include_directories(${LOGGING_INCLUDE_DIRS})
++link_directories(${LOGGING_LIBRARY_DIRS})
++
++# phosphor-dbus-interfaces
++find_package(PkgConfig REQUIRED)
++pkg_check_modules(DBUSINTERFACE phosphor-dbus-interfaces REQUIRED)
++include_directories(${DBUSINTERFACE_INCLUDE_DIRS})
++link_directories(${DBUSINTERFACE_LIBRARY_DIRS})
++
++add_executable(${PROJECT_NAME} ${SRC_FILES})
++target_link_libraries(${PROJECT_NAME} ${DBUSINTERFACE_LIBRARIES} )
++target_link_libraries(${PROJECT_NAME} "${SDBUSPLUSPLUS_LIBRARIES} -lstdc++fs -lphosphor_dbus")
++
++install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
++install (FILES ${SERVICE_FILES} DESTINATION /lib/systemd/system/)
+\ No newline at end of file
+diff --git a/MAINTAINERS b/MAINTAINERS
+new file mode 100644
+index 0000000..de6cc54
+--- /dev/null
++++ b/MAINTAINERS
+@@ -0,0 +1,45 @@
++How to use this list:
++ Find the most specific section entry (described below) that matches where
++ your change lives and add the reviewers (R) and maintainers (M) as
++ reviewers. You can use the same method to track down who knows a particular
++ code base best.
++
++ Your change/query may span multiple entries; that is okay.
++
++ If you do not find an entry that describes your request at all, someone
++ forgot to update this list; please at least file an issue or send an email
++ to a maintainer, but preferably you should just update this document.
++
++Description of section entries:
++
++ Section entries are structured according to the following scheme:
++
++ X: NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!>
++ X: ...
++ .
++ .
++ .
++
++ Where REPO_NAME is the name of the repository within the OpenBMC GitHub
++ organization; FILE_PATH is a file path within the repository, possibly with
++ wildcards; X is a tag of one of the following types:
++
++ M: Denotes maintainer; has fields NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!>;
++ if omitted from an entry, assume one of the maintainers from the
++ MAINTAINERS entry.
++ R: Denotes reviewer; has fields NAME <EMAIL_USERNAME@DOMAIN> <IRC_USERNAME!>;
++ these people are to be added as reviewers for a change matching the repo
++ path.
++ F: Denotes forked from an external repository; has fields URL.
++
++ Line comments are to be denoted "# SOME COMMENT" (typical shell style
++ comment); it is important to follow the correct syntax and semantics as we
++ may want to use automated tools with this file in the future.
++
++ A change cannot be added to an OpenBMC repository without a MAINTAINER's
++ approval; thus, a MAINTAINER should always be listed as a reviewer.
++
++START OF MAINTAINERS LIST
++-------------------------
++
++M: Kuiying Wang <kuiying.wang@intel.com> <kuiyingw>
+\ No newline at end of file
+diff --git a/inc/post_code.hpp b/inc/post_code.hpp
+new file mode 100644
+index 0000000..84c8b3e
+--- /dev/null
++++ b/inc/post_code.hpp
+@@ -0,0 +1,152 @@
++/*
++// Copyright (c) 2019 Intel Corporation
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++// http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++*/
++#pragma once
++#include <fcntl.h>
++#include <unistd.h>
++#include <cereal/cereal.hpp>
++#include <experimental/filesystem>
++#include <cereal/access.hpp>
++#include <cereal/archives/json.hpp>
++#include <iostream>
++#include <fstream>
++#include <cereal/types/vector.hpp>
++
++#include <xyz/openbmc_project/State/Boot/PostCode/server.hpp>
++#include <xyz/openbmc_project/Common/error.hpp>
++#include <phosphor-logging/elog-errors.hpp>
++#include <xyz/openbmc_project/State/Host/server.hpp>
++
++#define MaxPostCodeCycles 100
++
++const static constexpr char *PostCodePath =
++ "/xyz/openbmc_project/state/boot/raw";
++const static constexpr char *PropertiesIntf =
++ "org.freedesktop.DBus.Properties";
++const static constexpr char *PostCodeListPath =
++ "/var/lib/phosphor-post-code-manager/";
++const static constexpr char *CurrentBootCycleIndexName =
++ "CurrentBootCycleIndex";
++const static constexpr char *HostStatePath =
++ "/xyz/openbmc_project/state/host0";
++
++
++struct EventDeleter
++{
++ void operator()(sd_event *event) const
++ {
++ event = sd_event_unref(event);
++ }
++};
++using EventPtr = std::unique_ptr<sd_event, EventDeleter>;
++namespace fs = std::experimental::filesystem;
++namespace StateServer = sdbusplus::xyz::openbmc_project::State::server;
++
++using post_code =
++ sdbusplus::xyz::openbmc_project::State::Boot::server::PostCode;
++
++struct PostCode : sdbusplus::server::object_t<post_code>
++{
++ PostCode(sdbusplus::bus::bus& bus, const char* path,
++ EventPtr &event) :
++ sdbusplus::server::object_t<post_code>(bus, path),
++ bus(bus),
++ propertiesChangedSignalRaw(
++ bus,
++ sdbusplus::bus::match::rules::type::signal() +
++ sdbusplus::bus::match::rules::member("PropertiesChanged") +
++ sdbusplus::bus::match::rules::path(PostCodePath) +
++ sdbusplus::bus::match::rules::interface(PropertiesIntf),
++ [this](sdbusplus::message::message &msg) {
++ std::string objectName;
++ std::map<std::string, sdbusplus::message::variant<uint64_t>> msgData;
++ msg.read(objectName, msgData);
++ // Check if it was the Value property that changed.
++ auto valPropMap = msgData.find("Value");
++ {
++ if (valPropMap != msgData.end())
++ {
++ this->savePostCodes(sdbusplus::message::variant_ns::get<uint64_t>(valPropMap->second));
++ }
++ }
++ }),
++ propertiesChangedSignalCurrentHostState(
++ bus,
++ sdbusplus::bus::match::rules::type::signal() +
++ sdbusplus::bus::match::rules::member("PropertiesChanged") +
++ sdbusplus::bus::match::rules::path(HostStatePath) +
++ sdbusplus::bus::match::rules::interface(PropertiesIntf),
++ [this](sdbusplus::message::message &msg) {
++ std::string objectName;
++ std::map<std::string, sdbusplus::message::variant<std::string>> msgData;
++ msg.read(objectName, msgData);
++ // Check if it was the Value property that changed.
++ auto valPropMap = msgData.find("CurrentHostState");
++ {
++ if (valPropMap != msgData.end())
++ {
++ StateServer::Host::HostState currentHostState =
++ StateServer::Host::convertHostStateFromString(
++ sdbusplus::message::variant_ns::get<std::string>(valPropMap->second));
++ if (currentHostState == StateServer::Host::HostState::Off)
++ {
++ if (this->currentBootCycleIndex() >= this->maxBootCycleNum())
++ {
++ this->currentBootCycleIndex(1);
++ } else{
++ this->currentBootCycleIndex(this->currentBootCycleIndex() + 1);
++ }
++ this->postCodes.clear();
++ }
++ }
++ }
++ })
++ {
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "PostCode is created");
++ auto dir = fs::path(PostCodeListPath);
++ fs::create_directories(dir);
++ strPostCodeListPath = PostCodeListPath;
++ strCurrentBootCycleIndexName = CurrentBootCycleIndexName;
++ uint16_t index = 0;
++ deserialize(fs::path(strPostCodeListPath + strCurrentBootCycleIndexName), index);
++ currentBootCycleIndex(index);
++ maxBootCycleNum(MaxPostCodeCycles);
++ if (currentBootCycleIndex() >= maxBootCycleNum())
++ {
++ currentBootCycleIndex(1);
++ } else{
++ currentBootCycleIndex(currentBootCycleIndex() + 1);
++ }
++ }
++ ~PostCode()
++ {
++
++ }
++
++ std::vector<uint64_t> getPostCodes(uint16_t index) override;
++
++ private:
++ sdbusplus::bus::bus& bus;
++ std::vector<uint64_t> postCodes;
++ std::string strPostCodeListPath;
++ std::string strCurrentBootCycleIndexName;
++ void savePostCodes(uint64_t code);
++ sdbusplus::bus::match_t propertiesChangedSignalRaw;
++ sdbusplus::bus::match_t propertiesChangedSignalCurrentHostState;
++ fs::path serialize(const std::string& path);
++ bool deserialize(const fs::path& path, uint16_t& index);
++ bool deserializePostCodes(const fs::path& path, std::vector<uint64_t> &codes);
++};
+diff --git a/service_files/xyz.openbmc_project.State.Boot.PostCode.service b/service_files/xyz.openbmc_project.State.Boot.PostCode.service
+new file mode 100644
+index 0000000..67bc43f
+--- /dev/null
++++ b/service_files/xyz.openbmc_project.State.Boot.PostCode.service
+@@ -0,0 +1,11 @@
++[Unit]
++Description=Post code manager
++
++[Service]
++ExecStart=/usr/bin/env post-code-manager
++SyslogIdentifier=post-code-manager
++Type=dbus
++BusName=xyz.openbmc_project.State.Boot.PostCode
++
++[Install]
++WantedBy=obmc-standby.target
+diff --git a/src/main.cpp b/src/main.cpp
+new file mode 100644
+index 0000000..4a74b29
+--- /dev/null
++++ b/src/main.cpp
+@@ -0,0 +1,61 @@
++/*
++// Copyright (c) 2019 Intel Corporation
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++// http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++*/
++#include "post_code.hpp"
++
++int main(int argc, char* argv[])
++{
++ int ret = 0;
++
++ phosphor::logging::log<phosphor::logging::level::INFO>(
++ "Start post code manager service...");
++
++ sd_event* event = nullptr;
++ ret = sd_event_default(&event);
++ if (ret < 0)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error creating a default sd_event handler");
++ return ret;
++ }
++ EventPtr eventP{event};
++ event = nullptr;
++
++ sdbusplus::bus::bus bus = sdbusplus::bus::new_default();
++ sdbusplus::server::manager_t m{bus, DBUS_OBJECT_NAME};
++
++ bus.request_name(DBUS_INTF_NAME);
++
++ PostCode postCode{bus, DBUS_OBJECT_NAME, eventP};
++
++ try
++ {
++ bus.attach_event(eventP.get(), SD_EVENT_PRIORITY_NORMAL);
++ ret = sd_event_loop(eventP.get());
++ if (ret < 0)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(
++ "Error occurred during the sd_event_loop",
++ phosphor::logging::entry("RET=%d", ret));
++ }
++ }
++ catch (std::exception& e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
++ return -1;
++ }
++ return 0;
++
++}
+diff --git a/src/post_code.cpp b/src/post_code.cpp
+new file mode 100644
+index 0000000..983eeee
+--- /dev/null
++++ b/src/post_code.cpp
+@@ -0,0 +1,109 @@
++/*
++// Copyright (c) 2019 Intel Corporation
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++// http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++*/
++#include "post_code.hpp"
++std::vector<uint64_t> PostCode::getPostCodes(uint16_t index)
++{
++ std::vector<uint64_t> codes;
++
++ if (currentBootCycleIndex() == index)
++ return postCodes;
++ deserializePostCodes(fs::path(strPostCodeListPath + std::to_string(index)), codes);
++ return codes;
++}
++void PostCode::savePostCodes(uint64_t code)
++{
++ postCodes.push_back(code);
++ serialize(fs::path(PostCodeListPath));
++ return;
++}
++
++fs::path PostCode::serialize(const std::string& path)
++{
++ try
++ {
++ uint16_t index = currentBootCycleIndex();
++ fs::path fullPath(path + strCurrentBootCycleIndexName);
++ std::ofstream os(fullPath.c_str(), std::ios::binary);
++ cereal::JSONOutputArchive oarchive(os);
++ oarchive(index);
++
++ std::ofstream osPostCodes((path + std::to_string(currentBootCycleIndex())).c_str(), std::ios::binary);
++ cereal::JSONOutputArchive oarchivePostCodes(osPostCodes);
++ oarchivePostCodes(postCodes);
++
++ return path;
++ }
++ catch (cereal::Exception& e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
++ }
++ catch (const fs::filesystem_error& e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
++ }
++}
++
++bool PostCode::deserialize(const fs::path& path, uint16_t& index)
++{
++ try
++ {
++ if (fs::exists(path))
++ {
++ std::ifstream is(path.c_str(), std::ios::in | std::ios::binary);
++ cereal::JSONInputArchive iarchive(is);
++ iarchive(index);
++ return true;
++ }
++ return false;
++ }
++ catch (cereal::Exception& e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
++ return false;
++ }
++ catch (const fs::filesystem_error& e)
++ {
++ return false;
++ }
++
++ return false;
++}
++
++bool PostCode::deserializePostCodes(const fs::path& path, std::vector<uint64_t> &codes)
++{
++ try
++ {
++ if (fs::exists(path))
++ {
++ std::ifstream is(path.c_str(), std::ios::in | std::ios::binary);
++ cereal::JSONInputArchive iarchive(is);
++ iarchive(codes);
++ return true;
++ }
++ return false;
++ }
++ catch (cereal::Exception& e)
++ {
++ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
++ return false;
++ }
++ catch (const fs::filesystem_error& e)
++ {
++ return false;
++ }
++
++ return false;
++}
+--
+2.19.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager_git.bb
new file mode 100644
index 000000000..8f2ead18a
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/state/post-code-manager_git.bb
@@ -0,0 +1,34 @@
+SUMMARY = "Phosphor post code manager"
+DESCRIPTION = "Post Code Manager"
+
+SRC_URI = "git://github.com/openbmc/phosphor-post-code-manager.git"
+SRCREV = "7f50dcaa6feb66cf5307b8a0e4742a36a50eed29"
+
+S = "${WORKDIR}/git"
+
+PV = "1.0+git${SRCPV}"
+
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327"
+
+inherit cmake pkgconfig systemd
+
+SYSTEMD_SERVICE_${PN} += "xyz.openbmc_project.State.Boot.PostCode.service"
+
+DEPENDS += " \
+ autoconf-archive-native \
+ systemd \
+ sdbusplus \
+ sdbusplus-native \
+ phosphor-dbus-interfaces \
+ phosphor-dbus-interfaces-native \
+ phosphor-logging \
+ "
+RDEPENDS_${PN} += " \
+ libsystemd \
+ sdbusplus \
+ phosphor-dbus-interfaces \
+ phosphor-logging \
+ "
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+SRC_URI += "file://0001-Implement-post-code-manager.patch"