meta-facebook: catalina: phosphor-state-manager: add power action services

Add power action services.

This commit is relies on the below patch:
[1] https://gerrit.openbmc.org/c/openbmc/openbmc/+/69903

Change-Id: I37bd8a191259e4f51534a8cc4b7f77103bea044e
Signed-off-by: Potin Lai <potin.lai@quantatw.com>
diff --git a/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-power-state-init b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-power-state-init
new file mode 100644
index 0000000..d2f8912
--- /dev/null
+++ b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-power-state-init
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+busctl set-property \
+    xyz.openbmc_project.State.Chassis0 \
+    /xyz/openbmc_project/state/chassis0 \
+    xyz.openbmc_project.State.Chassis \
+    CurrentPowerState s \
+    xyz.openbmc_project.State.Chassis.PowerState.On
+
+busctl set-property \
+    xyz.openbmc_project.State.Chassis0 \
+    /xyz/openbmc_project/state/chassis0 \
+    xyz.openbmc_project.State.Chassis \
+    CurrentPowerStatus s \
+    xyz.openbmc_project.State.Chassis.PowerStatus.Good
+
diff --git a/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-power-state-init.conf b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-power-state-init.conf
new file mode 100644
index 0000000..132a42f
--- /dev/null
+++ b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-power-state-init.conf
@@ -0,0 +1,3 @@
+[Service]
+ExecStartPre=/usr/libexec/phosphor-state-manager/chassis-power-state-init
+
diff --git a/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-powercycle b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-powercycle
new file mode 100644
index 0000000..1be59f8
--- /dev/null
+++ b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-powercycle
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# shellcheck source=meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/power-cmd
+source /usr/libexec/phosphor-state-manager/power-cmd
+
+if ! chassis_power_cycle; then
+   phosphor_log_err "chassis power cycle failed"
+   exit 1
+fi
+
+phosphor_log_info "chassis power cycle success"
+exit 0
diff --git a/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-powercycle@.service b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-powercycle@.service
new file mode 100644
index 0000000..1060a5c
--- /dev/null
+++ b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-powercycle@.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Chassis Power Cycle: %i
+Before=obmc-chassis-powercycle@%i.target
+
+[Service]
+Type=oneshot
+ExecStart=/usr/libexec/phosphor-state-manager/chassis-powercycle %i
+
+[Install]
+RequiredBy=obmc-chassis-powercycle@%i.target
diff --git a/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-poweron b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-poweron
new file mode 100644
index 0000000..e7e49a6
--- /dev/null
+++ b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-poweron
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# shellcheck source=meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/power-cmd
+source /usr/libexec/phosphor-state-manager/power-cmd
+
+if ! chassis_power_on; then
+   phosphor_log_err "chassis power on failed"
+   exit 1
+fi
+
+phosphor_log_info "chassis power on success"
+exit 0
diff --git a/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-poweron@.service b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-poweron@.service
new file mode 100644
index 0000000..56aa080
--- /dev/null
+++ b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/chassis-poweron@.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=power on chassis:%i
+Before=obmc-chassis-poweron@%i.target
+
+[Service]
+Type=oneshot
+ExecStart=/usr/libexec/phosphor-state-manager/chassis-poweron %i
+
+[Install]
+RequiredBy=obmc-chassis-poweron@%i.target
diff --git a/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-force-poweroff b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-force-poweroff
new file mode 100644
index 0000000..8e98171
--- /dev/null
+++ b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-force-poweroff
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# shellcheck source=meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/power-cmd
+source /usr/libexec/phosphor-state-manager/power-cmd
+
+if ! host_force_power_off; then
+   phosphor_log_err "host force power off failed"
+   exit 1
+fi
+
+phosphor_log_info "host force power off success"
+exit 0
\ No newline at end of file
diff --git a/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-force-poweroff@.service b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-force-poweroff@.service
new file mode 100644
index 0000000..062d4f2
--- /dev/null
+++ b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-force-poweroff@.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=power off host:%i
+After=obmc-host-stop-pre@%i.target
+Before=obmc-host-stopping@%i.target
+Conflicts=obmc-host-startmin@%i.target
+
+[Service]
+Restart=no
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/libexec/phosphor-state-manager/host-force-poweroff %i
+
+[Install]
+RequiredBy=obmc-host-stop@%i.target
diff --git a/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-graceful-poweroff b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-graceful-poweroff
new file mode 100644
index 0000000..d415896
--- /dev/null
+++ b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-graceful-poweroff
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# shellcheck source=meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/power-cmd
+source /usr/libexec/phosphor-state-manager/power-cmd
+
+if ! host_graceful_power_off; then
+   phosphor_log_err "host graceful power off failed"
+   exit 1
+fi
+
+phosphor_log_info "host graceful power off success"
+exit 0
\ No newline at end of file
diff --git a/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-graceful-poweroff@.service b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-graceful-poweroff@.service
new file mode 100644
index 0000000..c8af4ee
--- /dev/null
+++ b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-graceful-poweroff@.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=power off host:%i
+Wants=obmc-host-stop-pre@%i.target
+Before=obmc-host-stop-pre@%i.target
+Conflicts=obmc-host-start@%i.target
+ConditionPathExists=!/run/openbmc/host@%i-request
+
+[Service]
+Restart=no
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/libexec/phosphor-state-manager/host-graceful-poweroff %i
+
+[Install]
+WantedBy=obmc-host-shutdown@%i.target
diff --git a/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-poweron b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-poweron
new file mode 100644
index 0000000..9840932
--- /dev/null
+++ b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-poweron
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# shellcheck source=meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/power-cmd
+source /usr/libexec/phosphor-state-manager/power-cmd
+
+if ! host_power_on; then
+   phosphor_log_err "host power on failed"
+   exit 1
+fi
+
+phosphor_log_info "host power on success"
+exit 0
diff --git a/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-poweron@.service b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-poweron@.service
new file mode 100644
index 0000000..17b875f
--- /dev/null
+++ b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/host-poweron@.service
@@ -0,0 +1,22 @@
+[Unit]
+Description=power on host:%i
+Wants=obmc-host-start-pre@%i.target
+After=obmc-host-start-pre@%i.target
+Wants=obmc-host-starting@%i.target
+Before=obmc-host-starting@%i.target
+Before=obmc-host-started@%i.target
+Wants=obmc-power-on@%i.target
+After=obmc-power-on@%i.target
+Conflicts=obmc-host-stop@%i.target
+Wants=phosphor-set-host-transition-to-running@service
+Before=phosphor-set-host-transition-to-running@service
+ConditionPathExists=!/run/openbmc/host@%i-on
+
+[Service]
+Restart=no
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/libexec/phosphor-state-manager/host-poweron %i
+
+[Install]
+RequiredBy=obmc-host-startmin@%i.target
diff --git a/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/phosphor-wait-power-off@.service b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/phosphor-wait-power-off@.service
new file mode 100644
index 0000000..d3d6829
--- /dev/null
+++ b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/phosphor-wait-power-off@.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=Wait for Power%i to turn off
+Before=obmc-power-off@%i.target
+Wants=obmc-power-stop@%i.target
+Before=obmc-power-stop@%i.target
+Wants=obmc-power-stop-pre@%i.target
+After=obmc-power-stop-pre@%i.target
+Conflicts=obmc-chassis-poweron@%i.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+# This is wrong, but at least gives us something since we're not using
+# skeleton.
+ExecStart=sleep 10
+ExecStart=/bin/rm -f /run/openbmc/host@%i-request
+
+[Install]
+RequiredBy=obmc-host-stop@%i.target
diff --git a/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/power-cmd b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/power-cmd
new file mode 100644
index 0000000..fc2ae92
--- /dev/null
+++ b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager/power-cmd
@@ -0,0 +1,153 @@
+#!/bin/bash
+
+# shellcheck source=meta-facebook/recipes-fb/obmc_functions/files/fb-common-functions
+source /usr/libexec/fb-common-functions
+
+phosphor_log() {
+    busctl call \
+        xyz.openbmc_project.Logging \
+        /xyz/openbmc_project/logging \
+        xyz.openbmc_project.Logging.Create \
+        Create "ssa{ss}" "$1" "$2" 0
+}
+
+phosphor_log_err() {
+    local msg=$1
+    local logErr="xyz.openbmc_project.Logging.Entry.Level.Error"
+    phosphor_log "$msg" "$logErr"
+}
+
+phosphor_log_info() {
+    local msg=$1
+    local logInfo="xyz.openbmc_project.Logging.Entry.Level.Informational"
+    phosphor_log "$msg" "$logInfo"
+}
+
+chassis_power_cycle_ltc4287()
+{
+    if ! i2cset -f -y 20 0x42 0xfd 0x04; then
+        echo "48V HSC1 set reboot delay failed"
+        return 1
+    fi
+
+    if ! i2cset -f -y 20 0x43 0xfd 0x04; then
+        echo "48V HSC2 set reboot delay failed"
+        return 1
+    fi
+
+    if ! i2cset -f -y 20 0x42 0xfd 0x0c; then
+        echo "48V HSC1 set reboot bit failed"
+        return 1
+    fi
+
+    if ! i2cset -f -y 20 0x43 0xfd 0x0c; then
+        echo "48V HSC2 set reboot bit failed"
+        return 1
+    fi
+
+    return 0
+}
+
+chassis_power_cycle()
+{
+    chassis_power_cycle_ltc4287
+    return $?
+}
+
+chassis_power_on()
+{
+    # MB stabdby power should enabled by before BMC ready
+    # So only do checking here.
+    if [ "$(chassis_power_status)" != "on" ]; then
+        return 1
+    fi
+    return 0
+}
+
+chassis_power_status()
+{
+    if [ "$(get_gpio "STBY_POWER_PG_3V3")" -eq 1 ]; then
+        echo "on"
+    else
+        echo "off"
+    fi
+}
+
+host_power_on()
+{
+    if [ "$(host_power_status)" == "off" ]; then
+        press_host_power_button 1
+        if ! wait_host_power_on; then
+            return 1
+        fi
+    fi
+    return 0
+}
+
+host_force_power_off()
+{
+    if [ "$(host_power_status)" == "on" ]; then
+        press_host_power_button 6
+        if ! wait_host_power_off; then
+            return 1
+        fi
+    fi
+    return 0
+}
+
+host_graceful_power_off()
+{
+    if [ "$(host_power_status)" == "on" ]; then
+        press_host_power_button 1
+        if ! wait_host_power_off; then
+            return 1
+        fi
+    fi
+    return 0
+}
+
+host_power_status()
+{
+    if [ "$(get_gpio "host0-ready")" -eq 1 ]; then
+        echo "on"
+    else
+        echo "off"
+    fi
+}
+
+press_host_power_button()
+{
+    local press_delay_sec="$1"
+    set_gpio "SYS_BMC_PWRBTN_R_N" 1
+    set_gpio "SYS_BMC_PWRBTN_R_N" 0
+    sleep "$press_delay_sec"
+    set_gpio "SYS_BMC_PWRBTN_R_N" 1
+}
+
+wait_host_power_change()
+{
+    local exp_val="$1"
+    local count=0
+    until [ $count -gt 10 ]
+    do
+        sleep 1
+        if [ "$(host_power_status)" == "$exp_val" ]; then
+            return 0
+        fi
+        ((count++))
+    done
+
+    return 1
+}
+
+wait_host_power_on()
+{
+    wait_host_power_change "on"
+    return $?
+}
+
+wait_host_power_off()
+{
+    wait_host_power_change "off"
+    return $?
+}
\ No newline at end of file
diff --git a/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager_%.bbappend b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager_%.bbappend
new file mode 100644
index 0000000..036473e
--- /dev/null
+++ b/meta-facebook/meta-catalina/recipes-phosphor/state/phosphor-state-manager_%.bbappend
@@ -0,0 +1,135 @@
+FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
+
+#===============================================================================
+# TODO: need to be removed once patch merged.
+# meta-facebook: phosphor-state-manager: refactor targets and relationships
+# https://gerrit.openbmc.org/c/openbmc/openbmc/+/69903
+
+PACKAGECONFIG:remove = "only-run-apr-on-power-loss"
+
+# The host-graceful-poweroff service replaces the `pldmSoftPowerOff` and
+# `xyz.openbmc_project.Ipmi.Internal.SoftPowerOff` services to gracefully
+# shutdown the host.
+HOST_DEFAULT_TARGETS:append = " \
+    obmc-host-shutdown@{}.target.requires/host-graceful-poweroff@{}.service \
+    obmc-host-warm-reboot@{}.target.requires/host-graceful-poweroff@{}.service \
+    "
+
+# The "warm-reboot" is what does the graceful shutdown operation and the
+# normal "reboot" is suppose to do a forced reboot.  `host-shutdown` is used
+# as part of the graceful shutdown path, which we want to skip in a normal
+# reboot, so remove the dependency.  The `phosphor-reboot-host@.service` does
+# continue to be in `obmc-host-reboot` requirements and it depends on
+# `obmc-host-stop`, which will initiate a `host-force-poweroff`.
+HOST_DEFAULT_TARGETS:remove = " \
+    obmc-host-reboot@{}.target.requires/obmc-host-shutdown@{}.service \
+    "
+
+# The host-poweron service is the equivalent to the start_host@ service
+# from meta-openpower.
+HOST_DEFAULT_TARGETS:append = " \
+    obmc-host-startmin@{}.target.requires/host-poweron@{}.service \
+    "
+
+# The host-stop service is called as a side-effect of force-warm-reboot and is
+# expected to force-stop the processors.  They will be restarted in the
+# subsequent `obmc-host-reboot` (which calls `host-startmin`)
+HOST_DEFAULT_TARGETS:append = " \
+    obmc-host-stop@{}.target.requires/host-force-poweroff@{}.service \
+    "
+
+# Add services for the chassis power operations.
+CHASSIS_DEFAULT_TARGETS:append = " \
+    obmc-chassis-poweron@{}.target.requires/chassis-poweron@{}.service \
+    obmc-chassis-hard-poweroff@{}.target.requires/chassis-poweroff@{}.service \
+    obmc-chassis-powercycle@{}.target.requires/chassis-powercycle@{}.service \
+    "
+
+# We don't use the obmc-power-start or obmc-power-stop, which use the
+# `org.openbmc` interface but instead install our own chassis-poweron and
+# chassis-poweroff.
+CHASSIS_DEFAULT_TARGETS:remove = " \
+    obmc-chassis-poweron@{}.target.requires/obmc-power-start@{}.service \
+    obmc-chassis-poweroff@{}.target.requires/obmc-power-stop@{}.service \
+    "
+
+# The obmc-chassis-powerreset target is used to determine the state of the host
+# when the BMC resets (to handle cases where the BMC reset while the host is
+# running).  The default implementation of these relies on `org.openbmc`
+# interfaces we do not implement, so we need to remove them.
+CHASSIS_DEFAULT_TARGETS:remove = " \
+    obmc-chassis-powerreset@{}.target.requires/phosphor-reset-chassis-on@{}.service \
+    obmc-chassis-powerreset@{}.target.requires/phosphor-reset-chassis-running@{}.service \
+    "
+
+RDEPENDS:${PN}:append = " bash"
+
+FILES:${PN} += "${systemd_system_unitdir}/*.service"
+FILES:${PN} += "${libexecdir}/${PN}"
+
+CHASSIS_DEFAULT_TARGETS:remove = " \
+    obmc-chassis-poweron@{}.target.wants/chassis-poweron@{}.service \
+    obmc-chassis-hard-poweroff@{}.target.wants/chassis-poweroff@{}.service \
+    obmc-chassis-powercycle@{}.target.wants/chassis-powercycle@{}.service \
+"
+
+HOST_DEFAULT_TARGETS:remove = " \
+    obmc-host-shutdown@{}.target.wants/host-poweroff@{}.service \
+    obmc-host-start@{}.target.wants/host-poweron@{}.service \
+    obmc-host-reboot@{}.target.wants/host-powercycle@{}.service \
+    obmc-host-force-warm-reboot@{}.target.wants/host-powerreset@{}.service \
+"
+#===============================================================================
+
+RDEPENDS:${PN}:append = " bash"
+PACKAGECONFIG:append = " host-gpio"
+
+SRC_URI:append = " \
+    file://chassis-power-state-init \
+    file://chassis-power-state-init.conf \
+    file://chassis-powercycle \
+    file://chassis-powercycle@.service \
+    file://chassis-poweron \
+    file://chassis-poweron@.service \
+    file://host-force-poweroff \
+    file://host-force-poweroff@.service \
+    file://host-graceful-poweroff \
+    file://host-graceful-poweroff@.service \
+    file://host-poweron \
+    file://host-poweron@.service \
+    file://power-cmd \
+    file://phosphor-wait-power-off@.service \
+    "
+
+# Catalina chassis off is host force off
+CHASSIS_DEFAULT_TARGETS:remove = " \
+    obmc-chassis-hard-poweroff@{}.target.requires/chassis-poweroff@{}.service \
+    "
+CHASSIS_DEFAULT_TARGETS:append = " \
+    obmc-chassis-hard-poweroff@{}.target.requires/host-force-poweroff@{}.service \
+    "
+
+#We need to ensure that the chassis power is always on.
+CHASSIS_DEFAULT_TARGETS:remove = " \
+    obmc-host-shutdown@{}.target.requires/obmc-chassis-poweroff@{}.target \
+    "
+HARD_OFF_TMPL_CTRL=""
+HARD_OFF_TGTFMT_CTRL=""
+HARD_OFF_FMT_CTRL=""
+HARD_OFF_INSTFMT_CTRL=""
+
+do_install:append() {
+    install -d ${D}${systemd_system_unitdir}
+    install -m 0644 ${WORKDIR}/*.service ${D}${systemd_system_unitdir}/
+
+    install -d ${D}${libexecdir}/${PN}
+    install -m 0755 ${WORKDIR}/chassis-power-state-init ${D}${libexecdir}/${PN}/
+    install -m 0755 ${WORKDIR}/chassis-poweron ${D}${libexecdir}/${PN}/
+    install -m 0755 ${WORKDIR}/chassis-powercycle ${D}${libexecdir}/${PN}/
+    install -m 0755 ${WORKDIR}/host-force-poweroff ${D}${libexecdir}/${PN}/
+    install -m 0755 ${WORKDIR}/host-graceful-poweroff ${D}${libexecdir}/${PN}/
+    install -m 0755 ${WORKDIR}/host-poweron ${D}${libexecdir}/${PN}/
+    install -m 0755 ${WORKDIR}/power-cmd ${D}${libexecdir}/${PN}/
+}
+
+SYSTEMD_OVERRIDE:${PN}-host += "chassis-power-state-init.conf:xyz.openbmc_project.State.Host@0.service.d/chassis-power-state-init.conf"