meta-ampere: support Altra Boot Progress handling

Handle Altra Boot Progress reported from SCP regiter map by the use of
smpro-misc driver.

Tested: check boot progress is updated in Redfish for:
1. Reboot Host.
2. IPMI chassis power reset
3. IPMI chassis power cycle
4. IPMI chassis power off, then on
5. WebUI Orderly – OS shuts down, then server reboots
6. WebUI Immediate – Server reboots without OS shutting down

Signed-off-by: Thang Q. Nguyen <thang@os.amperecomputing.com>
Change-Id: I9483328ccf5731904d0e6e71074561f7dd743bed
diff --git a/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress.bb b/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress.bb
new file mode 100644
index 0000000..823bea7
--- /dev/null
+++ b/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress.bb
@@ -0,0 +1,33 @@
+SUMMARY = "Altra Boot Progress Handling Service"
+DESCRIPTION = "OpenBMC Altra Boot Progress Handling Daemon"
+
+PR = "r1"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+
+inherit systemd
+inherit obmc-phosphor-systemd
+
+DEPENDS += "systemd"
+RDEPENDS:${PN} += "libsystemd"
+RDEPENDS:${PN} += "bash"
+
+SRC_URI = " \
+           file://ampere_boot_progress.sh \
+          "
+
+SYSTEMD_PACKAGES = "${PN}"
+
+HOST_ON_RESET_HOSTTMPL = "ampere-boot-progress.service"
+HOST_ON_RESET_HOSTINSTMPL = "ampere-boot-progress.service"
+HOST_ON_RESET_HOSTTGTFMT = "obmc-host-already-on@{0}.target"
+HOST_ON_RESET_HOSTFMT = "../${HOST_ON_RESET_HOSTTMPL}:${HOST_ON_RESET_HOSTTGTFMT}.requires/${HOST_ON_RESET_HOSTINSTMPL}"
+SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'HOST_ON_RESET_HOSTFMT', 'OBMC_HOST_INSTANCES')}"
+
+SYSTEMD_SERVICE:${PN} += "${HOST_ON_RESET_HOSTTMPL}"
+
+do_install () {
+    install -d ${D}${sbindir}
+    install -m 0755 ${WORKDIR}/ampere_boot_progress.sh ${D}${sbindir}/
+}
+
diff --git a/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress/ampere-boot-progress.service b/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress/ampere-boot-progress.service
new file mode 100644
index 0000000..267d901
--- /dev/null
+++ b/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress/ampere-boot-progress.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=Ampere Altra Boot Progress Handling
+After=ampere-host-already-on@0.target
+BindTo=obmc-host-already-on@0.target
+
+[Service]
+Restart=simple
+ExecStart=/usr/sbin/ampere_boot_progress.sh
+SyslogIdentifier=ampere-boot-progress
+RemainAfterExit=no
+
+[Install]
+WantedBy=obmc-host-already-on@0.target
diff --git a/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress/ampere_boot_progress.sh b/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress/ampere_boot_progress.sh
new file mode 100755
index 0000000..87ad34f
--- /dev/null
+++ b/meta-ampere/meta-common/recipes-ampere/host/ac01-boot-progress/ampere_boot_progress.sh
@@ -0,0 +1,201 @@
+#!/bin/bash
+# Initialize variables
+boot_stage=00
+boot_status=00
+uefi_code=00000000
+
+function set_postcode()
+{
+	# shellcheck disable=SC2086
+	busctl set-property xyz.openbmc_project.State.Boot.Raw \
+		/xyz/openbmc_project/state/boot/raw0 \
+		xyz.openbmc_project.State.Boot.Raw Value \(tay\) "$1" 0
+}
+
+function update_boot_progress_last_state_time()
+{
+	# Get BMC current time
+	bp_last_state_time=$(busctl get-property xyz.openbmc_project.Time.Manager \
+		/xyz/openbmc_project/time/bmc \
+		xyz.openbmc_project.Time.EpochTime \
+		Elapsed | cut -d' ' -f2)
+
+	# Update the Boot Progress LastStateTime
+	busctl set-property xyz.openbmc_project.State.Host \
+		/xyz/openbmc_project/state/host0 \
+		xyz.openbmc_project.State.Boot.Progress \
+		BootProgressLastUpdate t \
+		"$bp_last_state_time"
+}
+
+function update_boot_progress()
+{
+	bootprog=$1
+
+	busctl set-property xyz.openbmc_project.State.Host \
+		/xyz/openbmc_project/state/host0 \
+		xyz.openbmc_project.State.Boot.Progress \
+		BootProgress s \
+		"xyz.openbmc_project.State.Boot.Progress.ProgressStages.$bootprog"
+
+	# Update Boot Progress LastStateTime
+	update_boot_progress_last_state_time
+}
+
+function get_boot_stage_string()
+{
+	bootstage=$1
+	ueficode=$2
+
+	case $bootstage in
+
+		00)
+			boot_stage_str="SMpro"
+			;;
+
+		01)
+			boot_stage_str="PMpro"
+			;;
+
+		02)
+			boot_stage_str="ATF BL1 (Code=${ueficode})"
+			;;
+
+		03)
+			boot_stage_str="DDR initialization (Code=${ueficode})"
+			;;
+
+		04)
+			boot_stage_str="DDR training progress (Code=${ueficode})"
+			;;
+
+		05)
+			boot_stage_str="ATF BL2 (Code=${ueficode})"
+			;;
+
+		06)
+			boot_stage_str="ATF BL31 (Code=${ueficode})"
+			;;
+
+		07)
+			boot_stage_str="ATF BL32 (Code=${ueficode})"
+			;;
+
+		08)
+			boot_stage_str="UEFI booting (UEFI Code=${ueficode})"
+			;;
+		09)
+			boot_stage_str="OS booting"
+			;;
+
+	esac
+
+	echo "$boot_stage_str"
+}
+
+function set_boot_progress()
+{
+	boot_stage=$1
+	uefi_code=$2
+
+	case $boot_stage in
+
+		02)
+			update_boot_progress "PrimaryProcInit"
+			;;
+
+		03)
+			update_boot_progress "MemoryInit"
+			;;
+
+		08)
+			if [[ "$uefi_code" =~ 0201* ]]; then
+				update_boot_progress "PCIInit"
+			fi
+			;;
+		09)
+			update_boot_progress "OSStart"
+			;;
+
+	esac
+}
+
+function log_redfish_biosboot_ok_event()
+{
+	logger-systemd --journald << EOF
+MESSAGE=
+PRIORITY=2
+SEVERITY=
+REDFISH_MESSAGE_ID=OpenBMC.0.1.BIOSBoot.OK
+REDFISH_MESSAGE_ARGS="UEFI firmware booting done"
+EOF
+}
+
+function log_redfish_bios_panic_event()
+{
+	boot_state_str=$(get_boot_stage_string "$1" "$2")
+
+	logger-systemd --journald << EOF
+MESSAGE=
+PRIORITY=2
+SEVERITY=
+REDFISH_MESSAGE_ID=OpenBMC.0.1.BIOSFirmwarePanicReason.Warning
+REDFISH_MESSAGE_ARGS=${boot_state_str}
+EOF
+}
+
+cnt=0
+# If any reason makes SCP fail to access in 6s, break the service.
+while [ $cnt -lt 30 ];
+do
+	# Sleep 200ms
+	usleep 200000
+	if ! read -r bg <<< "$(cat /sys/bus/platform/devices/smpro-misc.2.auto/boot_progress)";
+	then
+		cnt=$((cnt + 1))
+		continue
+	fi
+	cnt=0
+
+	# Check if any update from previous check
+	if [ "$last_bg" == "$bg" ]; then
+		continue
+	fi
+	last_bg=$bg
+
+	# Check if the Host is already ON or not. If Host is already boot, update boot progress and break.
+	if [ "${boot_stage}" == "00" ] && [ "${bg[0]}" == "09" ];
+	then
+		update_boot_progress "OSRunning"
+		break
+	fi
+
+	# Update current boot progress
+	boot_stage=${bg:2:2}
+	boot_status=${bg:0:2}
+	uefi_code=${bg:4}
+	echo "Boot Progress = ${boot_stage} ${boot_status} ${uefi_code}"
+
+	# Log Boot Progress to dbus
+	if [ "${boot_status}" == "03" ]; then
+		# Log Redfish Event if failure.
+		log_redfish_bios_panic_event "$boot_stage" "$uefi_code"
+	elif [ "${boot_status}" == "01" ]; then
+		# Check and set boot progress to dbus
+		set_boot_progress "$boot_stage" "$uefi_code"
+	fi
+
+	# Log POST Code to dbus.
+	set_postcode "0x$boot_stage$boot_status$uefi_code"
+
+	# Stop the service when booting to OS
+	if [ "${boot_stage}" == "08" ] && [ "${boot_status}" == "02" ]; then
+		update_boot_progress "SystemInitComplete"
+		log_redfish_biosboot_ok_event
+	elif [ "${boot_stage}" == "09" ] && [ "${boot_status}" == "02" ];
+	then
+		update_boot_progress "OSRunning"
+		break
+	fi
+done
+
diff --git a/meta-ampere/meta-common/recipes-phosphor/host/phosphor-host-postd_%.bbappend b/meta-ampere/meta-common/recipes-phosphor/host/phosphor-host-postd_%.bbappend
new file mode 100644
index 0000000..6e2f476
--- /dev/null
+++ b/meta-ampere/meta-common/recipes-phosphor/host/phosphor-host-postd_%.bbappend
@@ -0,0 +1 @@
+SNOOP_DEVICE = ""
diff --git a/meta-ampere/meta-jade/recipes-ampere/packagegroups/packagegroup-ampere-apps.bb b/meta-ampere/meta-jade/recipes-ampere/packagegroups/packagegroup-ampere-apps.bb
index 2d3f302..7086190 100644
--- a/meta-ampere/meta-jade/recipes-ampere/packagegroups/packagegroup-ampere-apps.bb
+++ b/meta-ampere/meta-jade/recipes-ampere/packagegroups/packagegroup-ampere-apps.bb
@@ -28,6 +28,9 @@
         phosphor-hostlogger \
         phosphor-sel-logger \
         phosphor-logging \
+        ac01-boot-progress \
+        phosphor-post-code-manager \
+        phosphor-host-postd \
         "
 
 SUMMARY:${PN}-system = "Ampere System"