-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathcapi-flash-script.sh
executable file
·390 lines (349 loc) · 12.3 KB
/
capi-flash-script.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
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
#!/bin/bash
#
# Copyright 2016, 2017 International Business Machines
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Usage: sudo capi-flash-script.sh <path-to-bin-file>
tool_version=2.1
# Changes History
# V2.0 code cleaning
# V2.1 add this header and tests oc_ or fw_ file names
# get capi-utils root
[ -h $0 ] && package_root=`ls -l "$0" |sed -e 's|.*-> ||'` || package_root="$0"
package_root=$(dirname $package_root)
source $package_root/capi-utils-common.sh
printf "\n"
printf "==================================\n"
printf "== CAPI1.0/2.0 programming tool ==\n"
printf "==================================\n"
echo capi-flash_script version is $tool_version
printf "Tool compiled on: "
ls -l $package_root/capi-flash|cut -d ' ' -f '6-8'
force=0
program=`basename "$0"`
card=-1
flash_address=""
flash_address2=""
flash_block_size=""
flash_type=""
reset_factory=0
# Print usage message helper function
function usage() {
echo "Usage: sudo ${program} [OPTIONS]"
echo " [-C <card>] card to flash."
echo " [-f] force execution without asking."
echo " warning: use with care e.g. for automation."
echo " [-r] Reset adapter to factory before writing to flash."
echo " [-V] Print program version (${version})"
echo " [-h] Print this help message."
echo " <path-to-bin-file>"
echo " <path-to-secondary-bin-file> (Only for SPIx8 device)"
echo
echo "Utility to flash/write bitstreams to CAPI FPGA cards."
echo "Please ensure that you are using the right bitstream data."
echo "Using non-functional bitstream data or aborting the process"
echo "can leave your card in a state where a hardware debugger is"
echo "required to make the card usable again."
echo
}
# Parse any options given on the command line
while getopts ":C:fVhr" opt; do
case ${opt} in
C)
card=$OPTARG
;;
f)
force=1
;;
r)
reset_factory=1
;;
V)
echo "${version}" >&2
exit 0
;;
h)
usage;
exit 0
;;
\?)
printf "${bold}ERROR:${normal} Invalid option: -${OPTARG}\n" >&2
exit 1
;;
:)
printf "${bold}ERROR:${normal} Option -$OPTARG requires an argument.\n" >&2
exit 1
;;
esac
done
shift $((OPTIND-1))
# now do something with $@
ulimit -c unlimited
# make sure an input argument is provided
if [ $# -eq 0 ]; then
printf "${bold}ERROR:${normal} Input argument missing\n"
usage
exit 1
fi
# make sure the input file exists
if [[ ! -e $1 ]]; then
printf "${bold}ERROR:${normal} $1 not found\n"
usage
exit 1
fi
# check if CAPI boards exists
capi_check=`lspci -d "1014":"477" | wc -l`
if [ $capi_check -eq 0 ]; then
printf "${bold}ERROR:${normal} No CAPI devices found\n"
exit 1
fi
LockDir=/var/cxl/capi-flash-script.lock
# make cxl dir if not present
mkdir -p `dirname $LockDir`
# mutual exclusion
if ! mkdir $LockDir 2>/dev/null; then
echo
printf "${bold}ERROR:${normal} Existing LOCK => Another instance of this script is maybe running\n"
DateLastBoot=`who -b | awk '{print $3 " " $4}'`
EpochLastBoot=`date -d "$DateLastBoot" +%s`
EpochLockDir=`stat --format=%Y $LockDir`
DateLockDir=`date --date @$EpochLockDir`
echo
echo "Last BOOT: `date --date @$EpochLastBoot` ($EpochLastBoot)"
echo "Last LOCK modification: $DateLockDir ($EpochLockDir)"
echo;echo "======================================================="
if [ $EpochLockDir -lt $EpochLastBoot ]; then
echo "$LockDir modified BEFORE last boot"
echo "LOCK is not supposed to still be here"
echo " ==> Deleting and recreating $LockDir"
rmdir $LockDir
mkdir $LockDir
else
echo "$LockDir modified AFTER last boot"
printf "${bold}ERROR:${normal} Another instance of this script is running\n"
echo "Exiting..."
exit 1
fi
fi
trap 'rm -rf "$LockDir"' EXIT
# get number of cards in system
n=`ls -d /sys/class/cxl/card* | awk -F"/sys/class/cxl/card" '{ print $2 }' | wc -w`
# touch history files if not present
for i in `seq 0 $(($n - 1))`; do
f="/var/cxl/card$i"
if [[ ! -f $f ]]; then
touch $f
fi
done
# print current date on server for comparison
printf "\n${bold}Current date:${normal}\n$(date)\n\n"
# print table header
printf "${bold}%-7s %-30s %-29s %-20s %s${normal}\n" "#" "Card" "Flashed" "by" "Last Image"
# print card information and flash history
for i in `seq 0 $((n - 1))`; do
p[$i]=$(cat /sys/class/cxl/card$i/device/subsystem_device)
# check for legacy device
if [[ ${p[$i]:0:6} == "0x04af" ]]; then
p[$i]=$(cat /sys/class/cxl/card$i/psl_revision | xargs printf "0x%.4X")
fi
f=$(cat /var/cxl/card$i)
while IFS='' read -r line || [[ -n $line ]]; do
if [[ ${line:0:6} == ${p[$i]:0:6} ]]; then
parse_info=($line)
board_vendor[$i]=${parse_info[1]}
fpga_type[$i]=${parse_info[2]}
flash_partition[$i]=${parse_info[3]}
flash_block[$i]=${parse_info[4]}
flash_interface[$i]=${parse_info[5]}
flash_secondary[$i]=${parse_info[6]}
printf "%-7s %-30s %-29s %-20s %s\n" "card$i" "${line:6:25}" "${f:0:29}" "${f:30:20}" "${f:51}"
fi
done < "$package_root/psl-devices"
done
printf "\n"
# card is set via parameter since it is positive
if (($card >= 0)); then
c=$((10#$card))
if (( "$c" >= "$n" )); then
printf "${bold}ERROR:${normal} Wrong card number ${card}\n"
exit 1
fi
else
# prompt card to flash to
while true; do
read -p "Which card do you want to flash? [0-$(($n - 1))] " c
if ! [[ $c =~ ^[0-9]+$ ]]; then
printf "${bold}ERROR:${normal} Invalid input\n"
else
c=$((10#$c))
if (( "$c" >= "$n" )); then
printf "${bold}ERROR:${normal} Wrong card number\n"
exit 1
else
break
fi
fi
done
fi
printf "\n"
# check file type
FILE_EXT=${1##*.}
if [[ ${fpga_type[$c]} == "Altera" ]]; then
if [[ $FILE_EXT != "rbf" ]]; then
printf "${bold}ERROR: ${normal}Wrong file extension: .rbf must be used for boards with Altera FPGA\n"
exit 0
fi
elif [[ ${fpga_type[$c]} == "Xilinx" ]]; then
if [[ $FILE_EXT != "bin" ]]; then
printf "${bold}ERROR: ${normal}Wrong file extension: .bin must be used for boards with Xilinx FPGA\n"
exit 0
fi
else
printf "${bold}ERROR: ${normal}Card not listed in psl-devices or previous card failed or is not responding\n"
exit 0
fi
# get flash address and block size
if [ -z "$flash_address" ]; then
flash_address=${flash_partition[$c]}
if [ $flash_address == "0x0000000" ] || [ $flash_address == "0x00000000" ]; then
if [[ $1 =~ "oc_" ]]
then
printf "===================================================================================\n"
echo "NOTE : You are in the process of programming an OPENCAPI image in FACTORY area!"
echo " A reboot or power cycle will be needed to re-enumerate the cards."
echo " Don't forget to sudo hange programming address to USER afterwards ( /lib/capi-utils/psl-devices)"
printf "===================================================================================\n"
else
printf "========================================================================\n"
printf "${bold}== WARNING :${normal} YOU ARE IN THE PROCESS OF PROGRAMMING IN FACTORY AREA! \n"
printf "== If this is not intentional, sudo change programming address in /lib/capi-utils/psl-devices\n"
printf "========================================================================\n"
fi
else
if [[ $1 =~ "oc_" ]]
then
printf "===================================================================================\n"
printf "WARNING: You are in the process of programming an OpenCAPI image in USER area!
Sudo change programming address in /lib/capi-utils/psl-devices if this is what you expect to do.
In order to achieve this, please change default CAPI2 User area to Factory area,
1) if card uses a single flash memory, just set single address to 0x00000000
2) If card uses 2 SPI flash memories, you need to change primary address to 0x00000000
while keeping the secondary flash selection bit active.
2a) For AD9H7 cards and further coming cards using large memory range,
secondary selection bit is the Most significant bit of the 32bit address.
eg : 0x0668 Alphadata_AD9H7 Xilinx 0x04000000 64 SPIx8 0x84000000 # DEFAULT USER AREA
0x0668 Alphadata_AD9H7 Xilinx 0x00000000 64 SPIx8 0x80000000 # FACTORY AREA
2b) for other SPI8 cards the secondary selection bit is the Most significant
bit of the secondary address.
eg : 0x060f Alphadata_AD9V3 Xilinx 0x01000000 64 SPIx8 0x03000000 # DEFAULT USER AREA
0x060f Alphadata_AD9V3 Xilinx 0x00000000 64 SPIx8 0x02000000 # FACTORY AREA\n"
printf "===================================================================================\n"
else
printf "${bold}INFO :${normal} You are programming in USER area\n"
fi
fi
fi
if [ -z "$flash_block_size" ]; then
flash_block_size=${flash_block[$c]}
fi
if [ -z "$flash_type" ]; then
flash_type=${flash_interface[$c]}
fi
if [ -z "$flash_type" ]; then
flash_type="BPIx16" #If it is not listed in psl-device file, use default value
fi
# Deal with the second argument
if [ $flash_type == "SPIx8" ]; then
if [ $# -eq 1 ]; then
printf "${bold}ERROR:${normal} Input argument missing. The selected device is SPIx8 and needs both primary and secondary bin files\n"
usage
exit 1
fi
#Check the second file
if [[ ! -e $2 ]]; then
printf "${bold}ERROR:${normal} $2 not found\n"
usage
exit 1
fi
#Assign secondary address
flash_address2=${flash_secondary[$c]}
if [ -z "$flash_address2" ]; then
printf "${bold}ERROR:${normal} The second address must be assigned in file psl-device\n"
exit 1
fi
fi
# card is set via parameter since it is positive
if (($force != 1)); then
# prompt to confirm
while true; do
printf "Will flash ${bold}card$c${normal} with: \n\t${bold}$1${normal}"
if [ $flash_type == "SPIx8" ]; then
printf "\nand \t${bold}$2${normal}\n"
fi
read -p "Do you want to continue? [y/n] " yn
case $yn in
[Yy]* ) break;;
[Nn]* ) exit;;
* ) printf "${bold}ERROR:${normal} Please answer with y or n\n";;
esac
done
else
printf "Continue to flash ${bold}$1${normal} ";
if [ $flash_type == "SPIx8" ]; then
printf "and ${bold}$2${normal} "
fi
printf "to ${bold}card$c${normal}\n"
fi
printf "\n"
# update flash history file
if [ $flash_type == "SPIx8" ]; then
printf "%-29s %-20s %s %s\n" "$(date)" "$(logname)" $1 $2 > /var/cxl/card$c
else
printf "%-29s %-20s %s\n" "$(date)" "$(logname)" $1 > /var/cxl/card$c
fi
# Check if lowlevel flash utility is existing and executable
if [ ! -x $package_root/capi-flash ]; then
printf "${bold}ERROR:${normal} Utility capi-flash not found!\n"
exit 1
fi
# Reset to card/flash registers to known state (factory)
if [ "$reset_factory" -eq 1 ]; then
reset_card $c factory "Preparing card for flashing"
fi
trap 'kill -TERM $PID; perst_factory $c' TERM INT
# flash card with corresponding binary
if [ $flash_type == "SPIx8" ]; then
# SPIx8 needs two file inputs (primary/secondary)
$package_root/capi-flash --type $flash_type --file $1 --file2 $2 --card $c --address $flash_address --address2 $flash_address2 --blocksize $flash_block_size &
else
$package_root/capi-flash --type $flash_type --file $1 --card $c --address $flash_address --blocksize $flash_block_size &
fi
PID=$!
wait $PID
trap - TERM INT
wait $PID
RC=$?
if [ $RC -eq 0 ]; then
# reset card only if Flashing was good
if [[ $1 =~ "oc_" ]]
then
# reset card only if Flashing was good
# reset to factory if programming an oc image
echo "Resetting card to factory area"
reset_card $c factory
else
# reset card only if Flashing was good
reset_card $c user
fi
fi