blob: eaa29a186d85792a8e526e54038d43a082ff21cb [file] [log] [blame]
Leonardo Sandoval9dfdd1b2020-08-06 17:08:11 -05001#!/usr/bin/env bash
Fathi Boudra422bf772019-12-02 11:10:16 +02002#
Boyan Karatotev27057342025-07-28 09:56:23 +01003# Copyright (c) 2019-2025 Arm Limited. All rights reserved.
Fathi Boudra422bf772019-12-02 11:10:16 +02004#
5# SPDX-License-Identifier: BSD-3-Clause
6#
7
8# Builds a package with Trusted Firwmare and other payload binaries. The package
9# is meant to be executed by run_package.sh
10
11set -e
12
13ci_root="$(readlink -f "$(dirname "$0")/..")"
14source "$ci_root/utils.sh"
15
16if [ ! -d "$workspace" ]; then
17 die "Directory $workspace doesn't exist"
18fi
19
20# Directory to where the source code e.g. for Trusted Firmware is checked out.
Zelalem219df412020-05-17 19:21:20 -050021export tf_root="${tf_root:-$workspace/trusted_firmware}"
22export tftf_root="${tftf_root:-$workspace/trusted_firmware_tf}"
Juan Pablo Conde3feb7f12023-10-21 13:14:47 -050023export tfut_root="${tfut_root:-$workspace/tfut}"
Zelalem219df412020-05-17 19:21:20 -050024cc_root="${cc_root:-$ccpathspec}"
Olivier Deprez0a9a3482019-12-16 14:10:31 +010025spm_root="${spm_root:-$workspace/spm}"
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +000026rmm_root="${rmm_root:-$workspace/tf-rmm}"
Zelalem219df412020-05-17 19:21:20 -050027
Fathi Boudra422bf772019-12-02 11:10:16 +020028# Refspecs
29tf_refspec="$TF_REFSPEC"
30tftf_refspec="$TFTF_REFSPEC"
Olivier Deprez0a9a3482019-12-16 14:10:31 +010031spm_refspec="$SPM_REFSPEC"
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +000032rmm_refspec="$RMM_REFSPEC"
Juan Pablo Conde3feb7f12023-10-21 13:14:47 -050033tfut_gerrit_refspec="$TFUT_GERRIT_REFSPEC"
Fathi Boudra422bf772019-12-02 11:10:16 +020034
35test_config="${TEST_CONFIG:?}"
36test_group="${TEST_GROUP:?}"
37build_configs="${BUILD_CONFIG:?}"
38run_config="${RUN_CONFIG:?}"
Zelalem219df412020-05-17 19:21:20 -050039cc_config="${CC_ENABLE:-}"
Fathi Boudra422bf772019-12-02 11:10:16 +020040
Boyan Karatotev97de8d82025-03-06 15:22:21 +000041export archive="$artefacts"
Fathi Boudra422bf772019-12-02 11:10:16 +020042build_log="$artefacts/build.log"
Boyan Karatotevde2cd442025-07-28 09:50:29 +010043
44fiptool_path() {
45 echo $tf_build_root/$(get_tf_opt PLAT)/${bin_mode}/tools/fiptool/fiptool
46}
47
48cert_create_path() {
49 echo $tf_build_root/$(get_tf_opt PLAT)/${bin_mode}/tools/cert_create/cert_create
50}
Fathi Boudra422bf772019-12-02 11:10:16 +020051
52# Validate $bin_mode
53case "$bin_mode" in
54 "" | debug | release)
55 ;;
56 *)
57 die "Invalid value for bin_mode: $bin_mode"
58 ;;
59esac
60
61# File to save any environem
62hook_env_file="$(mktempfile)"
63
Fathi Boudra422bf772019-12-02 11:10:16 +020064# Echo from a build wrapper. Print to descriptor 3 that's opened by the build
65# function.
66echo_w() {
67 echo $echo_flags "$@" >&3
68}
69
70# Print a separator to the log file. Intended to be used at the tail end of a pipe
71log_separator() {
72 {
73 echo
74 echo "----------"
75 } >> "$build_log"
76
77 tee -a "$build_log"
78
79 {
80 echo "----------"
81 echo
82 } >> "$build_log"
83}
84
85# Call function $1 if it's defined
86call_func() {
87 if type "${1:?}" &>/dev/null; then
88 echo
89 echo "> ${2:?}:$1()"
90 eval "$1"
91 echo "< $2:$1()"
92 fi
93}
94
Paul Sokolovskybe6510c2024-08-15 21:54:00 +030095# Retry a command a number of times if it fails. Intended for I/O commands
96# in a CI environment which may be flaky.
97function retry() {
98 for i in $(seq 1 3); do
99 if "$@"; then
100 return 0
101 fi
102 sleep $(( i * 5 ))
103 done
104 return 1
105}
106
Fathi Boudra422bf772019-12-02 11:10:16 +0200107# Call hook $1 in all chosen fragments if it's defined. Hooks are invoked from
108# within a subshell, so any variables set within a hook are lost. Should a
109# variable needs to be set from within a hook, the function 'set_hook_var'
110# should be used
111call_hook() {
112 local func="$1"
113 local config_fragment
114
115 [ -z "$func" ] && return 0
116
Paul Sokolovskye9962cd2021-12-17 18:39:40 +0300117 echo "=== Calling hooks: $1 ==="
118
Fathi Boudra422bf772019-12-02 11:10:16 +0200119 : >"$hook_env_file"
120
Nicola Mazzucato7fc5abd2024-02-23 21:32:48 +0000121 if [ "$run_config_candidates" ]; then
122 for config_fragment in $run_config_candidates; do
Fathi Boudra422bf772019-12-02 11:10:16 +0200123 (
124 source "$ci_root/run_config/$config_fragment"
125 call_func "$func" "$config_fragment"
126 )
127 done
128 fi
129
130 # Also source test config file
131 (
132 unset "$func"
133 source "$test_config_file"
134 call_func "$func" "$(basename $test_config_file)"
135 )
136
137 # Have any variables set take effect
138 source "$hook_env_file"
Paul Sokolovskye9962cd2021-12-17 18:39:40 +0300139
140 echo "=== End calling hooks: $1 ==="
Fathi Boudra422bf772019-12-02 11:10:16 +0200141}
142
143# Set a variable from within a hook
144set_hook_var() {
145 echo "export $1=\"${2?}\"" >> "$hook_env_file"
146}
147
148# Append to an array from within a hook
149append_hook_var() {
150 echo "export $1+=\"${2?}\"" >> "$hook_env_file"
151}
152
153# Have the main build script source a file
154source_later() {
155 echo "source ${1?}" >> "$hook_env_file"
156}
157
158# Setup TF build wrapper function by pointing to a script containing a function
159# that will be called with the TF build commands.
160setup_tf_build_wrapper() {
161 source_later "$ci_root/script/${wrapper?}_wrapper.sh"
162 set_hook_var "tf_build_wrapper" "${wrapper}_wrapper"
163 echo "Setup $wrapper build wrapper."
164}
165
166# Collect .bin files for archiving
167collect_build_artefacts() {
168 if [ ! -d "${from:?}" ]; then
169 return
170 fi
171
Manish V Badarkhe84c3a482025-04-16 08:15:38 +0100172 if ! find "$from" \( -name "*.bin" -o -name '*.elf' -o -name '*.dtb' -o -name '*.axf' -o -name '*.stm32' -o -name '*.img' \) -exec cp -t "${to:?}" '{}' +; then
Fathi Boudra422bf772019-12-02 11:10:16 +0200173 echo "You probably are running local CI on local repositories."
174 echo "Did you set 'dont_clean' but forgot to run 'distclean'?"
175 die
176 fi
177}
178
Manish Pandey1e7be852020-11-09 16:04:48 +0000179# Collect SPM/hafnium artefacts with "secure_" appended to the files
180# generated for SPM(secure hafnium).
181collect_spm_artefacts() {
Madhukar Pappireddyc683cf62021-11-01 14:38:32 -0500182 if [ -d "${non_secure_from:?}" ]; then
183 find "$non_secure_from" \( -name "*.bin" -o -name '*.elf' \) -exec cp -t "${to:?}" '{}' +
Manish Pandey1e7be852020-11-09 16:04:48 +0000184 fi
185
Madhukar Pappireddyc683cf62021-11-01 14:38:32 -0500186 if [ -d "${secure_from:?}" ]; then
187 for f in $(find "$secure_from" \( -name "*.bin" -o -name '*.elf' \)); do cp -- "$f" "${to:?}"/secure_$(basename $f); done
188 fi
Manish Pandey1e7be852020-11-09 16:04:48 +0000189}
190
Juan Pablo Conde3feb7f12023-10-21 13:14:47 -0500191collect_tfut_artefacts() {
192 if [ ! -d "${from:?}" ]; then
193 return
194 fi
195
196 pushd "$tfut_root/build"
197 artefact_list=$(python3 "$ci_root/script/get_ut_test_list.py")
198 for artefact in $artefact_list; do
199 cp -t "${to:?}" "$from/$artefact"
200 done
201 echo "$artefact_list" | tr ' ' '\n' > "${to:?}/tfut_artefacts.txt"
202 popd
203}
204
Javier Almansa Sobrino412d3612020-05-22 17:53:12 +0100205# Map the UART ID used for expect with the UART descriptor and port
206# used by the FPGA automation tools.
207map_uart() {
208 local port="${port:?}"
209 local descriptor="${descriptor:?}"
210 local baudrate="${baudrate:?}"
211 local run_root="${archive:?}/run"
212
213 local uart_dir="$run_root/uart${uart:?}"
214 mkdir -p "$uart_dir"
215
216 echo "$port" > "$uart_dir/port"
217 echo "$descriptor" > "$uart_dir/descriptor"
218 echo "$baudrate" > "$uart_dir/baudrate"
219
220 echo "UART${uart} mapped to port ${port} with descriptor ${descriptor} and baudrate ${baudrate}"
221}
222
Fathi Boudra422bf772019-12-02 11:10:16 +0200223# Arrange environment varibles to be set when expect scripts are launched
224set_expect_variable() {
225 local var="${1:?}"
226 local val="${2?}"
227
228 local run_root="${archive:?}/run"
229 local uart_dir="$run_root/uart${uart:?}"
230 mkdir -p "$uart_dir"
231
232 env_file="$uart_dir/env" quote="1" emit_env "$var" "$val"
233 echo "UART$uart: env has $@"
234}
235
236# Place the binary package a pointer to expect script, and its parameters
237track_expect() {
238 local file="${file:?}"
239 local timeout="${timeout-600}"
240 local run_root="${archive:?}/run"
241
242 local uart_dir="$run_root/uart${uart:?}"
243 mkdir -p "$uart_dir"
244
245 echo "$file" > "$uart_dir/expect"
246 echo "$timeout" > "$uart_dir/timeout"
Paul Sokolovskybfa8bab2023-01-25 19:34:51 +0700247 if [ -n "$lava_timeout" ]; then
248 set_run_env "lava_timeout" "$lava_timeout"
249 fi
Fathi Boudra422bf772019-12-02 11:10:16 +0200250
Paul Sokolovskybfa8bab2023-01-25 19:34:51 +0700251 echo "UART$uart to be tracked with $file; timeout ${timeout}s; lava_timeout ${lava_timeout:-N/A}s"
Fathi Boudra422bf772019-12-02 11:10:16 +0200252
Chris Kayfab6edc2022-11-17 19:18:32 +0000253 if [ ! -z "${port}" ]; then
254 echo "${port}" > "$uart_dir/port"
255 fi
256
Fathi Boudra422bf772019-12-02 11:10:16 +0200257 # The run script assumes UART0 to be primary. If we're asked to set any
258 # other UART to be primary, set a run environment variable to signal
259 # that to the run script
260 if upon "$set_primary"; then
261 echo "Primary UART set to UART$uart."
262 set_run_env "primary_uart" "$uart"
263 fi
Madhukar Pappireddy1e953722021-11-08 15:23:02 -0600264
265 # UART used by payload(such as tftf, Linux) may not be the same as the
266 # primary UART. Set a run environment variable to track the payload
267 # UART which is tracked to check if the test has finished sucessfully.
268 if upon "$set_payload_uart"; then
269 echo "Payload uses UART$uart."
270 set_run_env "payload_uart" "$uart"
271 fi
Fathi Boudra422bf772019-12-02 11:10:16 +0200272}
273
274# Extract a FIP in $1 using fiptool
275extract_fip() {
276 local fip="$1"
277
278 if is_url "$1"; then
279 url="$1" fetch_file
280 fip="$(basename "$1")"
281 fi
282
Boyan Karatotevde2cd442025-07-28 09:50:29 +0100283 fiptool=$(fiptool_path)
Fathi Boudra422bf772019-12-02 11:10:16 +0200284 "$fiptool" unpack "$fip"
285 echo "Extracted FIP: $fip"
286}
287
288# Report build failure by printing a the tail end of build log. Archive the
289# build log for later inspection
290fail_build() {
291 local log_path
292
293 if upon "$jenkins_run"; then
294 log_path="$BUILD_URL/artifact/artefacts/build.log"
295 else
296 log_path="$build_log"
297 fi
298
299 echo
Leonardo Sandovalae97eda2020-11-12 10:07:03 -0600300 echo "Build failed! Full build log below:"
Fathi Boudra422bf772019-12-02 11:10:16 +0200301 echo "[...]"
302 echo
Leonardo Sandovalae97eda2020-11-12 10:07:03 -0600303 cat "$build_log"
Fathi Boudra422bf772019-12-02 11:10:16 +0200304 echo
305 echo "See $log_path for full output"
306 echo
307 cp -t "$archive" "$build_log"
308 exit 1;
309}
310
311# Build a FIP with supplied arguments
312build_fip() {
313 (
314 echo "Building FIP with arguments: $@"
315 local tf_env="$workspace/tf.env"
316
317 if [ -f "$tf_env" ]; then
318 set -a
319 source "$tf_env"
320 set +a
321 fi
322
Slava Andrianov192ee172025-06-11 15:40:43 -0500323 if [ "$(get_tf_opt MEASURED_BOOT)" = 1 ]; then
324 # These are needed for accurate hash verification
325 local build_args_path="${workspace}/fip_build_args"
326 echo $@ > $build_args_path
327 archive_file $build_args_path
328 fi
329
Boyan Karatotev99e12312025-05-02 15:00:24 +0100330 make -C "$tf_root" $make_j_opts $(cat "$tf_config_file") DEBUG="$DEBUG" BUILD_BASE=$tf_build_root V=1 "$@" \
Fathi Boudra422bf772019-12-02 11:10:16 +0200331 ${fip_targets:-fip} &>>"$build_log" || fail_build
332 )
333}
334
Sandrine Bailleux189fdb32023-10-20 13:41:22 +0200335# Build any extra rule from TF-A makefile with supplied arguments.
336#
337# This is useful in case you need to build something else than firmware binaries
338# or the FIP.
339build_tf_extra() {
340 (
341 tf_extra_rules=${tf_extra_rules:?}
342 echo "Building extra TF rule(s): $tf_extra_rules"
343 echo " Arguments: $@"
344
345 local tf_env="$workspace/tf.env"
346
347 if [ -f "$tf_env" ]; then
348 set -a
349 source "$tf_env"
350 set +a
351 fi
352
Boyan Karatotev99e12312025-05-02 15:00:24 +0100353 make -C "$tf_root" $make_j_opts $(cat "$tf_config_file") DEBUG="$DEBUG" V=1 BUILD_BASE=$tf_build_root "$@" \
Sandrine Bailleux189fdb32023-10-20 13:41:22 +0200354 ${tf_extra_rules} &>>"$build_log" || fail_build
355 )
356}
357
Fathi Boudra422bf772019-12-02 11:10:16 +0200358fip_update() {
Boyan Karatotevde2cd442025-07-28 09:50:29 +0100359 fiptool=$(fiptool_path)
Fathi Boudra422bf772019-12-02 11:10:16 +0200360 # Before the update process, check if the given image is supported by
361 # the fiptool. It's assumed that both fiptool and cert_create move in
Chris Kay197b1022023-08-16 21:31:41 +0100362 # tandem, and therefore, if one has support, the other has it too.
363 if ! ("$fiptool" update 2>&1 || true) | grep -qe "\s\+--${bin_name:?}"; then
Fathi Boudra422bf772019-12-02 11:10:16 +0200364 return 1
365 fi
366
367 if not_upon "$(get_tf_opt TRUSTED_BOARD_BOOT)"; then
368 echo "Updating FIP image: $bin_name"
369 # Update HW config. Without TBBR, it's only a matter of using
370 # the update sub-command of fiptool
371 "$fiptool" update "--$bin_name" "${src:-}" \
372 "$archive/fip.bin"
373 else
374 echo "Updating FIP image (TBBR): $bin_name"
375 # With TBBR, we need to unpack, re-create certificates, and then
376 # recreate the FIP.
377 local fip_dir="$(mktempdir)"
378 local bin common_args stem
379 local rot_key="$(get_tf_opt ROT_KEY)"
380
381 rot_key="${rot_key:?}"
382 if ! is_abs "$rot_key"; then
383 rot_key="$tf_root/$rot_key"
384 fi
385
386 # Arguments only for cert_create
387 local cert_args="-n"
388 cert_args+=" --tfw-nvctr ${nvctr:-31}"
389 cert_args+=" --ntfw-nvctr ${nvctr:-223}"
390 cert_args+=" --key-alg ${KEY_ALG:-rsa}"
391 cert_args+=" --rot-key $rot_key"
392
393 local dyn_config_opts=(
Zelalem1af7a7b2020-08-04 17:34:32 -0500394 "fw-config"
Fathi Boudra422bf772019-12-02 11:10:16 +0200395 "hw-config"
396 "tb-fw-config"
397 "nt-fw-config"
398 "soc-fw-config"
399 "tos-fw-config"
400 )
401
402 # Binaries without key certificates
403 declare -A has_no_key_cert
404 for bin in "tb-fw" "${dyn_config_opts[@]}"; do
405 has_no_key_cert["$bin"]="1"
406 done
407
408 # Binaries without certificates
409 declare -A has_no_cert
410 for bin in "hw-config" "${dyn_config_opts[@]}"; do
411 has_no_cert["$bin"]="1"
412 done
413
414 pushd "$fip_dir"
415
416 # Unpack FIP
417 "$fiptool" unpack "$archive/fip.bin" &>>"$build_log"
418
419 # Remove all existing certificates
420 rm -f *-cert.bin
421
422 # Copy the binary to be updated
423 cp -f "$src" "${bin_name}.bin"
424
425 # FIP unpack dumps binaries with the same name as the option
426 # used to pack it; likewise for certificates. Reverse-engineer
427 # the command line from the binary output.
428 common_args="--trusted-key-cert trusted_key.crt"
429 for bin in *.bin; do
430 stem="${bin%%.bin}"
431 common_args+=" --$stem $bin"
432 if not_upon "${has_no_cert[$stem]}"; then
433 common_args+=" --$stem-cert $stem.crt"
434 fi
435 if not_upon "${has_no_key_cert[$stem]}"; then
436 common_args+=" --$stem-key-cert $stem-key.crt"
437 fi
438 done
439
440 # Create certificates
Boyan Karatotevde2cd442025-07-28 09:50:29 +0100441 cert_create=$(cert_create_path)
Fathi Boudra422bf772019-12-02 11:10:16 +0200442 "$cert_create" $cert_args $common_args &>>"$build_log"
443
444 # Recreate and archive FIP
445 "$fiptool" create $common_args "fip.bin" &>>"$build_log"
446 archive_file "fip.bin"
447
448 popd
449 fi
450}
451
452# Update hw-config in FIP, and remove the original DTB afterwards.
453update_fip_hw_config() {
454 # The DTB needs to be loaded by the model (and not updated in the FIP)
Madhukar Pappireddy9062ebf2021-03-02 17:07:06 -0600455 # in configs:
456 # 1. Where BL2 isn't present
457 # 2. Where we boot to Linux directly as BL33
Fathi Boudra422bf772019-12-02 11:10:16 +0200458 case "1" in
459 "$(get_tf_opt RESET_TO_BL31)" | \
Madhukar Pappireddy9062ebf2021-03-02 17:07:06 -0600460 "$(get_tf_opt ARM_LINUX_KERNEL_AS_BL33)" | \
Fathi Boudra422bf772019-12-02 11:10:16 +0200461 "$(get_tf_opt RESET_TO_SP_MIN)" | \
Maksims Svecovs7a0da522023-03-06 16:28:27 +0000462 "$(get_tf_opt RESET_TO_BL2)")
Fathi Boudra422bf772019-12-02 11:10:16 +0200463 return 0;;
464 esac
465
466 if bin_name="hw-config" src="$archive/dtb.bin" fip_update; then
467 # Remove the DTB so that model won't load it
468 rm -f "$archive/dtb.bin"
469 fi
470}
471
Fathi Boudra422bf772019-12-02 11:10:16 +0200472get_tftf_opt() {
473 (
474 name="${1:?}"
475 if config_valid "$tftf_config_file"; then
476 source "$tftf_config_file"
477 echo "${!name}"
478 fi
479 )
480}
481
482get_tf_opt() {
483 (
484 name="${1:?}"
485 if config_valid "$tf_config_file"; then
486 source "$tf_config_file"
487 echo "${!name}"
488 fi
489 )
490}
491
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +0000492get_rmm_opt() {
493 (
494 name="${1:?}"
Manish V Badarkhea3505272025-04-17 14:20:42 +0100495 default="$2"
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +0000496 if config_valid "$rmm_config_file"; then
497 source "$rmm_config_file"
Manish V Badarkhea3505272025-04-17 14:20:42 +0100498 # If !name is not defined, go with the default
499 # value (if defined)
500 if [ -z "${!name}" ]; then
501 echo "$default"
502 else
503 echo "${!name}"
504 fi
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +0000505 fi
506 )
507}
508
Fathi Boudra422bf772019-12-02 11:10:16 +0200509build_tf() {
510 (
511 env_file="$workspace/tf.env"
512 config_file="${tf_build_config:-$tf_config_file}"
513
514 # Build fiptool and all targets by default
Harrison Mutai32de9d02023-06-12 14:23:37 +0100515 build_targets="${tf_build_targets:-fiptool all}"
Fathi Boudra422bf772019-12-02 11:10:16 +0200516
517 source "$config_file"
518
519 # If it is a TBBR build, extract the MBED TLS library from archive
Manish V Badarkhe8f125012021-12-21 05:47:52 +0000520 if [ "$(get_tf_opt TRUSTED_BOARD_BOOT)" = 1 ] ||
Manish V Badarkhef43e3f52022-06-21 20:37:25 +0100521 [ "$(get_tf_opt MEASURED_BOOT)" = 1 ] ||
522 [ "$(get_tf_opt DRTM_SUPPORT)" = 1 ]; then
Fathi Boudra422bf772019-12-02 11:10:16 +0200523 mbedtls_dir="$workspace/mbedtls"
524 if [ ! -d "$mbedtls_dir" ]; then
525 mbedtls_ar="$workspace/mbedtls.tar.gz"
526
527 url="$mbedtls_archive" saveas="$mbedtls_ar" fetch_file
528 mkdir "$mbedtls_dir"
Leonardo Sandovalec9e16c2020-09-09 14:32:40 -0500529 extract_tarball $mbedtls_ar $mbedtls_dir --strip-components=1
Fathi Boudra422bf772019-12-02 11:10:16 +0200530 fi
531
532 emit_env "MBEDTLS_DIR" "$mbedtls_dir"
533 fi
Jimmy Brisson0d5e12c2023-05-16 14:51:51 -0500534 if [ "$(get_tf_opt PLATFORM_TEST)" = "tfm-testsuite" ] &&
535 not_upon "${TF_M_TESTS_PATH}"; then
536 emit_env "TF_M_TESTS_PATH" "$WORKSPACE/tf-m-tests"
537 fi
538 if [ "$(get_tf_opt PLATFORM_TEST)" = "tfm-testsuite" ] &&
539 not_upon "${TF_M_EXTRAS_PATH}"; then
540 emit_env "TF_M_EXTRAS_PATH" "$WORKSPACE/tf-m-extras"
541 fi
David Vincze82db6932024-02-21 12:05:50 +0100542 if [ "$(get_tf_opt DICE_PROTECTION_ENVIRONMENT)" = 1 ] &&
543 not_upon "${QCBOR_DIR}"; then
544 emit_env "QCBOR_DIR" "$WORKSPACE/qcbor"
545 fi
Slava Andrianov192ee172025-06-11 15:40:43 -0500546
547 # Hash verification only occurs if there is a sufficient amount of
548 # information in the event log, which is as long as EVENT_LOG_LEVEL
549 # is set to at least 20 or if it is a debug build
550 if [[ ("$(get_tf_opt MEASURED_BOOT)" -eq 1) &&
551 (($bin_mode == "debug") || ("$(get_tf_opt EVENT_LOG_LEVEL)" -ge 20)) ]]; then
552 # This variable is later exported to the expect scripts so
553 # the hashes in the TF-A event log can be verified
554 set_run_env "verify_hashes" "1"
555 fi
Fathi Boudra422bf772019-12-02 11:10:16 +0200556 if [ -f "$env_file" ]; then
557 set -a
558 source "$env_file"
559 set +a
560 fi
561
Harrison Mutai013f6332022-02-16 16:06:33 +0000562 if is_arm_jenkins_env || upon "$local_ci"; then
563 path_list=(
564 "$llvm_dir/bin"
565 )
566 extend_path "PATH" "path_list"
567 fi
568
Boyan Karatotev97de8d82025-03-06 15:22:21 +0000569 pushd "$tf_root"
Fathi Boudra422bf772019-12-02 11:10:16 +0200570
571 # Always distclean when running on Jenkins. Skip distclean when running
572 # locally and explicitly requested.
573 if upon "$jenkins_run" || not_upon "$dont_clean"; then
Boyan Karatotev97de8d82025-03-06 15:22:21 +0000574 make distclean BUILD_BASE=$tf_build_root &>>"$build_log" || fail_build
Fathi Boudra422bf772019-12-02 11:10:16 +0200575 fi
576
577 # Log build command line. It is left unfolded on purpose to assist
578 # copying to clipboard.
579 cat <<EOF | log_separator >/dev/null
580
581Build command line:
Boyan Karatotev97de8d82025-03-06 15:22:21 +0000582 $tf_build_wrapper make $make_j_opts $(cat "$config_file" | tr '\n' ' ') DEBUG=$DEBUG V=1 BUILD_BASE=$tf_build_root $build_targets
Fathi Boudra422bf772019-12-02 11:10:16 +0200583
Paul Sokolovsky7f71b072023-10-16 12:59:09 +0300584CC version:
585$(${CC-${CROSS_COMPILE}gcc} -v 2>&1)
Fathi Boudra422bf772019-12-02 11:10:16 +0200586EOF
587
Javier Almansa Sobrinoe8363182020-11-10 16:40:53 +0000588 if not_upon "$local_ci"; then
589 connect_debugger=0
590 fi
591
Fathi Boudra422bf772019-12-02 11:10:16 +0200592 # Build TF. Since build output is being directed to the build log, have
593 # descriptor 3 point to the current terminal for build wrappers to vent.
Harrison Mutai6361dbe2023-02-16 14:12:40 +0000594 $tf_build_wrapper poetry run make $make_j_opts $(cat "$config_file") \
Boyan Karatotev97de8d82025-03-06 15:22:21 +0000595 DEBUG="$DEBUG" V=1 BUILD_BASE="$tf_build_root" SPIN_ON_BL1_EXIT="$connect_debugger" \
Fathi Boudra422bf772019-12-02 11:10:16 +0200596 $build_targets 3>&1 &>>"$build_log" || fail_build
Harrison Mutai32de9d02023-06-12 14:23:37 +0100597
Harrison Mutai6dafb5f2023-07-18 15:21:48 +0100598 if [ "$build_targets" != "doc" ]; then
Chris Kay9ab2d952025-05-29 13:46:24 +0100599 (poetry run memory --root "$tf_build_root" symbols 2>&1 || true) | tee -a "${build_log}"
600
601 for map in $(find "${tf_build_root}" -name '*.map'); do
602 (poetry run memory --root "${tf_build_root}" summary "${map}" 2>&1 || true) | tee -a "${build_log}"
603 done
Harrison Mutai6dafb5f2023-07-18 15:21:48 +0100604 fi
Boyan Karatotev97de8d82025-03-06 15:22:21 +0000605 popd
Fathi Boudra422bf772019-12-02 11:10:16 +0200606 )
607}
608
609build_tftf() {
610 (
611 config_file="${tftf_build_config:-$tftf_config_file}"
612
613 # Build tftf target by default
614 build_targets="${tftf_build_targets:-all}"
615
616 source "$config_file"
617
618 cd "$tftf_root"
619
620 # Always distclean when running on Jenkins. Skip distclean when running
621 # locally and explicitly requested.
622 if upon "$jenkins_run" || not_upon "$dont_clean"; then
Boyan Karatotev97de8d82025-03-06 15:22:21 +0000623 make distclean BUILD_BASE="$tftf_build_root" &>>"$build_log" || fail_build
Fathi Boudra422bf772019-12-02 11:10:16 +0200624 fi
625
626 # TFTF build system cannot reliably deal with -j option, so we avoid
627 # using that.
628
629 # Log build command line
630 cat <<EOF | log_separator >/dev/null
631
632Build command line:
Boyan Karatotev97de8d82025-03-06 15:22:21 +0000633 make $make_j_opts $(cat "$config_file" | tr '\n' ' ') DEBUG=$DEBUG V=1 BUILD_BASE="$tftf_build_root" $build_targets
Fathi Boudra422bf772019-12-02 11:10:16 +0200634
635EOF
636
Boyan Karatotev97de8d82025-03-06 15:22:21 +0000637 make $make_j_opts $(cat "$config_file") DEBUG="$DEBUG" V=1 BUILD_BASE="$tftf_build_root" \
Fathi Boudra422bf772019-12-02 11:10:16 +0200638 $build_targets &>>"$build_log" || fail_build
639 )
640}
641
Zelalem219df412020-05-17 19:21:20 -0500642build_cc() {
643# Building code coverage plugin
644 ARM_DIR=/arm
645 pvlibversion=$(/arm/devsys-tools/abs/detag "SysGen:PVModelLib:$model_version::trunk")
646 PVLIB_HOME=$warehouse/SysGen/PVModelLib/$model_version/${pvlibversion}/external
647 if [ -n "$(find "$ARM_DIR" -maxdepth 0 -type d -empty 2>/dev/null)" ]; then
648 echo "Error: Arm warehouse not mounted. Please mount the Arm warehouse to your /arm local folder"
649 exit -1
650 fi # Error if arm warehouse not found
651 cd "$ccpathspec/scripts/tools/code_coverage/fastmodel_baremetal/bmcov"
652
653 make -C model-plugin PVLIB_HOME=$PVLIB_HOME &>>"$build_log"
654}
655
Olivier Deprez0a9a3482019-12-16 14:10:31 +0100656build_spm() {
657 (
658 env_file="$workspace/spm.env"
659 config_file="${spm_build_config:-$spm_config_file}"
660
661 source "$config_file"
662
663 if [ -f "$env_file" ]; then
664 set -a
665 source "$env_file"
666 set +a
667 fi
668
669 cd "$spm_root"
670
671 # Always clean when running on Jenkins. Skip clean when running
672 # locally and explicitly requested.
673 if upon "$jenkins_run" || not_upon "$dont_clean"; then
674 # make clean fails on a fresh repo where the project has not
675 # yet been built. Hence only clean if out/reference directory
676 # already exists.
677 if [ -d "out/reference" ]; then
678 make clean &>>"$build_log" || fail_build
679 fi
680 fi
681
682 # Log build command line. It is left unfolded on purpose to assist
683 # copying to clipboard.
684 cat <<EOF | log_separator >/dev/null
685
686Build command line:
Boyan Karatotev27057342025-07-28 09:56:23 +0100687 make $make_j_opts OUT=$spm_build_root $(cat "$config_file" | tr '\n' ' ')
Olivier Deprez0a9a3482019-12-16 14:10:31 +0100688
689EOF
690
691 # Build SPM. Since build output is being directed to the build log, have
692 # descriptor 3 point to the current terminal for build wrappers to vent.
Boyan Karatotev27057342025-07-28 09:56:23 +0100693 make $make_j_opts OUT=$spm_build_root $(cat "$config_file") 3>&1 &>>"$build_log" \
Olivier Deprez0a9a3482019-12-16 14:10:31 +0100694 || fail_build
695 )
696}
Zelalem219df412020-05-17 19:21:20 -0500697
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +0000698build_rmm() {
699 (
700 env_file="$workspace/rmm.env"
701 config_file="${rmm_build_config:-$rmm_config_file}"
702
703 # Build fiptool and all targets by default
Manish V Badarkhe8cbbabf2025-08-20 11:27:12 +0100704 export CROSS_COMPILE="aarch64-none-elf-"
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +0000705
706 source "$config_file"
707
708 if [ -f "$env_file" ]; then
709 set -a
710 source "$env_file"
711 set +a
712 fi
713
714 cd "$rmm_root"
715
716 if [ -f "$rmm_root/requirements.txt" ]; then
717 export PATH="$HOME/.local/bin:$PATH"
718 python3 -m pip install --upgrade pip
719 python3 -m pip install -r "$rmm_root/requirements.txt"
720 fi
721
722 # Always distclean when running on Jenkins. Skip distclean when running
723 # locally and explicitly requested.
724 if upon "$jenkins_run" || not_upon "$dont_clean"; then
725 # Remove 'rmm\build' folder
726 echo "Removing $rmm_build_root..."
727 rm -rf $rmm_build_root
728 fi
729
Manish V Badarkhea3505272025-04-17 14:20:42 +0100730 if not_upon "$local_ci"; then
731 connect_debugger=0
732 fi
733
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +0000734 # Log build command line. It is left unfolded on purpose to assist
735 # copying to clipboard.
736 cat <<EOF | log_separator >/dev/null
737
738Build command line:
Manish V Badarkhea3505272025-04-17 14:20:42 +0100739 cmake -DRMM_CONFIG=${plat}_defcfg "$cmake_gen" -S $rmm_root -B $rmm_build_root -DRMM_TOOLCHAIN=$rmm_toolchain -DRMM_FPU_USE_AT_REL2=$rmm_fpu_use_at_rel2 -DATTEST_EL3_TOKEN_SIGN=$rmm_attest_el3_token_sign -DRMM_V1_1=$rmm_v1_1 ${extra_options}
740 cmake --build $rmm_build_root --config $cmake_build_type $make_j_opts -v ${extra_targets+-- $extra_targets}
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +0000741
Manish V Badarkhea3505272025-04-17 14:20:42 +0100742EOF
743 cmake \
744 -DRMM_CONFIG=${plat}_defcfg $cmake_gen \
745 -S $rmm_root -B $rmm_build_root \
746 -DRMM_TOOLCHAIN=$rmm_toolchain \
747 -DRMM_FPU_USE_AT_REL2=$rmm_fpu_use_at_rel2 \
748 -DATTEST_EL3_TOKEN_SIGN=$rmm_attest_el3_token_sign \
749 -DRMM_V1_1=$rmm_v1_1 \
750 ${extra_options}
751 cmake --build $rmm_build_root --config $cmake_build_type $make_j_opts -v ${extra_targets+-- $extra_targets} 3>&1 &>>"$build_log" || fail_build
752 )
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +0000753}
754
Juan Pablo Conde3feb7f12023-10-21 13:14:47 -0500755build_tfut() {
756 (
757 config_file="${tfut_build_config:-$tfut_config_file}"
758
759 # Build tfut target by default
760 build_targets="${tfut_build_targets:-all}"
761
762 source "$config_file"
763
764 mkdir -p "$tfut_root/build"
765 cd "$tfut_root/build"
766
767 # Always distclean when running on Jenkins. Skip distclean when running
768 # locally and explicitly requested.
769 if upon "$jenkins_run" || not_upon "$dont_clean"; then
770 #make clean &>>"$build_log" || fail_build
771 rm -Rf * || fail_build
772 fi
773
774 #Override build targets only if the run config did not set them.
775 if [ $build_targets == "all" ]; then
776 tests_line=$(cat "$config_file" | { grep "tests=" || :; })
777 if [ -z "$tests_line" ]; then
778 build_targets=$(echo "$tests_line" | awk -F= '{ print $NF }')
779 fi
780 fi
781
782 config=$(cat "$config_file" | grep -v "tests=")
783 cmake_config=$(echo "$config" | sed -e 's/^/\-D/')
784
785 # Check if cmake is installed
786 if ! command -v cmake &> /dev/null
787 then
788 echo "cmake could not be found"
789 exit 1
790 fi
791
792 # Log build command line
793 cat <<EOF | log_separator >/dev/null
794
795Build command line:
796 cmake $(echo "$cmake_config") -G"Unix Makefiles" --debug-output -DCMAKE_VERBOSE_MAKEFILE -DUNIT_TEST_PROJECT_PATH="$tf_root" ..
797 make $(echo "$config" | tr '\n' ' ') DEBUG=$DEBUG V=1 $build_targets
798
799EOF
800 cmake $(echo "$cmake_config") -G"Unix Makefiles" --debug-output \
801 -DCMAKE_VERBOSE_MAKEFILE=ON \
802 -DUNIT_TEST_PROJECT_PATH="$tf_root" \
803 .. &>> "$build_log" || fail_build
804 echo "Done with cmake" >> "$build_log"
805 make $(echo "$config") VERBOSE=1 \
806 $build_targets &>> "$build_log" || fail_build
807 )
808
809}
810
Fathi Boudra422bf772019-12-02 11:10:16 +0200811# Set metadata for the whole package so that it can be used by both Jenkins and
812# shell
813set_package_var() {
814 env_file="$artefacts/env" emit_env "$@"
815}
816
817set_tf_build_targets() {
818 echo "Set build target to '${targets:?}'"
819 set_hook_var "tf_build_targets" "$targets"
820}
821
822set_tftf_build_targets() {
823 echo "Set build target to '${targets:?}'"
824 set_hook_var "tftf_build_targets" "$targets"
825}
826
Olivier Deprez0a9a3482019-12-16 14:10:31 +0100827set_spm_build_targets() {
828 echo "Set build target to '${targets:?}'"
829 set_hook_var "spm_build_targets" "$targets"
830}
831
Juan Pablo Conde3feb7f12023-10-21 13:14:47 -0500832set_tfut_build_targets() {
833 echo "Set build target to '${targets:?}'"
834 set_hook_var "tfut_build_targets" "$targets"
835}
836
Daniel Boulbyb8d2a462022-03-07 13:55:25 +0000837set_spm_out_dir() {
838 echo "Set SPMC binary build to '${out_dir:?}'"
839 set_hook_var "spm_secure_out_dir" "$out_dir"
840}
Fathi Boudra422bf772019-12-02 11:10:16 +0200841# Look under $archive directory for known files such as blX images, kernel, DTB,
842# initrd etc. For each known file foo, if foo.bin exists, then set variable
843# foo_bin to the path of the file. Make the path relative to the workspace so as
844# to remove any @ characters, which Jenkins inserts for parallel runs. If the
845# file doesn't exist, unset its path.
846set_default_bin_paths() {
847 local image image_name image_path path
848 local archive="${archive:?}"
849 local set_vars
850 local var
851
852 pushd "$archive"
853
854 for file in *.bin; do
855 # Get a shell variable from the file's stem
856 var_name="${file%%.*}_bin"
857 var_name="$(echo "$var_name" | sed -r 's/[^[:alnum:]]/_/g')"
858
859 # Skip setting the variable if it's already
860 if [ "${!var_name}" ]; then
861 echo "Note: not setting $var_name; already set to ${!var_name}"
862 continue
863 else
864 set_vars+="$var_name "
865 fi
866
867 eval "$var_name=$file"
868 done
869
870 echo "Binary paths set for: "
871 {
872 for var in $set_vars; do
873 echo -n "\$$var "
874 done
875 } | fmt -80 | sed 's/^/ /'
876 echo
877
878 popd
879}
880
881gen_model_params() {
882 local model_param_file="$archive/model_params"
Javier Almansa Sobrinoe8363182020-11-10 16:40:53 +0000883 [ "$connect_debugger" ] && [ "$connect_debugger" -eq 1 ] && wait_debugger=1
Fathi Boudra422bf772019-12-02 11:10:16 +0200884
885 set_default_bin_paths
886 echo "Generating model parameter for $model..."
887 source "$ci_root/model/${model:?}.sh"
888 archive_file "$model_param_file"
889}
890
891set_model_path() {
892 set_run_env "model_path" "${1:?}"
893}
894
Zelalem1af7a7b2020-08-04 17:34:32 -0500895set_model_env() {
896 local var="${1:?}"
897 local val="${2?}"
898 local run_root="${archive:?}/run"
899
900 mkdir -p "$run_root"
901 echo "export $var=$val" >> "$run_root/model_env"
902}
Fathi Boudra422bf772019-12-02 11:10:16 +0200903set_run_env() {
904 local var="${1:?}"
905 local val="${2?}"
906 local run_root="${archive:?}/run"
907
908 mkdir -p "$run_root"
909 env_file="$run_root/env" quote="1" emit_env "$var" "$val"
910}
911
912show_head() {
913 # Display HEAD descripton
914 pushd "$1"
915 git show --quiet --no-color | sed 's/^/ > /g'
916 echo
917 popd
918}
919
920# Choose debug binaries to run; by default, release binaries are chosen to run
921use_debug_bins() {
922 local run_root="${archive:?}/run"
923
924 echo "Choosing debug binaries for execution"
925 set_package_var "BIN_MODE" "debug"
926}
927
928assert_can_git_clone() {
929 local name="${1:?}"
930 local dir="${!name}"
931
932 # If it doesn't exist, it can be cloned into
933 if [ ! -e "$dir" ]; then
934 return 0
935 fi
936
937 # If it's a directory, it must be a Git clone already
938 if [ -d "$dir" ] && [ -d "$dir/.git" ]; then
939 # No need to clone again
940 echo "Using existing git clone for $name: $dir"
941 return 1
942 fi
943
944 die "Path $dir exists but is not a git clone"
945}
946
947clone_repo() {
948 if ! is_url "${clone_url?}"; then
949 # For --depth to take effect on local paths, it needs to use the
950 # file:// scheme.
951 clone_url="file://$clone_url"
952 fi
953
954 git clone -q --depth 1 "$clone_url" "${where?}"
955 if [ "$refspec" ]; then
956 pushd "$where"
957 git fetch -q --depth 1 origin "$refspec"
958 git checkout -q FETCH_HEAD
959 popd
960 fi
961}
962
963build_unstable() {
964 echo "--BUILD UNSTABLE--" | tee -a "$build_log"
965}
966
967undo_patch_record() {
968 if [ ! -f "${patch_record:?}" ]; then
969 return
970 fi
971
972 # Undo patches in reverse
973 echo
974 for patch_name in $(tac "$patch_record"); do
975 echo "Undoing $patch_name..."
976 if ! git apply -R "$ci_root/patch/$patch_name"; then
977 if upon "$local_ci"; then
978 echo
979 echo "Your local directory may have been dirtied."
980 echo
981 fi
982 fail_build
983 fi
984 done
985
986 rm -f "$patch_record"
987}
988
989undo_local_patches() {
990 pushd "$tf_root"
991 patch_record="$tf_patch_record" undo_patch_record
992 popd
993
994 if [ -d "$tftf_root" ]; then
995 pushd "$tftf_root"
996 patch_record="$tftf_patch_record" undo_patch_record
997 popd
998 fi
999}
1000
1001undo_tftf_patches() {
1002 pushd "$tftf_root"
1003 patch_record="$tftf_patch_record" undo_patch_record
1004 popd
1005}
1006
1007undo_tf_patches() {
1008 pushd "$tf_root"
1009 patch_record="$tf_patch_record" undo_patch_record
1010 popd
1011}
1012
1013apply_patch() {
1014 # If skip_patches is set, the developer has applied required patches
1015 # manually. They probably want to keep them applied for debugging
1016 # purposes too. This means we don't have to apply/revert them as part of
1017 # build process.
1018 if upon "$skip_patches"; then
1019 echo "Skipped applying ${1:?}..."
1020 return 0
1021 else
1022 echo "Applying ${1:?}..."
1023 fi
1024
Sandrine Bailleux4cb8c222023-09-13 13:48:15 +02001025 if git apply --reverse --check < "$ci_root/patch/$1" 2> /dev/null; then
Jimmy Brissonf134e4c2023-03-22 13:20:20 -05001026 echo "Skipping already applied ${1:?}"
1027 return 0
1028 fi
1029
Fathi Boudra422bf772019-12-02 11:10:16 +02001030 if git apply < "$ci_root/patch/$1"; then
1031 echo "$1" >> "${patch_record:?}"
1032 else
1033 if upon "$local_ci"; then
1034 undo_local_patches
1035 fi
1036 fail_build
1037 fi
1038}
1039
Fathi Boudra422bf772019-12-02 11:10:16 +02001040apply_tf_patch() {
Boyan Karatotevfaf9a9d2025-07-28 09:52:05 +01001041 root="$tf_root"
1042 new_root="$archive/tfa_mirror"
1043
1044 # paralell builds are only used locally. Don't do for CI since this will
1045 # have a speed penalty. Also skip if this was already done as a single
1046 # job may apply many patches.
1047 if upon "$local_ci" && [[ ! -d $new_root ]]; then
1048 root=$new_root
1049 diff=$(mktempfile)
1050
1051 # get anything still uncommitted
1052 pushd $tf_root
1053 git diff HEAD > $diff
1054 popd
1055
1056 # git will hard link when cloning locally, no need for --depth=1
1057 git clone "$tf_root" $root --shallow-submodules
1058
1059 tf_root=$root # next apply_tf_patch will run in the same hook
1060 set_hook_var "tf_root" "$root" # for anyone outside the hook
1061
1062 # apply uncommited changes so they are picked up in the build
1063 pushd $tf_root
1064 git apply $diff &> /dev/null || true
1065 popd
1066
1067 fi
1068
1069 pushd "$root"
Fathi Boudra422bf772019-12-02 11:10:16 +02001070 patch_record="$tf_patch_record" apply_patch "$1"
1071 popd
1072}
1073
Fathi Boudra422bf772019-12-02 11:10:16 +02001074mkdir -p "$workspace"
1075mkdir -p "$archive"
1076set_package_var "TEST_CONFIG" "$test_config"
1077
1078{
1079echo
1080echo "CONFIGURATION: $test_group/$test_config"
1081echo
1082} |& log_separator
1083
1084tf_config="$(echo "$build_configs" | awk -F, '{print $1}')"
1085tftf_config="$(echo "$build_configs" | awk -F, '{print $2}')"
Chris Kay4f7846a2025-08-04 19:56:35 +01001086spm_config="$(echo "$build_configs" | awk -F, '{print $3}')"
1087rmm_config="$(echo "$build_configs" | awk -F, '{print $4}')"
Juan Pablo Conde3feb7f12023-10-21 13:14:47 -05001088tfut_config="$(echo "$build_configs" | awk -F, '{print $5}')"
Fathi Boudra422bf772019-12-02 11:10:16 +02001089
1090test_config_file="$ci_root/group/$test_group/$test_config"
1091
1092tf_config_file="$ci_root/tf_config/$tf_config"
1093tftf_config_file="$ci_root/tftf_config/$tftf_config"
Olivier Deprez0a9a3482019-12-16 14:10:31 +01001094spm_config_file="$ci_root/spm_config/$spm_config"
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +00001095rmm_config_file="$ci_root/rmm_config/$rmm_config"
Juan Pablo Conde3feb7f12023-10-21 13:14:47 -05001096tfut_config_file="$ci_root/tfut_config/$tfut_config"
Fathi Boudra422bf772019-12-02 11:10:16 +02001097
1098# File that keeps track of applied patches
1099tf_patch_record="$workspace/tf_patches"
1100tftf_patch_record="$workspace/tftf_patches"
1101
Juan Pablo Conde84bf39f2024-01-12 22:09:49 -06001102# Split run config into TF and TFUT components
1103run_config_tfa="$(echo "$run_config" | awk -F, '{print $1}')"
1104run_config_tfut="$(echo "$run_config" | awk -F, '{print $2}')"
1105
Fathi Boudra422bf772019-12-02 11:10:16 +02001106pushd "$workspace"
1107
1108if ! config_valid "$tf_config"; then
1109 tf_config=
1110else
1111 echo "Trusted Firmware config:"
1112 echo
1113 sort "$tf_config_file" | sed '/^\s*$/d;s/^/\t/'
1114 echo
1115fi
1116
1117if ! config_valid "$tftf_config"; then
1118 tftf_config=
1119else
1120 echo "Trusted Firmware TF config:"
1121 echo
1122 sort "$tftf_config_file" | sed '/^\s*$/d;s/^/\t/'
1123 echo
1124fi
1125
Olivier Deprez0a9a3482019-12-16 14:10:31 +01001126if ! config_valid "$spm_config"; then
1127 spm_config=
1128else
1129 echo "SPM config:"
1130 echo
1131 sort "$spm_config_file" | sed '/^\s*$/d;s/^/\t/'
Zelalem219df412020-05-17 19:21:20 -05001132 echo
1133fi
1134
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +00001135# File that keeps track of applied patches
1136rmm_patch_record="$workspace/rmm_patches"
1137
1138if ! config_valid "$rmm_config"; then
1139 rmm_config=
1140else
1141 echo "Trusted Firmware RMM config:"
1142 echo
1143 sort "$rmm_config_file" | sed '/^\s*$/d;s/^/\t/'
1144 echo
1145fi
1146
Juan Pablo Conde3feb7f12023-10-21 13:14:47 -05001147if ! config_valid "$tfut_config"; then
1148 tfut_config=
1149else
1150 echo "TFUT config:"
1151 echo
1152 sort "$tfut_config_file" | sed '/^\s*$/d;s/^/\t/'
1153 echo
1154fi
1155
Juan Pablo Conde84bf39f2024-01-12 22:09:49 -06001156if ! config_valid "$run_config_tfa"; then
1157 run_config_tfa=
Fathi Boudra422bf772019-12-02 11:10:16 +02001158fi
1159
Juan Pablo Conde3feb7f12023-10-21 13:14:47 -05001160if { [ "$tf_config" ] || [ "$tfut_config" ]; } && assert_can_git_clone "tf_root"; then
Fathi Boudra422bf772019-12-02 11:10:16 +02001161 # If the Trusted Firmware repository has already been checked out, use
1162 # that location. Otherwise, clone one ourselves.
1163 echo "Cloning Trusted Firmware..."
1164 clone_url="${TF_CHECKOUT_LOC:-$tf_src_repo_url}" where="$tf_root" \
1165 refspec="$TF_REFSPEC" clone_repo &>>"$build_log"
1166 show_head "$tf_root"
1167fi
1168
1169if [ "$tftf_config" ] && assert_can_git_clone "tftf_root"; then
1170 # If the Trusted Firmware TF repository has already been checked out,
1171 # use that location. Otherwise, clone one ourselves.
1172 echo "Cloning Trusted Firmware TF..."
1173 clone_url="${TFTF_CHECKOUT_LOC:-$tftf_src_repo_url}" where="$tftf_root" \
1174 refspec="$TFTF_REFSPEC" clone_repo &>>"$build_log"
1175 show_head "$tftf_root"
1176fi
1177
Zelalem219df412020-05-17 19:21:20 -05001178if [ -n "$cc_config" ] ; then
1179 if [ "$cc_config" -eq 1 ] && assert_can_git_clone "cc_root"; then
1180 # Copy code coverage repository
1181 echo "Cloning Code Coverage..."
1182 git clone -q $cc_src_repo_url cc_plugin --depth 1 -b $cc_src_repo_tag > /dev/null
1183 show_head "$cc_root"
1184 fi
1185fi
1186
Daniel Boulby25385ab2023-12-14 14:36:25 +00001187if [ "$spm_config" ] ; then
1188 if assert_can_git_clone "spm_root"; then
1189 # If the SPM repository has already been checked out, use
1190 # that location. Otherwise, clone one ourselves.
1191 echo "Cloning SPM..."
1192 clone_url="${SPM_CHECKOUT_LOC:-$spm_src_repo_url}" \
1193 where="$spm_root" refspec="$SPM_REFSPEC" \
1194 clone_repo &>>"$build_log"
1195 fi
Olivier Deprez0a9a3482019-12-16 14:10:31 +01001196
1197 # Query git submodules
1198 pushd "$spm_root"
Daniel Boulby25385ab2023-12-14 14:36:25 +00001199 # Check if submodules need initialising
Paul Sokolovskyad274422024-09-01 10:27:56 +03001200
1201 # This handling is needed to reliably fetch submodules
1202 # in CI environment.
1203 for subm in $(git submodule status | awk '/^-/ {print $2}'); do
1204 for i in $(seq 1 7); do
1205 git submodule init $subm
1206 if git submodule update $subm; then
1207 break
1208 fi
1209 git submodule deinit --force $subm
1210 echo "Retrying $subm"
1211 sleep $((RANDOM % 10 + 5))
1212 done
1213 done
1214
1215 git submodule status
Olivier Deprez0a9a3482019-12-16 14:10:31 +01001216 popd
1217
1218 show_head "$spm_root"
1219fi
1220
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +00001221if [ "$rmm_config" ] && assert_can_git_clone "rmm_root"; then
Manish V Badarkhe41909452025-04-11 12:06:45 +01001222 # If the RMM repository has already been checked out,
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +00001223 # use that location. Otherwise, clone one ourselves.
1224 echo "Cloning TF-RMM..."
1225 clone_url="${RMM_CHECKOUT_LOC:-$rmm_src_repo_url}" where="$rmm_root" \
1226 refspec="$RMM_REFSPEC" clone_repo &>>"$build_log"
1227 show_head "$rmm_root"
1228fi
1229
Juan Pablo Conde3feb7f12023-10-21 13:14:47 -05001230if [ "$tfut_config" ] && assert_can_git_clone "tfut_root"; then
1231 # If the Trusted Firmware UT repository has already been checked out,
1232 # use that location. Otherwise, clone one ourselves.
1233 echo "Cloning Trusted Firmware UT..."
1234 clone_url="${TFUT_CHECKOUT_LOC:-$tfut_src_repo_url}" where="$tfut_root" \
1235 refspec="$TFUT_GERRIT_REFSPEC" clone_repo &>>"$build_log"
1236 show_head "$tfut_root"
1237fi
1238
Juan Pablo Conde84bf39f2024-01-12 22:09:49 -06001239if [ "$run_config_tfa" ]; then
1240 # Get candidates for TF-A run config
Nicola Mazzucato7fc5abd2024-02-23 21:32:48 +00001241 run_config_candidates="$("$ci_root/script/gen_run_config_candidates.py" \
Juan Pablo Conde84bf39f2024-01-12 22:09:49 -06001242 "$run_config_tfa")"
Nicola Mazzucato7fc5abd2024-02-23 21:32:48 +00001243 if [ -z "$run_config_candidates" ]; then
Fathi Boudra422bf772019-12-02 11:10:16 +02001244 die "No run config candidates!"
1245 else
1246 echo
1247 echo "Chosen fragments:"
1248 echo
Nicola Mazzucato7fc5abd2024-02-23 21:32:48 +00001249 echo "$run_config_candidates" | sed 's/^\|\n/\t/g'
Fathi Boudra422bf772019-12-02 11:10:16 +02001250 echo
Harrison Mutai4dfe1192024-07-03 12:35:38 +00001251
1252 if [ ! -n "$bin_mode" ]; then
1253 if echo $run_config_candidates | grep -wq "debug"; then
1254 bin_mode="debug"
1255 else
1256 bin_mode="release"
1257 fi
1258 fi
Fathi Boudra422bf772019-12-02 11:10:16 +02001259 fi
1260fi
1261
1262call_hook "test_setup"
1263echo
1264
1265if upon "$local_ci"; then
1266 # For local runs, since each config is tried in sequence, it's
1267 # advantageous to run jobs in parallel
1268 if [ "$make_j" ]; then
1269 make_j_opts="-j $make_j"
1270 else
1271 n_cores="$(getconf _NPROCESSORS_ONLN)" 2>/dev/null || true
1272 if [ "$n_cores" ]; then
1273 make_j_opts="-j $n_cores"
1274 fi
1275 fi
1276fi
1277
Harrison Mutai07043e92023-07-06 09:41:12 +01001278# Install python build dependencies
1279if is_arm_jenkins_env; then
1280 source "$ci_root/script/install_python_deps.sh"
1281fi
1282
Juan Pablo Conde3feb7f12023-10-21 13:14:47 -05001283# Install c-picker dependency
1284if config_valid "$tfut_config"; then
1285 echo "started building"
1286 python3 -m venv .venv
1287 source .venv/bin/activate
1288
1289 if ! python3 -m pip show c-picker &> /dev/null; then
1290 echo "Installing c-picker"
1291 pip install git+https://git.trustedfirmware.org/TS/trusted-services.git@topics/c-picker || {
1292 echo "c-picker was not installed!"
1293 exit 1
1294 }
1295 echo "c-picker was installed"
1296 else
1297 echo "c-picker is already installed"
1298 fi
1299fi
1300
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +00001301# Print CMake version
1302cmake_ver=$(echo `cmake --version | sed -n '1p'`)
1303echo "Using $cmake_ver"
1304
1305# Check for Ninja
1306if [ -x "$(command -v ninja)" ]; then
1307 # Print Ninja version
1308 ninja_ver=$(echo `ninja --version | sed -n '1p'`)
1309 echo "Using ninja $ninja_ver"
1310 export cmake_gen="-G Ninja"
1311else
1312 echo 'Ninja is not installed'
1313 export cmake_gen=""
1314fi
1315
1316undo_rmm_patches() {
1317 pushd "$rmm_root"
1318 patch_record="$rmm_patch_record" undo_patch_record
1319 popd
1320}
1321
Fathi Boudra422bf772019-12-02 11:10:16 +02001322modes="${bin_mode:-debug release}"
1323for mode in $modes; do
Paul Sokolovskye9962cd2021-12-17 18:39:40 +03001324 echo "===== Building package in mode: $mode ====="
Fathi Boudra422bf772019-12-02 11:10:16 +02001325 # Build with a temporary archive
1326 build_archive="$archive/$mode"
1327 mkdir "$build_archive"
1328
1329 if [ "$mode" = "debug" ]; then
Zelalem219df412020-05-17 19:21:20 -05001330 export bin_mode="debug"
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +00001331 cmake_build_type="Debug"
Fathi Boudra422bf772019-12-02 11:10:16 +02001332 DEBUG=1
1333 else
Zelalem219df412020-05-17 19:21:20 -05001334 export bin_mode="release"
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +00001335 cmake_build_type="Release"
Fathi Boudra422bf772019-12-02 11:10:16 +02001336 DEBUG=0
1337 fi
1338
1339 # Perform builds in a subshell so as not to pollute the current and
1340 # subsequent builds' environment
1341
Zelalem219df412020-05-17 19:21:20 -05001342 if config_valid "$cc_config"; then
1343 # Build code coverage plugin
1344 build_cc
1345 fi
1346
Fathi Boudra422bf772019-12-02 11:10:16 +02001347 # TFTF build
1348 if config_valid "$tftf_config"; then
1349 (
1350 echo "##########"
1351
Manish V Badarkhe3bd3fea2020-11-08 15:17:00 +00001352 plat_utils="$(get_tf_opt PLAT_UTILS)"
1353 if [ -z ${plat_utils} ]; then
1354 # Source platform-specific utilities.
1355 plat="$(get_tftf_opt PLAT)"
1356 plat_utils="$ci_root/${plat}_utils.sh"
1357 else
1358 # Source platform-specific utilities by
1359 # using plat_utils name.
1360 plat_utils="$ci_root/${plat_utils}.sh"
1361 fi
1362
Fathi Boudra422bf772019-12-02 11:10:16 +02001363 if [ -f "$plat_utils" ]; then
1364 source "$plat_utils"
1365 fi
1366
1367 archive="$build_archive"
Boyan Karatotev97de8d82025-03-06 15:22:21 +00001368 tftf_build_root="$archive/build/tftf"
1369 mkdir -p ${tftf_build_root}
Fathi Boudra422bf772019-12-02 11:10:16 +02001370
1371 echo "Building Trusted Firmware TF ($mode) ..." |& log_separator
1372
1373 # Call pre-build hook
1374 call_hook pre_tftf_build
1375
1376 build_tftf
1377
1378 from="$tftf_build_root" to="$archive" collect_build_artefacts
1379
1380 # Clear any local changes made by applied patches
1381 undo_tftf_patches
1382
1383 echo "##########"
1384 echo
1385 )
1386 fi
1387
Olivier Deprez0a9a3482019-12-16 14:10:31 +01001388 # SPM build
1389 if config_valid "$spm_config"; then
1390 (
1391 echo "##########"
1392
1393 # Get platform name from spm_config file
1394 plat="$(echo "$spm_config" | awk -F- '{print $1}')"
1395 plat_utils="$ci_root/${plat}_utils.sh"
1396 if [ -f "$plat_utils" ]; then
1397 source "$plat_utils"
1398 fi
1399
Daniel Boulbyb8d2a462022-03-07 13:55:25 +00001400 # Call pre-build hook
1401 call_hook pre_spm_build
1402
Manish Pandey1e7be852020-11-09 16:04:48 +00001403 # SPM build generates two sets of binaries, one for normal and other
1404 # for Secure world. We need both set of binaries for CI.
Olivier Deprez0a9a3482019-12-16 14:10:31 +01001405 archive="$build_archive"
Boyan Karatotev27057342025-07-28 09:56:23 +01001406 spm_build_root="$archive/build/spm"
1407
1408 spm_secure_build_root="$spm_build_root/$spm_secure_out_dir"
1409 spm_ns_build_root="$spm_build_root/$spm_non_secure_out_dir"
Olivier Deprez0a9a3482019-12-16 14:10:31 +01001410
Daniel Boulbyb8d2a462022-03-07 13:55:25 +00001411 echo "spm_build_root is $spm_build_root"
Olivier Deprez0a9a3482019-12-16 14:10:31 +01001412 echo "Building SPM ($mode) ..." |& log_separator
1413
1414 # NOTE: mode has no effect on SPM build (for now), hence debug
1415 # mode is built but subsequent build using release mode just
1416 # goes through with "nothing to do".
1417 build_spm
1418
1419 # Show SPM/Hafnium binary details
Boyan Karatotev27057342025-07-28 09:56:23 +01001420 cksum $spm_secure_build_root/hafnium.bin
Madhukar Pappireddyc683cf62021-11-01 14:38:32 -05001421
1422 # Some platforms only have secure configuration enabled. Hence,
1423 # non secure hanfnium binary might not be built.
Boyan Karatotev27057342025-07-28 09:56:23 +01001424 if [ -f $spm_ns_build_root/hafnium.bin ]; then
1425 cksum $spm_ns_build_root/hafnium.bin
Madhukar Pappireddyc683cf62021-11-01 14:38:32 -05001426 fi
Olivier Deprez0a9a3482019-12-16 14:10:31 +01001427
Boyan Karatotev27057342025-07-28 09:56:23 +01001428 secure_from="$spm_secure_build_root" non_secure_from="$spm_ns_build_root" to="$archive" collect_spm_artefacts
Olivier Deprez0a9a3482019-12-16 14:10:31 +01001429
1430 echo "##########"
1431 echo
1432 )
1433 fi
1434
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +00001435 # TF RMM build
1436 if config_valid "$rmm_config"; then
1437 (
1438 echo "##########"
1439
1440 plat_utils="$(get_rmm_opt PLAT_UTILS)"
1441 if [ -z ${plat_utils} ]; then
1442 # Source platform-specific utilities.
1443 plat="$(get_rmm_opt PLAT)"
Manish V Badarkhea3505272025-04-17 14:20:42 +01001444 extra_options="$(get_rmm_opt EXTRA_OPTIONS)"
1445 extra_targets="$(get_rmm_opt EXTRA_TARGETS "")"
1446 rmm_toolchain="$(get_rmm_opt TOOLCHAIN gnu)"
1447 rmm_fpu_use_at_rel2="$(get_rmm_opt RMM_FPU_USE_AT_REL2 OFF)"
1448 rmm_attest_el3_token_sign="$(get_rmm_opt ATTEST_EL3_TOKEN_SIGN OFF)"
1449 rmm_v1_1="$(get_rmm_opt RMM_V1_1 ON)"
Manish V Badarkhed62aa5f2025-03-18 21:18:14 +00001450 plat_utils="$ci_root/${plat}_utils.sh"
1451 else
1452 # Source platform-specific utilities by
1453 # using plat_utils name.
1454 plat_utils="$ci_root/${plat_utils}.sh"
1455 fi
1456
1457 if [ -f "$plat_utils" ]; then
1458 source "$plat_utils"
1459 fi
1460
1461 archive="$build_archive"
1462 rmm_build_root="$rmm_root/build"
1463
1464 echo "Building Trusted Firmware RMM ($mode) ..." |& log_separator
1465
1466 #call_hook pre_rmm_build
1467 build_rmm
1468
1469 # Collect all rmm.* files: rmm.img, rmm.elf, rmm.dump, rmm.map
1470 from="$rmm_build_root" to="$archive" collect_build_artefacts
1471
1472 # Clear any local changes made by applied patches
1473 undo_rmm_patches
1474
1475 echo "##########"
1476 )
1477 fi
1478
Fathi Boudra422bf772019-12-02 11:10:16 +02001479 # TF build
1480 if config_valid "$tf_config"; then
1481 (
1482 echo "##########"
1483
Manish V Badarkhe3bd3fea2020-11-08 15:17:00 +00001484 plat_utils="$(get_tf_opt PLAT_UTILS)"
Madhukar Pappireddy2f284e12021-08-30 16:06:14 -05001485 export plat_variant="$(get_tf_opt TARGET_PLATFORM)"
1486
Manish V Badarkhe3bd3fea2020-11-08 15:17:00 +00001487 if [ -z ${plat_utils} ]; then
1488 # Source platform-specific utilities.
1489 plat="$(get_tf_opt PLAT)"
1490 plat_utils="$ci_root/${plat}_utils.sh"
1491 else
1492 # Source platform-specific utilities by
1493 # using plat_utils name.
1494 plat_utils="$ci_root/${plat_utils}.sh"
1495 fi
1496
Fathi Boudra422bf772019-12-02 11:10:16 +02001497 if [ -f "$plat_utils" ]; then
1498 source "$plat_utils"
1499 fi
1500
Chris Kaye5a486b2023-08-04 11:50:31 +00001501 fvp_tsram_size="$(get_tf_opt FVP_TRUSTED_SRAM_SIZE)"
1502 fvp_tsram_size="${fvp_tsram_size:-256}"
1503
Harrison Mutaidc703402024-08-02 14:40:16 +00001504 poetry -C "$tf_root" install --without docs
Chris Kayd0837902021-11-17 10:17:52 +00001505
Fathi Boudra422bf772019-12-02 11:10:16 +02001506 archive="$build_archive"
Boyan Karatotev97de8d82025-03-06 15:22:21 +00001507 tf_build_root="$archive/build/tfa"
1508 mkdir -p ${tf_build_root}
Fathi Boudra422bf772019-12-02 11:10:16 +02001509
1510 echo "Building Trusted Firmware ($mode) ..." |& log_separator
1511
1512 # Call pre-build hook
1513 call_hook pre_tf_build
1514
1515 build_tf
1516
1517 # Call post-build hook
1518 call_hook post_tf_build
1519
1520 # Pre-archive hook
1521 call_hook pre_tf_archive
1522
1523 from="$tf_build_root" to="$archive" collect_build_artefacts
1524
1525 # Post-archive hook
1526 call_hook post_tf_archive
1527
1528 call_hook fetch_tf_resource
1529 call_hook post_fetch_tf_resource
1530
Chris Kay4e8aaf12022-09-01 15:21:55 +01001531 # Generate LAVA job files if necessary
1532 call_hook generate_lava_job_template
1533 call_hook generate_lava_job
1534
Fathi Boudra422bf772019-12-02 11:10:16 +02001535 # Clear any local changes made by applied patches
1536 undo_tf_patches
1537
1538 echo "##########"
1539 )
1540 fi
1541
Juan Pablo Conde3feb7f12023-10-21 13:14:47 -05001542 # TFUT build
1543 if config_valid "$tfut_config"; then
1544 (
1545 echo "##########"
1546
1547 archive="$build_archive"
1548 tfut_build_root="$tfut_root/build"
1549
1550 echo "Building Trusted Firmware UT ($mode) ..." |& log_separator
1551
1552 # Call pre-build hook
1553 call_hook pre_tfut_build
1554
1555 build_tfut
1556
1557 from="$tfut_build_root" to="$archive" collect_tfut_artefacts
1558
1559 echo "##########"
1560 echo
1561 )
1562 fi
Fathi Boudra422bf772019-12-02 11:10:16 +02001563 echo
1564 echo
1565done
1566
Juan Pablo Conde3feb7f12023-10-21 13:14:47 -05001567if config_valid "$tfut_config"; then
1568 deactivate
1569fi
1570
Fathi Boudra422bf772019-12-02 11:10:16 +02001571call_hook pre_package
1572
1573call_hook post_package
1574
1575if upon "$jenkins_run" && upon "$artefacts_receiver" && [ -d "artefacts" ]; then
Zelalem219df412020-05-17 19:21:20 -05001576 source "$CI_ROOT/script/send_artefacts.sh" "artefacts"
Fathi Boudra422bf772019-12-02 11:10:16 +02001577fi
1578
1579echo
1580echo "Done"