blob: ee878e2c6d14bc20eda638a026f5ebf12de7fe95 [file] [log] [blame]
Javier Almansa Sobrino412d3612020-05-22 17:53:12 +01001#!/bin/bash
2#
3# Copyright (c) 2020, Arm Limited. All rights reserved.
4#
5# SPDX-License-Identifier: BSD-3-Clause
6#
7
8set -e
9
10# Enable job control to have background processes run in their own process
11# group. That way, we can kill a background process group in one go.
12set -m
13
14ci_root="$(readlink -f "$(dirname "$0")/..")"
15source "$ci_root/utils.sh"
16
17artefacts="${artefacts-$workspace/artefacts}"
18
19run_root="$workspace/run"
20pid_dir="$workspace/pids"
21
22mkdir -p "$pid_dir"
23mkdir -p "$run_root"
24
25archive="$artefacts"
Javier Almansa Sobrinof98dbd82020-09-30 19:29:27 +010026bootargs_file="bootargs_file"
Javier Almansa Sobrino412d3612020-05-22 17:53:12 +010027
28gen_fpga_params() {
29 local fpga_param_file="fpga_env.sh"
30
31 echo "Generating parameters for FPGA $fpga..."
32 echo
33
34 echo "baudrate=$uart_baudrate" > $fpga_param_file
35 echo "fpga=$fpga" >> $fpga_param_file
36 echo "fpga_bitfile=$fpga_bitfile" >> $fpga_param_file
Javier Almansa Sobrino412d3612020-05-22 17:53:12 +010037 echo "project_name=$project_name" >> $fpga_param_file
38 echo "port=$uart_port" >> $fpga_param_file
39 echo "uart=$uart_descriptor" >> $fpga_param_file
40
Javier Almansa Sobrinof98dbd82020-09-30 19:29:27 +010041 if [ -n "$bl33_img" ]; then
42 echo "bl33_img=$bl33_img" >> $fpga_param_file
43 echo "bl33_addr=$bl33_addr" >> $fpga_param_file
44 fi
45
46 if [ -n "$initrd_img" ]; then
47 echo "initrd_img=$initrd_img" >> $fpga_param_file
48 echo "initrd_addr=$initrd_addr" >> $fpga_param_file
49 fi
50
51 if [ -n "$bootargs" ]; then
52 echo "CMD:$bootargs" > $bootargs_file
53 archive_file "$bootargs_file"
54 echo "cmdline_file=$bootargs_file" >> $fpga_param_file
55 echo "cmdline_addr=$bootargs_addr" >> $fpga_param_file
56 fi
57
Javier Almansa Sobrino412d3612020-05-22 17:53:12 +010058 archive_file "$fpga_param_file"
59}
60
61kill_and_reap() {
62 local gid
63 # Kill an active process. Ignore errors
64 [ "$1" ] || return 0
65 kill -0 "$1" &>/dev/null || return 0
66
67 # Kill the children
68 kill -- "-$1" &>/dev/null || true
69 # Kill the group
70 { gid="$(awk '{print $5}' < /proc/$1/stat)";} 2>/dev/null || return
71 kill -SIGKILL -- "-$gid" &>/dev/null || true
72
73 wait "$gid" &>/dev/null || true
74}
75
76# Perform clean up and ignore errors
77cleanup() {
78 local pid
79
80 # Test success. Kill all background processes so far and wait for them
81 pushd "$pid_dir"
82 set +e
83 while read pid; do
84 pid="$(cat $pid)"
85 kill_and_reap "$pid"
86 done < <(find -name '*.pid')
87 popd
88}
89
90# Launch a program. Have its PID saved in a file with given name with .pid
91# suffix. When the program exits, create a file with .success suffix, or one
92# with .fail if it fails. This function blocks, so the caller must '&' this if
93# they want to continue. Call must wait for $pid_dir/$name.pid to be created
94# should it want to read it.
95launch() {
96 local pid
97
98 "$@" &
99 pid="$!"
100 echo "$pid" > "$pid_dir/${name:?}.pid"
101 if wait "$pid"; then
102 touch "$pid_dir/$name.success"
103 else
104 touch "$pid_dir/$name.fail"
105 fi
106}
107
108# Cleanup actions
109trap cleanup SIGINT SIGHUP SIGTERM EXIT
110
111# Source variables required for run
112source "$artefacts/env"
113
114echo
115echo "RUNNING: $TEST_CONFIG"
116echo
117
118# Accept BIN_MODE from environment, or default to release. If bin_mode is set
119# and non-empty (intended to be set from command line), that takes precedence.
120pkg_bin_mode="${BIN_MODE:-release}"
121bin_mode="${bin_mode:-$pkg_bin_mode}"
122
123artefacts_wd="$artefacts/$bin_mode"
124
125# Change directory so that all binaries can be accessed relative to where they
126# lie
127run_cwd="$artefacts/$bin_mode"
128cd "$run_cwd"
129
130# Source environment for run
131if [ -f "run/env" ]; then
132 source "run/env"
133fi
134
135# Whether to display primary UART progress live on the console
136primary_live="${primary_live-$PRIMARY_LIVE}"
137
138# Assume 0 is the primary UART to track
139primary_uart="${primary_uart:-0}"
140
141# Assume 1 UARTs by default
142num_uarts="${num_uarts:-1}"
143
144# Generate the environment configuration file for the FPGA host.
145for u in $(seq 0 $(( $num_uarts - 1 )) | tac); do
146 descriptor="run/uart$u/descriptor"
147 if [ -f "$descriptor" ]; then
148 uart_descriptor="$(cat "$descriptor")"
149 else
150 echo "Error: No descriptor specified for UART$u"
151 exit 1
152 fi
153
154 baudrate="run/uart$u/baudrate"
155 if [ -f "$baudrate" ]; then
156 uart_baudrate="$(cat "$baudrate")"
157 else
158 echo "Error: No baudrate specified for UART$u"
159 exit 1
160 fi
161
162 port="run/uart$u/port"
163 if [ -f "$port" ]; then
164 uart_port="$(cat "$port")"
165 else
166 echo "Error: No port specified for UART$u"
167 exit 1
168 fi
169
170 fpga="$fpga_cluster" gen_fpga_params
171done
172
173if [ -z "$fpga_user" ]; then
174 echo "FPGA user not configured!"
175 exit 1
176fi
177if [ -z "$fpga_host" ]; then
178 echo "FPGA host not configured!"
179 exit 1
180fi
181remote_user="$fpga_user"
182remote_host="$fpga_host"
183
184echo
185echo "Copying artefacts to $remote_host as user $remote_user"
186echo
187
188# Copy the image to the remote host.
Javier Almansa Sobrinof98dbd82020-09-30 19:29:27 +0100189if [ -n "$bl33_img" ]; then
190 scp "$artefacts_wd/$bl33_img" "$remote_user@$remote_host:." > /dev/null
191fi
192
193if [ -n "$initrd_img" ]; then
194 scp "$artefacts_wd/$initrd_img" "$remote_user@$remote_host:." > /dev/null
195fi
196
197if [ -n "$bootargs" ]; then
198 scp "$artefacts_wd/$bootargs_file" "$remote_user@$remote_host:." > /dev/null
199fi
200scp "$artefacts_wd/bl31.axf" "$remote_user@$remote_host:." > /dev/null
Javier Almansa Sobrino412d3612020-05-22 17:53:12 +0100201
202# Copy the env and run scripts to the remote host.
203scp "$artefacts_wd/fpga_env.sh" "$remote_user@$remote_host:." > /dev/null
204scp "$ci_root/script/$fpga_run_script" "$remote_user@$remote_host:." > /dev/null
205
206echo "FPGA configuration options:"
207echo
Javier Almansa Sobrinof98dbd82020-09-30 19:29:27 +0100208while read conf_option; do
209 echo -e "\t$conf_option"
210done <$artefacts/fpga_env.sh
211if [ -n "$bootargs" ]; then
212echo -e "\tKernel bootargs: $bootargs"
213fi
Javier Almansa Sobrino412d3612020-05-22 17:53:12 +0100214
215# For an automated run, export a known variable so that we can identify stale
216# processes spawned by Trusted Firmware CI by inspecting its environment.
217export TRUSTED_FIRMWARE_CI="1"
218
219echo
220echo "Executing on $remote_host as user $remote_user"
221echo
222
223# Run the FPGA from the remote host.
224name="fpga_run" launch ssh "$remote_user@$remote_host" "bash ./$fpga_run_script" > \
225 /dev/null 2>&1 &
226
227# Wait enough time for the UART to show up on the FPGA host so the connection
228# can be stablished.
Javier Almansa Sobrinof98dbd82020-09-30 19:29:27 +0100229sleep 65
Javier Almansa Sobrino412d3612020-05-22 17:53:12 +0100230
231# If it's a test run, skip all the hoops and start a telnet connection to the FPGA.
232if upon "$test_run"; then
233 telnet "$remote_host" "$(cat "run/uart$primary_uart/port")"
234 exit 0
235fi
236
237# Launch expect scripts for all UARTs
238for u in $(seq 0 $(( $num_uarts - 1 )) | tac); do
239 script="run/uart$u/expect"
240 if [ -f "$script" ]; then
241 script="$(cat "$script")"
242 else
243 script=
244 fi
245
246 # Primary UART must have a script
247 if [ -z "$script" ]; then
248 if [ "$u" = "$primary_uart" ]; then
249 die "No primary UART script!"
250 else
251 echo "Ignoring UART$u (no expect script provided)."
252 continue
253 fi
254 fi
255
256 uart_descriptor="$(cat "run/uart$u/descriptor")"
257
258 timeout="run/uart$u/timeout"
259 uart_port="$(cat "run/uart$u/port")"
260
261 if [ -f "$timeout" ]; then
262 timeout="$(cat "$timeout")"
263 else
264 timeout=
265 fi
266 timeout="${timeout-600}"
267
268 full_log="$run_root/uart${u}_full.txt"
269
270 if [ "$u" = "$primary_uart" ]; then
271 star="*"
272 uart_name="primary_uart"
273 else
274 star=" "
275 uart_name="uart$u"
276 fi
277
278 # Launch expect after exporting required variables
279 (
280 if [ -f "run/uart$u/env" ]; then
281 set -a
282 source "run/uart$u/env"
283 set +a
284 fi
285
286 if [ "$u" = "$primary_uart" ] && upon "$primary_live"; then
287 uart_port="$uart_port" remote_host="$remote_host" timeout="$timeout" \
288 name="$uart_name" launch expect -f "$ci_root/expect/$script" | \
289 tee "$full_log"
290 echo
291 else
292 uart_port="$uart_port" remote_host="$remote_host" timeout="$timeout" \
293 name="$uart_name" launch expect -f "$ci_root/expect/$script" \
294 &>"$full_log"
295 fi
296
297 ) &
298
299 echo "Tracking UART$u$star ($uart_descriptor) with $script and timeout $timeout."
300done
301echo
302
303result=0
304
305set +e
306
307# Wait for all the children. Note that the wait below is *not* a timed wait.
308wait -n
309
310pushd "$pid_dir"
311# Wait for fpga_run to finish on the remote server.
312while :; do
313 if [ "$(wc -l < <(ls -l fpga_run.* 2> /dev/null))" -eq 2 ]; then
314 break
315 else
316 sleep 1
317 fi
318done
319
320# Check if there is any failure.
321while :; do
322 # Exit failure if we've any failures
323 if [ "$(wc -l < <(find -name '*.fail'))" -ne 0 ]; then
324 result=1
325 break
326 fi
327
328 # We're done if the primary UART exits success
329 if [ -f "$pid_dir/primary_uart.success" ]; then
330 break
331 fi
332done
333
Javier Almansa Sobrinof98dbd82020-09-30 19:29:27 +0100334ssh "$remote_user@$remote_host" "rm ./$fpga_run_script"
335
Javier Almansa Sobrino412d3612020-05-22 17:53:12 +0100336cleanup
337
338if [ "$result" -eq 0 ]; then
339 echo "Test success!"
340else
341 echo "Test failed!"
342fi
343
344if upon "$jenkins_run"; then
345 echo
346 echo "Artefacts location: $BUILD_URL."
347 echo
348fi
349
350if upon "$jenkins_run" && upon "$artefacts_receiver" && [ -d "$workspace/run" ]; then
351 source "$CI_ROOT/script/send_artefacts.sh" "run"
352fi
353
354exit "$result"
355# vim: set tw=80 sw=8 noet: