meta-ampere: mtmitchell: add some helper utils
Add some help scripts to help users easier to debug systems from BMC
console.
Tested:
1. New helper scripts are available from BMC console.
2. Manually check script execution
Signed-off-by: Thang Q. Nguyen <thang@os.amperecomputing.com>
Change-Id: Ibe93547d1299768ae8d67440f161c86c29dbb61e
diff --git a/meta-ampere/meta-common/recipes-ampere/platform/ampere-utils.bb b/meta-ampere/meta-common/recipes-ampere/platform/ampere-utils.bb
index c0ae7bd..7c71b95 100644
--- a/meta-ampere/meta-common/recipes-ampere/platform/ampere-utils.bb
+++ b/meta-ampere/meta-common/recipes-ampere/platform/ampere-utils.bb
@@ -7,6 +7,8 @@
SRC_URI = " \
file://ampere_add_redfishevent.sh \
file://ampere_update_mac.sh \
+ file://ampere_spi_util.sh \
+ file://ampere_power_control_lock.sh \
"
RDEPENDS:${PN} = "bash"
@@ -15,4 +17,6 @@
install -d ${D}/usr/sbin
install -m 0755 ${WORKDIR}/ampere_add_redfishevent.sh ${D}/${sbindir}/
install -m 0755 ${WORKDIR}/ampere_update_mac.sh ${D}/${sbindir}/
+ install -m 0755 ${WORKDIR}/ampere_spi_util.sh ${D}/${sbindir}/
+ install -m 0755 ${WORKDIR}/ampere_power_control_lock.sh ${D}/${sbindir}/
}
diff --git a/meta-ampere/meta-common/recipes-ampere/platform/ampere-utils/ampere_power_control_lock.sh b/meta-ampere/meta-common/recipes-ampere/platform/ampere-utils/ampere_power_control_lock.sh
new file mode 100644
index 0000000..db78c43
--- /dev/null
+++ b/meta-ampere/meta-common/recipes-ampere/platform/ampere-utils/ampere_power_control_lock.sh
@@ -0,0 +1,99 @@
+#!/bin/bash
+
+declare -a power_reboot_targets=(
+ obmc-host-reboot@0.target
+ obmc-host-warm-reboot@0.target
+ obmc-host-force-warm-reboot@0.target
+ )
+
+declare -a power_off_targets=(
+ obmc-chassis-hard-poweroff@0.target
+ )
+
+declare -a power_on_targets=(
+ obmc-host-start@0.target
+ )
+
+systemd1_service="org.freedesktop.systemd1"
+systemd1_object_path="/org/freedesktop/systemd1"
+systemd1_manager_interface="org.freedesktop.systemd1.Manager"
+mask_method="MaskUnitFiles"
+unmask_method="UnmaskUnitFiles"
+
+function mask_reboot_targets()
+{
+ # To prevent reboot actions, this function will mask all reboot targets
+ for target in "${power_reboot_targets[@]}"
+ do
+ busctl call $systemd1_service $systemd1_object_path $systemd1_manager_interface \
+ $mask_method asbb 1 "$target" true true
+ done
+}
+
+function unmask_reboot_targets()
+{
+ # Allow reboot targets work normal
+ for target in "${power_reboot_targets[@]}"
+ do
+ busctl call $systemd1_service $systemd1_object_path $systemd1_manager_interface \
+ $unmask_method asb 1 "$target" true
+ done
+}
+
+function mask_off_targets()
+{
+ # To prevent off actions,this function will mask all off targets
+ for target in "${power_off_targets[@]}"
+ do
+ busctl call $systemd1_service $systemd1_object_path $systemd1_manager_interface \
+ $mask_method asbb 1 "$target" true true
+ done
+}
+
+function unmask_off_targets()
+{
+ # Allow off targets work normal
+ for target in "${power_off_targets[@]}"
+ do
+ busctl call $systemd1_service $systemd1_object_path $systemd1_manager_interface \
+ $unmask_method asb 1 "$target" true
+ done
+}
+
+function mask_on_targets()
+{
+ # To prevent on actions, this function will mask all on targets
+ systemctl mask "${power_on_targets[@]}" --runtime
+}
+
+function unmask_on_targets()
+{
+ # Allow on targets work normal
+ systemctl unmask "${power_on_targets[@]}" --runtime
+}
+
+purpose=$1
+allow=$2
+
+if [ "$purpose" == "reboot" ]; then
+ if [ "$allow" == "false" ]
+ then
+ mask_reboot_targets
+ else
+ unmask_reboot_targets
+ fi
+elif [ "$purpose" == "off" ]; then
+ if [ "$allow" == "false" ]
+ then
+ mask_off_targets
+ else
+ unmask_off_targets
+ fi
+elif [ "$purpose" == "on" ]; then
+ if [ "$allow" == "false" ]
+ then
+ mask_on_targets
+ else
+ unmask_on_targets
+ fi
+fi
diff --git a/meta-ampere/meta-common/recipes-ampere/platform/ampere-utils/ampere_spi_util.sh b/meta-ampere/meta-common/recipes-ampere/platform/ampere-utils/ampere_spi_util.sh
new file mode 100755
index 0000000..ad3df4e
--- /dev/null
+++ b/meta-ampere/meta-common/recipes-ampere/platform/ampere-utils/ampere_spi_util.sh
@@ -0,0 +1,242 @@
+#!/bin/bash
+
+# shellcheck disable=SC2046
+# shellcheck source=meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/gpio-lib.sh
+source /usr/sbin/gpio-lib.sh
+
+spi_address="1e630000.spi"
+spi_bind="/sys/bus/platform/drivers/spi-aspeed-smc/bind"
+spi_unbind="/sys/bus/platform/drivers/spi-aspeed-smc/unbind"
+spi_lock="/run/platform/spi.lock"
+spi_lock_dir="/run/platform"
+
+bind_aspeed_smc_driver() {
+ if [ -f "${spi_lock}" ]; then
+ pid=$1
+ pid_lock=$(cat "${spi_lock}")
+ if [[ "${pid}" != "${pid_lock}" ]]; then
+ echo "SPI-NOR resoure is lock by process $pid_lock"
+ return 1
+ fi
+ fi
+
+ # BMC access SPI-NOR resource
+ gpio_name_set spi0-program-sel 1
+ sleep 0.1
+ echo "Bind the ASpeed SMC driver"
+ echo "${spi_address}" > "${spi_bind}" 2>/dev/null
+ # Check the HNOR partition available
+ HOST_MTD=$(< /proc/mtd grep "pnor" | sed -n 's/^\(.*\):.*/\1/p')
+ if [ -z "$HOST_MTD" ]; then
+ echo "${spi_address}" > "${spi_unbind}"
+ sleep 0.1
+ echo "${spi_address}" > "${spi_bind}"
+ fi
+ # BMC release SPI-NOR resource
+ gpio_name_set spi0-program-sel 0
+ return 0
+}
+
+unbind_aspeed_smc_driver() {
+ if [ -f "${spi_lock}" ]; then
+ pid=$1
+ pid_lock=$(cat "${spi_lock}")
+ if [[ "${pid}" != "${pid_lock}" ]]; then
+ echo "SPI-NOR resoure is lock by process $pid_lock . Wait 10s"
+ # Wait maximum 10 seconds for unlock SPI-NOR
+ cnt=10
+ while [ $cnt -gt 0 ]
+ do
+ if [ -f "${spi_lock}" ]; then
+ sleep 1
+ cnt=$((cnt - 1))
+ else
+ break
+ fi
+ done
+ if [ "$cnt" -eq "0" ]; then
+ echo "Timeout 10 seconds, SPI-NOR still busy. Force unlock to access SPI"
+ rm -f "${spi_lock}"
+ fi
+ fi
+ fi
+
+ HOST_MTD=$(< /proc/mtd grep "pnor" | sed -n 's/^\(.*\):.*/\1/p')
+ if [ -n "$HOST_MTD" ]; then
+ # If the HNOR partition is available, then unbind driver
+ # BMC access SPI-NOR resource
+ gpio_name_set spi0-program-sel 1
+ sleep 0.1
+ echo "Unbind the ASpeed SMC driver"
+ echo "${spi_address}" > "${spi_unbind}"
+ fi
+ # BMC release SPI-NOR resource
+ gpio_name_set spi0-program-sel 0
+ # Deassert BMC access SPI-NOR pin
+ gpio_name_set spi-nor-access 0
+ sleep 0.5
+ return 0
+}
+
+lock_spi_resource() {
+ # Wait maximum 10 seconds to lock SPI-NOR
+ cnt=10
+ while [ $cnt -gt 0 ]
+ do
+ if [ -f "${spi_lock}" ]; then
+ sleep 1
+ cnt=$((cnt - 1))
+ else
+ echo "$1" > "${spi_lock}"
+ break
+ fi
+ done
+
+ if [ "$cnt" -eq "0" ]; then
+ echo "Timeout 10 seconds, SPI-NOR is still locked by another process"
+ return 1
+ fi
+ return 0
+}
+
+unlock_spi_resource() {
+ if [ ! -f "${spi_lock}" ]; then
+ echo "SPI-NOR is already unlocked"
+ return 0
+ fi
+
+ pid=$1
+ pid_lock=$(cat "${spi_lock}")
+ if [[ "${pid}" == "${pid_lock}" ]]; then
+ rm -f "${spi_lock}"
+ else
+ echo "Cannot unlock, SPI-NOR is locked by another process"
+ return 1
+ fi
+ return 0
+}
+
+start_handshake_spi() {
+ if [ -f "${spi_lock}" ]; then
+ pid=$1
+ pid_lock=$(cat "${spi_lock}")
+ if [[ "${pid}" != "${pid_lock}" ]]; then
+ echo "SPI-NOR resoure is lock by process $pid_lock"
+ return 1
+ fi
+ fi
+
+ # Wait maximum 10 seconds to grant access SPI
+ cnt=10
+ while [ $cnt -gt 0 ]
+ do
+ spinor_access=$(gpio_name_get soc-spi-nor-access)
+ if [ "$spinor_access" == "1" ]; then
+ sleep 1
+ cnt=$((cnt - 1))
+ else
+ break
+ fi
+ done
+
+ if [ "$cnt" -eq "0" ]; then
+ echo "Timeout 10 seconds, host is still hold SPI-NOR."
+ return 1
+ fi
+ echo "Start handshake SPI-NOR"
+ # Grant BMC access SPI-NOR. The process call the scripts should only
+ # claim the bus for only maximum period 500ms.
+ gpio_name_set spi-nor-access 1
+ # Switch the Host SPI-NOR to BMC
+ gpio_name_set spi0-program-sel 1
+}
+
+stop_handshake_spi() {
+ if [ -f "${spi_lock}" ]; then
+ pid=$1
+ pid_lock=$(cat "${spi_lock}")
+ if [[ "${pid}" != "${pid_lock}" ]]; then
+ echo "SPI-NOR resoure is lock by process $pid_lock"
+ return 1
+ fi
+ fi
+ echo "Stop handshake SPI-NOR"
+ # Switch the Host SPI-NOR to HOST
+ gpio_name_set spi0-program-sel 0
+ # Deassert BMC access SPI-NOR pin
+ gpio_name_set spi-nor-access 0
+}
+
+
+if [ $# -eq 0 ]; then
+ echo "Usage:"
+ echo " - Handshake access SPI-NOR "
+ echo " $(basename "$0") cmd pid"
+ echo " <cmd>:"
+ echo " lock - lock the SPI-NOR resource"
+ echo " unlock - unlock the SPI-NOR resource"
+ echo " bind - bind the SPI-NOR resource"
+ echo " unbind - unbind the SPI-NOR resource"
+ echo " start_handshake - start handshake between BMC and Host"
+ echo " stop_handshake - release handshake between BMC and Host"
+ echo " <pid>: Optional - PID of the process call script"
+ exit 0
+fi
+
+CMD=$1
+
+if [ ! -d "${spi_lock_dir}" ]; then
+ mkdir -p "${spi_lock_dir}"
+fi
+
+if [ -z "$2" ]; then
+ PID=$$
+else
+ PID=$2
+fi
+
+if [[ "${CMD}" == "lock" ]]; then
+ lock_spi_resource "${PID}"
+ ret=$?
+ if [[ "${ret}" == "1" ]]; then
+ echo "Cannot lock SPI-NOR, the resource is busy"
+ exit 1
+ fi
+elif [[ "${CMD}" == "unlock" ]]; then
+ unlock_spi_resource "${PID}"
+ ret=$?
+ if [[ "${ret}" == "1" ]]; then
+ echo "Cannot unlock SPI-NOR, the resource is busy"
+ exit 1
+ fi
+elif [[ "${CMD}" == "bind" ]]; then
+ bind_aspeed_smc_driver "${PID}"
+ ret=$?
+ if [[ "${ret}" == "1" ]]; then
+ echo "Cannot bind SPI-NOR, the resource is busy"
+ exit 1
+ fi
+elif [[ "${CMD}" == "unbind" ]]; then
+ unbind_aspeed_smc_driver "${PID}"
+ ret=$?
+ if [[ "${ret}" == "1" ]]; then
+ echo "Cannot unbind SPI-NOR, the resource is busy"
+ exit 1
+ fi
+elif [[ "${CMD}" == "start_handshake" ]]; then
+ start_handshake_spi "${PID}"
+ ret=$?
+ if [[ "${ret}" == "1" ]]; then
+ echo "Cannot start handshake SPI-NOR"
+ exit 1
+ fi
+elif [[ "${CMD}" == "stop_handshake" ]]; then
+ stop_handshake_spi "${PID}"
+ ret=$?
+ if [[ "${ret}" == "1" ]]; then
+ echo "Cannot stop handshake SPI-NOR"
+ exit 1
+ fi
+fi
+
+exit 0