forked from Confusingboat/flash-it
-
Notifications
You must be signed in to change notification settings - Fork 0
/
flash-it.sh
288 lines (240 loc) · 9.35 KB
/
flash-it.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
#!/bin/bash
# Must be run as root
[[ $EUID > 0 ]] && echo "Error: must run as root/su" && exit 1
MEGACLI_URL="https://docs.broadcom.com/docs-and-downloads/raid-controllers/raid-controllers-common-files/8-07-14_MegaCLI.zip"
LSIUTIL_URL="https://github.com/confusingboat/meta-xa-stm/raw/master/recipes-support/lsiutil/files/lsiutil-1.72.tar.gz"
LSIREC_REPO_URL="https://github.com/confusingboat/lsirec"
FIRMWARE_BIOS_URL="https://docs.broadcom.com/docs-and-downloads/host-bus-adapters/host-bus-adapters-common-files/sas_sata_6g_p20/9211-8i_Package_P20_IR_IT_FW_BIOS_for_MSDOS_Windows.zip"
UEFI_URL="https://docs.broadcom.com/docs-and-downloads/host-bus-adapters/host-bus-adapters-common-files/sas_sata_6g_p20/UEFI_BSD_P20.zip"
MEGACLI_FILE_NAME="megacli.zip"
LSIUTIL_FILE_NAME="lsiutil.tar.gz"
FIRMWARE_PACKAGE_FILE_NAME="firmware.zip"
UEFI_PACKAGE_FILE_NAME="uefi.zip"
BACKUP_ROOT_DIR="/tmp"
ADAPTER_PATTERN="H310|H200|M1015"
ADAPTER_INDEX="0"
#SBR_CFG_MODIFIED_FILE_PATH="H310MM_mod.cfg"
FIRMWARE_UNPACK_DIR="/tmp/lsi_firmware"
UEFI_UNPACK_DIR="/tmp/lsi_uefi"
FIRMWARE_FILE_NAME="2118it.bin"
BIOS_FILE_NAME="mptsas2.rom"
UEFI_FILE_NAME="x64sas2.rom"
FIRMWARE_FILE_PATH="$(find ${FIRMWARE_UNPACK_DIR} -name ${FIRMWARE_FILE_NAME})"
BIOS_FILE_PATH="$(find ${FIRMWARE_UNPACK_DIR} -name ${BIOS_FILE_NAME})"
UEFI_FILE_PATH="$(find ${UEFI_UNPACK_DIR} -name ${UEFI_FILE_NAME} | grep Signed)"
function wait_for_ioc {
local c=0
echo
echo -n "Waiting for IOC to become ready..."
while ! lsirec/lsirec ${LSIREC_ADDR} info | grep -E "IOC is (OPERATIONAL|READY)"
do
(( c > 180 )) && echo "timed out" && echo && echo "Operation incomplete, exiting early. Please check the state of the device." && exit 1
((c++))
echo -n "."
sleep 1
done
}
function wait_for_mpt {
local c=0
echo
echo -n "Waiting for MPT..."
while ! lsiutil/lsiutil -e -p1 -a 0 | grep -E "LSI.+SAS2[0-9]{3}"
do
(( c > 180 )) && echo "timed out" && echo "Operation incomplete, exiting early. Please check the state of the device." && exit 1
((c++))
echo -n "."
sleep 1
done
}
function reset_device {
wait_for_ioc
echo "Resetting device..."
echo
lsirec/lsirec ${LSIREC_ADDR} reset
lsirec/lsirec ${LSIREC_ADDR} rescan
echo
}
# Install necessary packages
apt update
apt install git-core build-essential python3 pciutils p7zip-full sysfsutils unzip -y
# Download and extract firmware/BIOS (maybe)
if [ ! -f "${FIRMWARE_FILE_PATH}" ] || [ ! -f "${BIOS_FILE_PATH}" ]; then
if [ ! -f "${FIRMWARE_PACKAGE_FILE_NAME}" ]; then
wget ${FIRMWARE_BIOS_URL} -O "${FIRMWARE_PACKAGE_FILE_NAME}"
fi
rm -rf "${FIRMWARE_UNPACK_DIR}"
unzip "${FIRMWARE_PACKAGE_FILE_NAME}" -d "${FIRMWARE_UNPACK_DIR}"
FIRMWARE_FILE_PATH="$(find ${FIRMWARE_UNPACK_DIR} -name ${FIRMWARE_FILE_NAME})"
BIOS_FILE_PATH="$(find ${FIRMWARE_UNPACK_DIR} -name ${BIOS_FILE_NAME})"
fi
[ ! -f "${FIRMWARE_FILE_PATH}" ] && echo "Error: could not find or acquire firmware file at '${FIRMWARE_FILE_PATH}'. No changes have been made." && exit 1
[ ! -f "${BIOS_FILE_PATH}" ] && echo "Error: could not find or acquire BIOS file at '${BIOS_FILE_PATH}'. No changes have been made." && exit 1
# Download and extract UEFI (maybe)
if [ ! -f "${UEFI_FILE_PATH}" ]; then
if [ ! -f "${UEFI_PACKAGE_FILE_NAME}" ]; then
wget ${UEFI_URL} -O "${UEFI_PACKAGE_FILE_NAME}"
fi
rm -rf "${UEFI_UNPACK_DIR}"
unzip "${UEFI_PACKAGE_FILE_NAME}" -d "${UEFI_UNPACK_DIR}"
UEFI_FILE_PATH="$(find ${UEFI_UNPACK_DIR} -name ${UEFI_FILE_NAME} | grep Signed)"
fi
[ ! -f "${UEFI_FILE_PATH}" ] && echo "Error: could not find or acquire UEFI file at '${UEFI_FILE_PATH}'. No changes have been made." && exit 1
# Build megacli
if [ ! -f "${MEGACLI_FILE_NAME}" ]; then
wget ${MEGACLI_URL} -O "${MEGACLI_FILE_NAME}"
unzip "${MEGACLI_FILE_NAME}"
7z x Linux/MegaCli-8.07.14-1.noarch.rpm
7z x MegaCli-8.07.14-1.noarch.cpio
chmod 755 opt/MegaRAID/MegaCli/MegaCli64
fi
# Display SAS address and dump to file
opt/MegaRAID/MegaCli/MegaCli64 -AdpAllInfo -a${ADAPTER_INDEX} | grep SAS\ Address
BACKUP_SAS_ADDRESS_FILE="$(find ${BACKUP_ROOT_DIR} -name sas_address.txt)"
SAS_ADDRESS="$(opt/MegaRAID/MegaCli/MegaCli64 -AdpAllInfo -a${ADAPTER_INDEX} | grep -E 'SAS Address[^:]*:\W*(\w+)' | cut -d':' -f2 | cut -d' ' -f2)"
if [ ${#SAS_ADDRESS} -ne 16 ]; then
echo "Could not retrieve SAS address from MegaCli, attempting to load from existing backup file."
[ ! -f "${BACKUP_SAS_ADDRESS_FILE}" ] && echo "Error: unable to locate SAS address backup file. No changes have been made." && exit 1
SAS_ADDRESS=`cat ${BACKUP_SAS_ADDRESS_FILE}`
fi
[ ${#SAS_ADDRESS} -ne 16 ] && echo "Unable to acquire SAS address. No changes have been made." && exit 1
echo "Using SAS address '${SAS_ADDRESS}'"
ADAPTER_BACKUP_DIR="${BACKUP_ROOT_DIR}/${SAS_ADDRESS}"
mkdir -p "${ADAPTER_BACKUP_DIR}"
BACKUP_SAS_ADDRESS_FILE="${ADAPTER_BACKUP_DIR}/sas_address.txt"
BACKUP_PCI_ADDRESS_FILE="${ADAPTER_BACKUP_DIR}/pci_address.txt"
echo "${SAS_ADDRESS}" > ${BACKUP_SAS_ADDRESS_FILE}
# OPTIONAL IF YOU NEED DEB
# apt install alien -y
# alien Linux/MegaCli-8.07.14-1.noarch.rpm --scripts
# dpkg -i megacli_8.07.14-2_all.deb
#
# Build lsiutil
if [ ! -f "${LSIUTIL_FILE_NAME}" ]; then
wget ${LSIUTIL_URL} -O "${LSIUTIL_FILE_NAME}"
tar xzf "${LSIUTIL_FILE_NAME}"
make -C lsiutil -f Makefile_Linux
fi
# Build lsirec
git clone ${LSIREC_REPO_URL}
make -C lsirec
# Unload the HBA kernel module
rmmod megaraid_sas
# Enable huge pages for loading IT firmware from host to card
echo 16 > /proc/sys/vm/nr_hugepages
# Display full PCI information and dump PCI address to file
lspci -mnn | grep -E ${ADAPTER_PATTERN}
PCI_ADDRESS="$(lspci -mnn | grep -E ${ADAPTER_PATTERN} | grep -E '^\w+' | cut -d' ' -f1)"
if [ ${#PCI_ADDRESS} -ne 7 ]; then
echo "Could not retrieve PCI address from lspci, attempting to load from existing backup file."
[ ! -f "${BACKUP_PCI_ADDRESS_FILE}" ] && echo "Error: unable to locate PCI address backup file. No changes have been made." && exit 1
PCI_ADDRESS=`cat ${BACKUP_PCI_ADDRESS_FILE}`
fi
[ ${#PCI_ADDRESS} -ne 7 ] && echo "Error: could not validate PCI address. No changes have been made." && exit 1
echo "${PCI_ADDRESS}" > ${BACKUP_PCI_ADDRESS_FILE}
LSIREC_ADDR="0000:${PCI_ADDRESS}"
# Unbind and halt PCI device
echo "Unbinding and halting device..."
echo
lsirec/lsirec ${LSIREC_ADDR} unbind
lsirec/lsirec ${LSIREC_ADDR} halt
echo
# Read SBR and dump to file
echo "Backing up SBR..."
echo
BACKUP_SBR_FILE="${ADAPTER_BACKUP_DIR}/${SAS_ADDRESS}_backup.sbr"
lsirec/lsirec ${LSIREC_ADDR} readsbr "${BACKUP_SBR_FILE}"
echo
# Extract SBR config
echo "Extracting SBR config..."
echo
BACKUP_SBR_CFG_FILE="${ADAPTER_BACKUP_DIR}/${SAS_ADDRESS}_backup.cfg"
python3 lsirec/sbrtool.py parse "${BACKUP_SBR_FILE}" "${BACKUP_SBR_CFG_FILE}"
echo
# Modify SBR config
echo "Modifying SBR config..."
echo
SBR_CFG_MODIFIED_FILE_PATH="${ADAPTER_BACKUP_DIR}/${SAS_ADDRESS}_modified.cfg"
cp "${BACKUP_SBR_CFG_FILE}" "${SBR_CFG_MODIFIED_FILE_PATH}"
sed -i -r -e "s/^PCIPID = [0-9a-z]+$/PCIPID = 0x0072/I" "${SBR_CFG_MODIFIED_FILE_PATH}"
sed -i -r -e "s/^Interface = [0-9a-z]+$/Interface = 0x00/I" "${SBR_CFG_MODIFIED_FILE_PATH}"
echo
# Create modified SBR
echo "Building new SBR..."
echo
SBR_MODIFIED_FILE="${ADAPTER_BACKUP_DIR}/${SAS_ADDRESS}_modified.sbr"
[ ! -f "${SBR_CFG_MODIFIED_FILE_PATH}" ] && echo "Error: could not find modified SBR cfg file (e.g. H310MM_mod.cfg). No changes have been made." && exit 1
python3 lsirec/sbrtool.py build "${SBR_CFG_MODIFIED_FILE_PATH}" "${SBR_MODIFIED_FILE}"
echo
# Write modified SBR to device
echo "Writing modified SBR to device..."
echo
lsirec/lsirec ${LSIREC_ADDR} writesbr "${SBR_MODIFIED_FILE}"
echo
# Write IT firmware to running image on device and exit reset mode
echo "Writing IT firmware to running image on device..."
echo
lsirec/lsirec ${LSIREC_ADDR} hostboot "${FIRMWARE_FILE_PATH}"
echo
wait_for_ioc
# Rescan device
echo "Starting rescan..."
echo
lsirec/lsirec ${LSIREC_ADDR} rescan
echo
wait_for_mpt
# Use lsiutil to manually do the backup/flashing
# lsiutil/lsiutil -e
# select the device
# option 46 (backup)
# option 5
# arbitrary file name for backup
# option 33 (erase)
# option 3
# option 8
# return to main menu
# option 2 (flash)
# provide full path to 2118it.bin
# Use lsiutil CLI
# Backup existing flash
echo "Dumping existing flash..."
echo
BACKUP_FIRMWARE_FILE="${ADAPTER_BACKUP_DIR}/${SAS_ADDRESS}_backup.bin"
lsiutil/lsiutil -p1 -a 46,5,0 -f "${BACKUP_FIRMWARE_FILE}"
echo
[ ! -f "${BACKUP_FIRMWARE_FILE}" ] && \
echo "Error: flash backup not found. Stopping execution." && \
echo "Please check the state of your device and either:" && \
echo " - continue manually" && \
echo " or" && \
echo " - reflash SBR from ${BACKUP_SBR_FILE} then reboot and (optionally) start over." && \
echo && \
exit 1
wait_for_mpt
# Erase flash
echo "Erasing flash..."
echo
lsiutil/lsiutil -p1 -a 33,3,8,,0
echo
wait_for_mpt
# Flash IT firmware
echo "Flashing IT firmware..."
echo
lsiutil/lsiutil -p1 -a 2,yes,0 -f "${FIRMWARE_FILE_PATH}"
echo
reset_device
wait_for_mpt
# Set WWN/SAS Address
echo "Setting WWN/SAS address..."
echo
lsiutil/lsiutil -p1 -a 18,${SAS_ADDRESS},0
echo
reset_device
wait_for_mpt
# Flash BIOS/UEFI
echo "Flashing BIOS/UEFI boot ROMs..."
echo
lsiutil/lsiutil -p1 -a 4,yes,0 -f "${BIOS_FILE_PATH}",,"${UEFI_FILE_PATH}"
echo
echo
echo "All done. Copy /tmp/${SAS_ADDRESS}/ to persistent media and reboot."
echo