1#!/bin/bash
2# shellcheck disable=SC2046
3
4do_fru_upgrade() {
5	FRU_DEVICE="/sys/bus/i2c/devices/3-0050/eeprom"
6
7	if ! command -v ampere_fru_upgrade;
8	then
9		echo "Bypass fru update as no ampere_fru_upgrade available"
10		exit
11	fi
12	ampere_fru_upgrade -d $FRU_DEVICE -f "$IMAGE"
13
14	systemctl restart xyz.openbmc_project.FruDevice.service
15	systemctl restart phosphor-ipmi-host.service
16}
17
18do_smpmpro_upgrade() {
19	I2C_BUS_DEV="1"
20	EEPROM_ADDR="0x50"
21
22	if ! command -v ampere_eeprom_prog;
23	then
24		echo "Bypass SCP firmware update as no ampere_eeprom_prog available"
25		exit
26	fi
27	echo "SECPRO mode: $SECPRO"
28	# Turn off the Host if it is currently ON
29	chassisstate=$(obmcutil chassisstate | awk -F. '{print $NF}')
30	echo "Current Chassis State: $chassisstate"
31	if [ "$chassisstate" == 'On' ];
32	then
33		echo "Turning the Chassis off"
34		obmcutil chassisoff
35
36		# Wait 60s until Chassis is off
37		cnt=30
38		while [ "$cnt" -gt 0 ];
39		do
40			cnt=$((cnt - 1))
41			sleep 2
42			# Check if HOST was OFF
43			chassisstate_off=$(obmcutil chassisstate | awk -F. '{print $NF}')
44			if [ "$chassisstate_off" != 'On' ];
45			then
46				break
47			fi
48
49			if [ "$cnt" == "0" ];
50			then
51				echo "--- Error : Failed turning the Chassis off"
52				exit 1
53			fi
54		done
55	fi
56
57	if [[ $SECPRO == 1 ]]; then
58		gpioset $(gpiofind host0-special-boot)=1
59		gpioset $(gpiofind s1-special-boot)=1
60	fi
61
62	# Switch EEPROM control to BMC AST2500 I2C
63	gpioset $(gpiofind spi0-program-sel)=0
64
65	# 08 is BMC_GPIOB0_I2C_BACKUP_SEL
66	if [[ $DEV_SEL == 1 ]]; then
67		echo "Run update primary Boot EEPROM"
68		gpioset $(gpiofind i2c-backup-sel)=1       # Main EEPROM
69	elif [[ $DEV_SEL == 2 ]]; then
70		echo "Run update secondary Boot EEPROM"
71		gpioset $(gpiofind i2c-backup-sel)=0       # Second EEPROM
72	else
73		echo "Please choose Main (1) or Second EEPROM (2)"
74		exit 0
75	fi
76
77	# Write Firmware to EEPROM and read back for validation
78	ampere_eeprom_prog -b $I2C_BUS_DEV -s $EEPROM_ADDR -p -f "$IMAGE"
79
80	# Switch EEPROM control to Host
81	# 08 is BMC_GPIOB0_I2C_BACKUP_SEL
82	gpioset $(gpiofind i2c-backup-sel)=1
83	gpioset $(gpiofind spi0-program-sel)=1
84
85	# Deassert SECPRO GPIO PINs
86	if [[ $SECPRO == 1 ]]; then
87		echo "De-asserting special GPIO PINs"
88		gpioset $(gpiofind host0-special-boot)=0
89		gpioset $(gpiofind s1-special-boot)=0
90	fi
91
92	if [ "$chassisstate" == 'On' ];
93	then
94		sleep 5
95		echo "Turn on the Host"
96		obmcutil poweron
97	fi
98
99}
100
101
102if [ $# -eq 0 ]; then
103	echo "Usage:"
104	echo "      $(basename "$0") <Type> <Image file> <DEV_SEL> [SECPRO]"
105	echo "Where:"
106	echo "    <Type>: smpmpro or fru"
107	echo "            If Type is smpmpro, then DEV_SEL must is 1 (MAIN EEPROM), 2 (Failover)"
108	echo "    SECPRO: Optional, input '1' to enter & flash secpro mode. Default: 0"
109	exit 0
110fi
111
112TYPE=$1
113IMAGE=$2
114if [ -z "$3" ]
115then
116	DEV_SEL="1"    # by default, select Main image
117else
118	DEV_SEL=$3
119fi
120
121SECPRO=0
122if [ -n "$4" ]; then
123	if [[ "$4" == "1" ]]; then
124		SECPRO=1
125	fi
126fi
127
128MANIFEST="$(echo "$IMAGE" | cut -d'/' -f-4)/MANIFEST"
129if [ -f "$MANIFEST" ]; then
130	echo "MANIFEST: $MANIFEST"
131	if grep -qF "SECPRO" "$MANIFEST"; then
132		SECPRO=1
133	fi
134fi
135
136# Restrict to flash failover in case of SECPRO
137if [ $SECPRO == 1 ] && [ "$DEV_SEL" == 2 ]; then
138	echo "Not allow to flash the failover with SECPRO image"
139	exit
140fi
141
142if [[ $TYPE == "smpmpro" ]]; then
143	do_smpmpro_upgrade
144elif [[ $TYPE == "fru" ]]; then
145	do_fru_upgrade
146fi
147