1b50fedbcSChanh Nguyen#!/bin/bash
2b50fedbcSChanh Nguyen
3b50fedbcSChanh Nguyen# This script is used to flash the UEFI/EDKII
4b50fedbcSChanh Nguyen
5b50fedbcSChanh Nguyen# Syntax: ampere_flash_bios.sh $image_file $device_sellect
6b50fedbcSChanh Nguyen# Where:
7b50fedbcSChanh Nguyen#       $image_file : the image binary file
8b50fedbcSChanh Nguyen#       $device_sellect : 1 - Host Main SPI Nor
9b50fedbcSChanh Nguyen#                         2 - Host Second SPI Nor
10b50fedbcSChanh Nguyen
11b50fedbcSChanh Nguyen# Author : Chanh Nguyen (chnguyen@amperecomputing.com)
12b50fedbcSChanh Nguyen
13b50fedbcSChanh Nguyen# Note:
14b50fedbcSChanh Nguyen#      BMC_GPIOW6_SPI0_PROGRAM_SEL (GPIO 182): 1 => BMC owns SPI bus for upgrading
15b50fedbcSChanh Nguyen#                                              0 => HOST owns SPI bus for upgrading
16b50fedbcSChanh Nguyen
17b50fedbcSChanh Nguyen#      BMC_GPIOW7_SPI0_BACKUP_SEL (GPIO 183) :  1 => to switch SPI_CS0_L to primary SPI Nor device
18b50fedbcSChanh Nguyen#                                               0 => to switch SPI_CS0_L to second SPI Nor device
19b50fedbcSChanh Nguyen
20b50fedbcSChanh Nguyen# shellcheck disable=SC2046
21*e6a0291eSThang Q. Nguyen# shellcheck disable=SC2086
22b50fedbcSChanh Nguyen
23b50fedbcSChanh Nguyendo_flash () {
24*e6a0291eSThang Q. Nguyen	# always unbind then bind the ASpeed SMC driver again to prevent
25*e6a0291eSThang Q. Nguyen	# the changing of the device erasesize by nvparm
26b50fedbcSChanh Nguyen	HOST_MTD=$(< /proc/mtd grep "pnor" | sed -n 's/^\(.*\):.*/\1/p')
27*e6a0291eSThang Q. Nguyen	if [ -n "$HOST_MTD" ];
28b50fedbcSChanh Nguyen	then
29b50fedbcSChanh Nguyen		echo 1e630000.spi > /sys/bus/platform/drivers/spi-aspeed-smc/unbind
30b50fedbcSChanh Nguyen		sleep 2
31b50fedbcSChanh Nguyen	fi
32b50fedbcSChanh Nguyen	echo 1e630000.spi > /sys/bus/platform/drivers/spi-aspeed-smc/bind
33b50fedbcSChanh Nguyen
34*e6a0291eSThang Q. Nguyen	# Check the PNOR partition available
35b50fedbcSChanh Nguyen	HOST_MTD=$(< /proc/mtd grep "pnor" | sed -n 's/^\(.*\):.*/\1/p')
36b50fedbcSChanh Nguyen	if [ -z "$HOST_MTD" ];
37b50fedbcSChanh Nguyen	then
38*e6a0291eSThang Q. Nguyen		echo "Fail to probe the Host SPI-NOR device"
39b50fedbcSChanh Nguyen		exit 1
40b50fedbcSChanh Nguyen	fi
41b50fedbcSChanh Nguyen
42b50fedbcSChanh Nguyen	echo "--- Flashing firmware image $IMAGE to @/dev/$HOST_MTD"
43b50fedbcSChanh Nguyen	flashcp -v "$IMAGE" /dev/"$HOST_MTD"
44b50fedbcSChanh Nguyen}
45b50fedbcSChanh Nguyen
46b50fedbcSChanh Nguyen
47b50fedbcSChanh Nguyenif [ $# -eq 0 ]; then
487fc10f7eSHieu Huynh	echo "Usage: $(basename "$0") <UEFI/EDKII image file> <DEV_SEL> [SPECIAL_BOOT]"
497fc10f7eSHieu Huynh	echo "Where:"
507fc10f7eSHieu Huynh	echo "    DEV_SEL 1 is Primary SPI (by default), 2 is Second SPI"
51*e6a0291eSThang Q. Nguyen	echo "    SPECIAL_BOOT: Optional, input '1' to flash "Secure Provisioning" image and enter Special Boot mode. Default: 0"
52b50fedbcSChanh Nguyen	exit 0
53b50fedbcSChanh Nguyenfi
54b50fedbcSChanh Nguyen
55b50fedbcSChanh NguyenIMAGE="$1"
56b50fedbcSChanh Nguyenif [ ! -f "$IMAGE" ]; then
57b50fedbcSChanh Nguyen	echo "The image file $IMAGE does not exist"
58b50fedbcSChanh Nguyen	exit 1
59b50fedbcSChanh Nguyenfi
60b50fedbcSChanh Nguyen
61b50fedbcSChanh Nguyenif [ -z "$2" ]; then
62b50fedbcSChanh Nguyen       DEV_SEL="1"    # by default, select primary device
63b50fedbcSChanh Nguyenelse
64b50fedbcSChanh Nguyen       DEV_SEL="$2"
65b50fedbcSChanh Nguyenfi
66b50fedbcSChanh Nguyen
677fc10f7eSHieu HuynhSPECIAL_BOOT=0
687fc10f7eSHieu Huynhif [[ "$3" == "1" ]]; then
697fc10f7eSHieu Huynh	SPECIAL_BOOT=1
707fc10f7eSHieu Huynhfi
717fc10f7eSHieu Huynh
727fc10f7eSHieu Huynhecho "SPECIAL_BOOT mode: $SPECIAL_BOOT"
73b50fedbcSChanh Nguyen# Turn off the Host if it is currently ON
74b50fedbcSChanh Nguyenchassisstate=$(obmcutil chassisstate | awk -F. '{print $NF}')
75b50fedbcSChanh Nguyenecho "--- Current Chassis State: $chassisstate"
76b50fedbcSChanh Nguyenif [ "$chassisstate" == 'On' ];
77b50fedbcSChanh Nguyenthen
78b50fedbcSChanh Nguyen	echo "--- Turning the Chassis off"
79b50fedbcSChanh Nguyen	obmcutil chassisoff
80b50fedbcSChanh Nguyen	sleep 10
81b50fedbcSChanh Nguyen	# Check if HOST was OFF
82b50fedbcSChanh Nguyen	chassisstate_off=$(obmcutil chassisstate | awk -F. '{print $NF}')
83b50fedbcSChanh Nguyen	if [ "$chassisstate_off" == 'On' ];
84b50fedbcSChanh Nguyen	then
85b50fedbcSChanh Nguyen		echo "--- Error : Failed turning the Chassis off"
86b50fedbcSChanh Nguyen		exit 1
87b50fedbcSChanh Nguyen	fi
88b50fedbcSChanh Nguyenfi
89b50fedbcSChanh Nguyen
90b50fedbcSChanh Nguyen# Switch the host SPI bus to BMC"
91b50fedbcSChanh Nguyenecho "--- Switch the host SPI bus to BMC."
92b50fedbcSChanh Nguyenif ! gpioset $(gpiofind spi0-program-sel)=1; then
93b50fedbcSChanh Nguyen	echo "ERROR: Switch the host SPI bus to BMC. Please check gpio state"
94b50fedbcSChanh Nguyen	exit 1
95b50fedbcSChanh Nguyenfi
96b50fedbcSChanh Nguyen
97b50fedbcSChanh Nguyen# Switch the host SPI bus (between primary and secondary)
98b50fedbcSChanh Nguyen# 183 is BMC_GPIOW7_SPI0_BACKUP_SEL
99b50fedbcSChanh Nguyenif [[ $DEV_SEL == 1 ]]; then
100b50fedbcSChanh Nguyen	echo "Run update Primary Host SPI-NOR"
101b50fedbcSChanh Nguyen	gpioset $(gpiofind spi0-backup-sel)=1       # Primary SPI
102b50fedbcSChanh Nguyenelif [[ $DEV_SEL == 2 ]]; then
103*e6a0291eSThang Q. Nguyen	echo "Run update Secondary Host SPI-NOR"
104b50fedbcSChanh Nguyen	gpioset $(gpiofind spi0-backup-sel)=0       # Second SPI
105b50fedbcSChanh Nguyenelse
106b50fedbcSChanh Nguyen	echo "Please choose primary SPI (1) or second SPI (2)"
107b50fedbcSChanh Nguyen	exit 0
108b50fedbcSChanh Nguyenfi
109b50fedbcSChanh Nguyen
110*e6a0291eSThang Q. Nguyen# Restrict to flash Secondary Host SPI-NOR in case of SPECIAL_BOOT
1117fc10f7eSHieu Huynhif [ $SPECIAL_BOOT == 1 ] && [ "$DEV_SEL" == 2 ]; then
112*e6a0291eSThang Q. Nguyen	echo "Flashing 2nd Host SPI NOR image with SECProv image is not allowed"
1137fc10f7eSHieu Huynh	exit
1147fc10f7eSHieu Huynhfi
1157fc10f7eSHieu Huynh
116b50fedbcSChanh Nguyen# Flash the firmware
117b50fedbcSChanh Nguyendo_flash
118b50fedbcSChanh Nguyen
1197fc10f7eSHieu Huynh# Assert SPECIAL_BOOT GPIO PIN
1207fc10f7eSHieu Huynhif [[ $SPECIAL_BOOT == 1 ]]; then
1217fc10f7eSHieu Huynh	gpioset $(gpiofind host0-special-boot)=1
122*e6a0291eSThang Q. Nguyen	# Set HOST BOOTCOUNT to 0 to prevent Host reboot
123*e6a0291eSThang Q. Nguyen	busctl set-property xyz.openbmc_project.State.Host0 \
124*e6a0291eSThang Q. Nguyen		/xyz/openbmc_project/state/host0 \
125*e6a0291eSThang Q. Nguyen		xyz.openbmc_project.Control.Boot.RebootAttempts RetryAttempts u 0
1267fc10f7eSHieu Huynhfi
1277fc10f7eSHieu Huynh
128*e6a0291eSThang Q. Nguyen# Switch the SPI bus to the primary SPI device
129b50fedbcSChanh Nguyenecho "Switch to the Primary Host SPI-NOR"
130b50fedbcSChanh Nguyengpioset $(gpiofind spi0-backup-sel)=1       # Primary SPI
131b50fedbcSChanh Nguyen
132b50fedbcSChanh Nguyen# Switch the host SPI bus to HOST."
133b50fedbcSChanh Nguyenecho "--- Switch the host SPI bus to HOST."
134b50fedbcSChanh Nguyenif ! gpioset $(gpiofind spi0-program-sel)=0; then
135*e6a0291eSThang Q. Nguyen	echo "ERROR: Switch the host SPI bus to HOST. Please check GPIO state"
136b50fedbcSChanh Nguyen	exit 1
137b50fedbcSChanh Nguyenfi
138b50fedbcSChanh Nguyen
1397fc10f7eSHieu Huynhif [ "$chassisstate" == 'On' ] || [ $SPECIAL_BOOT == 1 ];
140b50fedbcSChanh Nguyenthen
141b50fedbcSChanh Nguyen	sleep 5
142b50fedbcSChanh Nguyen	echo "Turn on the Host"
143b50fedbcSChanh Nguyen	obmcutil poweron
144b50fedbcSChanh Nguyenfi
1457fc10f7eSHieu Huynh
146*e6a0291eSThang Q. Nguyen# Detection SECProv of failure or success
1477fc10f7eSHieu Huynhif [[ $SPECIAL_BOOT == 1 ]]; then
148*e6a0291eSThang Q. Nguyen	# 30s time out in wait for FW_BOOT_OK
149*e6a0291eSThang Q. Nguyen	state=0
150*e6a0291eSThang Q. Nguyen	cnt=60
151*e6a0291eSThang Q. Nguyen	while [ $cnt -gt 0 ];
1527fc10f7eSHieu Huynh	do
153*e6a0291eSThang Q. Nguyen		# Monitor FW_BOOT_OK gpio
154*e6a0291eSThang Q. Nguyen		state=$(gpioget $(gpiofind s0-fw-boot-ok))
155*e6a0291eSThang Q. Nguyen		if [[ "$state" == "1" ]]; then
156*e6a0291eSThang Q. Nguyen			break
1577fc10f7eSHieu Huynh		fi
158*e6a0291eSThang Q. Nguyen		sleep 0.5
159*e6a0291eSThang Q. Nguyen		cnt=$((cnt - 1))
1607fc10f7eSHieu Huynh	done
161*e6a0291eSThang Q. Nguyen
162*e6a0291eSThang Q. Nguyen	echo "--- Turning the Chassis off"
163*e6a0291eSThang Q. Nguyen	obmcutil chassisoff
164*e6a0291eSThang Q. Nguyen
165*e6a0291eSThang Q. Nguyen	# Deassert SPECIAL_BOOT GPIO PIN
166*e6a0291eSThang Q. Nguyen	gpioset $(gpiofind host0-special-boot)=0
167*e6a0291eSThang Q. Nguyen
168*e6a0291eSThang Q. Nguyen	sleep 10
169*e6a0291eSThang Q. Nguyen	# Recover HOST BOOTCOUNT to default
170*e6a0291eSThang Q. Nguyen	busctl set-property xyz.openbmc_project.State.Host0 \
171*e6a0291eSThang Q. Nguyen		/xyz/openbmc_project/state/host0 \
172*e6a0291eSThang Q. Nguyen		xyz.openbmc_project.Control.Boot.RebootAttempts RetryAttempts u 3
1737fc10f7eSHieu Huynhfi
174