blob: fa8d3215ea1f9e2f463b4a75e9683c46672022a3 [file] [log] [blame]
Fathi Boudra422bf772019-12-02 11:10:16 +02001#!/bin/bash
2#
3# Copyright (c) 2019, Arm Limited. All rights reserved.
4#
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.
21tf_root="${tf_root:-$workspace/trusted_firmware}"
22tftf_root="${tftf_root:-$workspace/trusted_firmware_tf}"
23scp_root="${scp_root:-$workspace/scp}"
24
25# Refspecs
26tf_refspec="$TF_REFSPEC"
27tftf_refspec="$TFTF_REFSPEC"
28scp_refspec="$SCP_REFSPEC"
29
30test_config="${TEST_CONFIG:?}"
31test_group="${TEST_GROUP:?}"
32build_configs="${BUILD_CONFIG:?}"
33run_config="${RUN_CONFIG:?}"
34
35archive="$artefacts"
36build_log="$artefacts/build.log"
37fiptool="$tf_root/tools/fiptool/fiptool"
38cert_create="$tf_root/tools/cert_create/cert_create"
39
40# Validate $bin_mode
41case "$bin_mode" in
42 "" | debug | release)
43 ;;
44 *)
45 die "Invalid value for bin_mode: $bin_mode"
46 ;;
47esac
48
49# File to save any environem
50hook_env_file="$(mktempfile)"
51
52# Check if a config is valid
53config_valid() {
54 local config="${1?}"
55 if [ -z "$config" ] || [ "$(basename "$config")" = "nil" ]; then
56 return 1
57 fi
58
59 return 0
60}
61
62# Echo from a build wrapper. Print to descriptor 3 that's opened by the build
63# function.
64echo_w() {
65 echo $echo_flags "$@" >&3
66}
67
68# Print a separator to the log file. Intended to be used at the tail end of a pipe
69log_separator() {
70 {
71 echo
72 echo "----------"
73 } >> "$build_log"
74
75 tee -a "$build_log"
76
77 {
78 echo "----------"
79 echo
80 } >> "$build_log"
81}
82
83# Call function $1 if it's defined
84call_func() {
85 if type "${1:?}" &>/dev/null; then
86 echo
87 echo "> ${2:?}:$1()"
88 eval "$1"
89 echo "< $2:$1()"
90 fi
91}
92
93# Call hook $1 in all chosen fragments if it's defined. Hooks are invoked from
94# within a subshell, so any variables set within a hook are lost. Should a
95# variable needs to be set from within a hook, the function 'set_hook_var'
96# should be used
97call_hook() {
98 local func="$1"
99 local config_fragment
100
101 [ -z "$func" ] && return 0
102
103 : >"$hook_env_file"
104
105 if [ "$run_config_candiates" ]; then
106 for config_fragment in $run_config_candiates; do
107 (
108 source "$ci_root/run_config/$config_fragment"
109 call_func "$func" "$config_fragment"
110 )
111 done
112 fi
113
114 # Also source test config file
115 (
116 unset "$func"
117 source "$test_config_file"
118 call_func "$func" "$(basename $test_config_file)"
119 )
120
121 # Have any variables set take effect
122 source "$hook_env_file"
123}
124
125# Set a variable from within a hook
126set_hook_var() {
127 echo "export $1=\"${2?}\"" >> "$hook_env_file"
128}
129
130# Append to an array from within a hook
131append_hook_var() {
132 echo "export $1+=\"${2?}\"" >> "$hook_env_file"
133}
134
135# Have the main build script source a file
136source_later() {
137 echo "source ${1?}" >> "$hook_env_file"
138}
139
140# Setup TF build wrapper function by pointing to a script containing a function
141# that will be called with the TF build commands.
142setup_tf_build_wrapper() {
143 source_later "$ci_root/script/${wrapper?}_wrapper.sh"
144 set_hook_var "tf_build_wrapper" "${wrapper}_wrapper"
145 echo "Setup $wrapper build wrapper."
146}
147
148# Collect .bin files for archiving
149collect_build_artefacts() {
150 if [ ! -d "${from:?}" ]; then
151 return
152 fi
153
154 if ! find "$from" \( -name "*.bin" -o -name '*.elf' -o -name '*.dtb' \) -exec cp -t "${to:?}" '{}' +; then
155 echo "You probably are running local CI on local repositories."
156 echo "Did you set 'dont_clean' but forgot to run 'distclean'?"
157 die
158 fi
159}
160
161# SCP and MCP binaries are named firmware.{bin,elf}, and are placed under
162# scp/mcp_ramfw and scp/mcp_romfw directories, so can't be collected by
163# collect_build_artefacts function.
164collect_scp_artefacts() {
165 to="${to:?}" \
166 find "$scp_root" \( -name "*.bin" -o -name '*.elf' \) -exec bash -c '
167 for file; do
168 ext="$(echo $file | awk -F. "{print \$NF}")"
169 case $file in
170 */scp_ramfw/*)
171 cp $file $to/scp_ram.$ext
172 ;;
173 */scp_romfw/*)
174 cp $file $to/scp_rom.$ext
175 ;;
176 */mcp_ramfw/*)
177 cp $file $to/mcp_ram.$ext
178 ;;
179 */mcp_romfw/*)
180 cp $file $to/mcp_rom.$ext
181 ;;
182 *)
183 echo "Unknown SCP binary: $file" >&2
184 ;;
185 esac
186 done
187 ' bash '{}' +
188}
189
190# Arrange environment varibles to be set when expect scripts are launched
191set_expect_variable() {
192 local var="${1:?}"
193 local val="${2?}"
194
195 local run_root="${archive:?}/run"
196 local uart_dir="$run_root/uart${uart:?}"
197 mkdir -p "$uart_dir"
198
199 env_file="$uart_dir/env" quote="1" emit_env "$var" "$val"
200 echo "UART$uart: env has $@"
201}
202
203# Place the binary package a pointer to expect script, and its parameters
204track_expect() {
205 local file="${file:?}"
206 local timeout="${timeout-600}"
207 local run_root="${archive:?}/run"
208
209 local uart_dir="$run_root/uart${uart:?}"
210 mkdir -p "$uart_dir"
211
212 echo "$file" > "$uart_dir/expect"
213 echo "$timeout" > "$uart_dir/timeout"
214
215 echo "UART$uart to be tracked with $file; timeout ${timeout}s"
216
217 # The run script assumes UART0 to be primary. If we're asked to set any
218 # other UART to be primary, set a run environment variable to signal
219 # that to the run script
220 if upon "$set_primary"; then
221 echo "Primary UART set to UART$uart."
222 set_run_env "primary_uart" "$uart"
223 fi
224}
225
226# Extract a FIP in $1 using fiptool
227extract_fip() {
228 local fip="$1"
229
230 if is_url "$1"; then
231 url="$1" fetch_file
232 fip="$(basename "$1")"
233 fi
234
235 "$fiptool" unpack "$fip"
236 echo "Extracted FIP: $fip"
237}
238
239# Report build failure by printing a the tail end of build log. Archive the
240# build log for later inspection
241fail_build() {
242 local log_path
243
244 if upon "$jenkins_run"; then
245 log_path="$BUILD_URL/artifact/artefacts/build.log"
246 else
247 log_path="$build_log"
248 fi
249
250 echo
251 echo "Build failed! Tail of build log below:"
252 echo "[...]"
253 echo
254 tail -n15 "$build_log"
255 echo
256 echo "See $log_path for full output"
257 echo
258 cp -t "$archive" "$build_log"
259 exit 1;
260}
261
262# Build a FIP with supplied arguments
263build_fip() {
264 (
265 echo "Building FIP with arguments: $@"
266 local tf_env="$workspace/tf.env"
267
268 if [ -f "$tf_env" ]; then
269 set -a
270 source "$tf_env"
271 set +a
272 fi
273
274 make -C "$tf_root" $(cat "$tf_config_file") DEBUG="$DEBUG" V=1 "$@" \
275 ${fip_targets:-fip} &>>"$build_log" || fail_build
276 )
277}
278
279fip_update() {
280 # Before the update process, check if the given image is supported by
281 # the fiptool. It's assumed that both fiptool and cert_create move in
282 # tandem, and therfore, if one has support, the other has it too.
283 if ! "$fiptool" update 2>&1 | grep -qe "\s\+--${bin_name:?}"; then
284 return 1
285 fi
286
287 if not_upon "$(get_tf_opt TRUSTED_BOARD_BOOT)"; then
288 echo "Updating FIP image: $bin_name"
289 # Update HW config. Without TBBR, it's only a matter of using
290 # the update sub-command of fiptool
291 "$fiptool" update "--$bin_name" "${src:-}" \
292 "$archive/fip.bin"
293 else
294 echo "Updating FIP image (TBBR): $bin_name"
295 # With TBBR, we need to unpack, re-create certificates, and then
296 # recreate the FIP.
297 local fip_dir="$(mktempdir)"
298 local bin common_args stem
299 local rot_key="$(get_tf_opt ROT_KEY)"
300
301 rot_key="${rot_key:?}"
302 if ! is_abs "$rot_key"; then
303 rot_key="$tf_root/$rot_key"
304 fi
305
306 # Arguments only for cert_create
307 local cert_args="-n"
308 cert_args+=" --tfw-nvctr ${nvctr:-31}"
309 cert_args+=" --ntfw-nvctr ${nvctr:-223}"
310 cert_args+=" --key-alg ${KEY_ALG:-rsa}"
311 cert_args+=" --rot-key $rot_key"
312
313 local dyn_config_opts=(
314 "hw-config"
315 "tb-fw-config"
316 "nt-fw-config"
317 "soc-fw-config"
318 "tos-fw-config"
319 )
320
321 # Binaries without key certificates
322 declare -A has_no_key_cert
323 for bin in "tb-fw" "${dyn_config_opts[@]}"; do
324 has_no_key_cert["$bin"]="1"
325 done
326
327 # Binaries without certificates
328 declare -A has_no_cert
329 for bin in "hw-config" "${dyn_config_opts[@]}"; do
330 has_no_cert["$bin"]="1"
331 done
332
333 pushd "$fip_dir"
334
335 # Unpack FIP
336 "$fiptool" unpack "$archive/fip.bin" &>>"$build_log"
337
338 # Remove all existing certificates
339 rm -f *-cert.bin
340
341 # Copy the binary to be updated
342 cp -f "$src" "${bin_name}.bin"
343
344 # FIP unpack dumps binaries with the same name as the option
345 # used to pack it; likewise for certificates. Reverse-engineer
346 # the command line from the binary output.
347 common_args="--trusted-key-cert trusted_key.crt"
348 for bin in *.bin; do
349 stem="${bin%%.bin}"
350 common_args+=" --$stem $bin"
351 if not_upon "${has_no_cert[$stem]}"; then
352 common_args+=" --$stem-cert $stem.crt"
353 fi
354 if not_upon "${has_no_key_cert[$stem]}"; then
355 common_args+=" --$stem-key-cert $stem-key.crt"
356 fi
357 done
358
359 # Create certificates
360 "$cert_create" $cert_args $common_args &>>"$build_log"
361
362 # Recreate and archive FIP
363 "$fiptool" create $common_args "fip.bin" &>>"$build_log"
364 archive_file "fip.bin"
365
366 popd
367 fi
368}
369
370# Update hw-config in FIP, and remove the original DTB afterwards.
371update_fip_hw_config() {
372 # The DTB needs to be loaded by the model (and not updated in the FIP)
373 # in configs where BL2 isn't present
374 case "1" in
375 "$(get_tf_opt RESET_TO_BL31)" | \
376 "$(get_tf_opt RESET_TO_SP_MIN)" | \
377 "$(get_tf_opt BL2_AT_EL3)")
378 return 0;;
379 esac
380
381 if bin_name="hw-config" src="$archive/dtb.bin" fip_update; then
382 # Remove the DTB so that model won't load it
383 rm -f "$archive/dtb.bin"
384 fi
385}
386
387get_scp_opt() {
388 (
389 name="${1:?}"
390 if config_valid "$scp_config_file"; then
391 source "$scp_config_file"
392 echo "${!name}"
393 fi
394 )
395}
396
397get_tftf_opt() {
398 (
399 name="${1:?}"
400 if config_valid "$tftf_config_file"; then
401 source "$tftf_config_file"
402 echo "${!name}"
403 fi
404 )
405}
406
407get_tf_opt() {
408 (
409 name="${1:?}"
410 if config_valid "$tf_config_file"; then
411 source "$tf_config_file"
412 echo "${!name}"
413 fi
414 )
415}
416
417build_tf() {
418 (
419 env_file="$workspace/tf.env"
420 config_file="${tf_build_config:-$tf_config_file}"
421
422 # Build fiptool and all targets by default
423 build_targets="${tf_build_targets:-fiptool all}"
424
425 source "$config_file"
426
427 # If it is a TBBR build, extract the MBED TLS library from archive
428 if [ "$(get_tf_opt TRUSTED_BOARD_BOOT)" = 1 ]; then
429 mbedtls_dir="$workspace/mbedtls"
430 if [ ! -d "$mbedtls_dir" ]; then
431 mbedtls_ar="$workspace/mbedtls.tar.gz"
432
433 url="$mbedtls_archive" saveas="$mbedtls_ar" fetch_file
434 mkdir "$mbedtls_dir"
435 pushd "$mbedtls_dir"
436 tar -xzf "$mbedtls_ar"
437 popd
438
439 fi
440
441 emit_env "MBEDTLS_DIR" "$mbedtls_dir"
442 fi
443
444 if [ -f "$env_file" ]; then
445 set -a
446 source "$env_file"
447 set +a
448 fi
449
450 cd "$tf_root"
451
452 # Always distclean when running on Jenkins. Skip distclean when running
453 # locally and explicitly requested.
454 if upon "$jenkins_run" || not_upon "$dont_clean"; then
455 make distclean &>>"$build_log" || fail_build
456 fi
457
458 # Log build command line. It is left unfolded on purpose to assist
459 # copying to clipboard.
460 cat <<EOF | log_separator >/dev/null
461
462Build command line:
463 $tf_build_wrapper make $make_j_opts $(cat "$config_file" | tr '\n' ' ') DEBUG=$DEBUG V=1 $build_targets
464
465EOF
466
467 # Build TF. Since build output is being directed to the build log, have
468 # descriptor 3 point to the current terminal for build wrappers to vent.
469 $tf_build_wrapper make $make_j_opts $(cat "$config_file") \
470 DEBUG="$DEBUG" V=1 \
471 $build_targets 3>&1 &>>"$build_log" || fail_build
472 )
473}
474
475build_tftf() {
476 (
477 config_file="${tftf_build_config:-$tftf_config_file}"
478
479 # Build tftf target by default
480 build_targets="${tftf_build_targets:-all}"
481
482 source "$config_file"
483
484 cd "$tftf_root"
485
486 # Always distclean when running on Jenkins. Skip distclean when running
487 # locally and explicitly requested.
488 if upon "$jenkins_run" || not_upon "$dont_clean"; then
489 make distclean &>>"$build_log" || fail_build
490 fi
491
492 # TFTF build system cannot reliably deal with -j option, so we avoid
493 # using that.
494
495 # Log build command line
496 cat <<EOF | log_separator >/dev/null
497
498Build command line:
499 make $(cat "$config_file" | tr '\n' ' ') DEBUG=$DEBUG V=1 $build_targets
500
501EOF
502
503 make $(cat "$config_file") DEBUG="$DEBUG" V=1 \
504 $build_targets &>>"$build_log" || fail_build
505 )
506}
507
508build_scp() {
509 (
510 config_file="${scp_build_config:-$scp_config_file}"
511
512 source "$config_file"
513
514 cd "$scp_root"
515
516 # Always distclean when running on Jenkins. Skip distclean when running
517 # locally and explicitly requested.
518 if upon "$jenkins_run" || not_upon "$dont_clean"; then
519 make clean &>>"$build_log" || fail_build
520 fi
521
522 # Log build command line. It is left unfolded on purpose to assist
523 # copying to clipboard.
524 cat <<EOF | log_separator >/dev/null
525
526SCP build command line:
527 make $(cat "$config_file" | tr '\n' ' ') MODE=$mode V=1
528
529EOF
530
531 # Build SCP
532 make $(cat "$config_file") MODE="$mode" V=1 &>>"$build_log" \
533 || fail_build
534 )
535}
536
537# Set metadata for the whole package so that it can be used by both Jenkins and
538# shell
539set_package_var() {
540 env_file="$artefacts/env" emit_env "$@"
541}
542
543set_tf_build_targets() {
544 echo "Set build target to '${targets:?}'"
545 set_hook_var "tf_build_targets" "$targets"
546}
547
548set_tftf_build_targets() {
549 echo "Set build target to '${targets:?}'"
550 set_hook_var "tftf_build_targets" "$targets"
551}
552
553set_scp_build_targets() {
554 echo "Set build target to '${targets:?}'"
555 set_hook_var "scp_build_targets" "$targets"
556}
557
558# Look under $archive directory for known files such as blX images, kernel, DTB,
559# initrd etc. For each known file foo, if foo.bin exists, then set variable
560# foo_bin to the path of the file. Make the path relative to the workspace so as
561# to remove any @ characters, which Jenkins inserts for parallel runs. If the
562# file doesn't exist, unset its path.
563set_default_bin_paths() {
564 local image image_name image_path path
565 local archive="${archive:?}"
566 local set_vars
567 local var
568
569 pushd "$archive"
570
571 for file in *.bin; do
572 # Get a shell variable from the file's stem
573 var_name="${file%%.*}_bin"
574 var_name="$(echo "$var_name" | sed -r 's/[^[:alnum:]]/_/g')"
575
576 # Skip setting the variable if it's already
577 if [ "${!var_name}" ]; then
578 echo "Note: not setting $var_name; already set to ${!var_name}"
579 continue
580 else
581 set_vars+="$var_name "
582 fi
583
584 eval "$var_name=$file"
585 done
586
587 echo "Binary paths set for: "
588 {
589 for var in $set_vars; do
590 echo -n "\$$var "
591 done
592 } | fmt -80 | sed 's/^/ /'
593 echo
594
595 popd
596}
597
598gen_model_params() {
599 local model_param_file="$archive/model_params"
600
601 set_default_bin_paths
602 echo "Generating model parameter for $model..."
603 source "$ci_root/model/${model:?}.sh"
604 archive_file "$model_param_file"
605}
606
607set_model_path() {
608 set_run_env "model_path" "${1:?}"
609}
610
611set_run_env() {
612 local var="${1:?}"
613 local val="${2?}"
614 local run_root="${archive:?}/run"
615
616 mkdir -p "$run_root"
617 env_file="$run_root/env" quote="1" emit_env "$var" "$val"
618}
619
620show_head() {
621 # Display HEAD descripton
622 pushd "$1"
623 git show --quiet --no-color | sed 's/^/ > /g'
624 echo
625 popd
626}
627
628# Choose debug binaries to run; by default, release binaries are chosen to run
629use_debug_bins() {
630 local run_root="${archive:?}/run"
631
632 echo "Choosing debug binaries for execution"
633 set_package_var "BIN_MODE" "debug"
634}
635
636assert_can_git_clone() {
637 local name="${1:?}"
638 local dir="${!name}"
639
640 # If it doesn't exist, it can be cloned into
641 if [ ! -e "$dir" ]; then
642 return 0
643 fi
644
645 # If it's a directory, it must be a Git clone already
646 if [ -d "$dir" ] && [ -d "$dir/.git" ]; then
647 # No need to clone again
648 echo "Using existing git clone for $name: $dir"
649 return 1
650 fi
651
652 die "Path $dir exists but is not a git clone"
653}
654
655clone_repo() {
656 if ! is_url "${clone_url?}"; then
657 # For --depth to take effect on local paths, it needs to use the
658 # file:// scheme.
659 clone_url="file://$clone_url"
660 fi
661
662 git clone -q --depth 1 "$clone_url" "${where?}"
663 if [ "$refspec" ]; then
664 pushd "$where"
665 git fetch -q --depth 1 origin "$refspec"
666 git checkout -q FETCH_HEAD
667 popd
668 fi
669}
670
671build_unstable() {
672 echo "--BUILD UNSTABLE--" | tee -a "$build_log"
673}
674
675undo_patch_record() {
676 if [ ! -f "${patch_record:?}" ]; then
677 return
678 fi
679
680 # Undo patches in reverse
681 echo
682 for patch_name in $(tac "$patch_record"); do
683 echo "Undoing $patch_name..."
684 if ! git apply -R "$ci_root/patch/$patch_name"; then
685 if upon "$local_ci"; then
686 echo
687 echo "Your local directory may have been dirtied."
688 echo
689 fi
690 fail_build
691 fi
692 done
693
694 rm -f "$patch_record"
695}
696
697undo_local_patches() {
698 pushd "$tf_root"
699 patch_record="$tf_patch_record" undo_patch_record
700 popd
701
702 if [ -d "$tftf_root" ]; then
703 pushd "$tftf_root"
704 patch_record="$tftf_patch_record" undo_patch_record
705 popd
706 fi
707}
708
709undo_tftf_patches() {
710 pushd "$tftf_root"
711 patch_record="$tftf_patch_record" undo_patch_record
712 popd
713}
714
715undo_tf_patches() {
716 pushd "$tf_root"
717 patch_record="$tf_patch_record" undo_patch_record
718 popd
719}
720
721apply_patch() {
722 # If skip_patches is set, the developer has applied required patches
723 # manually. They probably want to keep them applied for debugging
724 # purposes too. This means we don't have to apply/revert them as part of
725 # build process.
726 if upon "$skip_patches"; then
727 echo "Skipped applying ${1:?}..."
728 return 0
729 else
730 echo "Applying ${1:?}..."
731 fi
732
733 if git apply < "$ci_root/patch/$1"; then
734 echo "$1" >> "${patch_record:?}"
735 else
736 if upon "$local_ci"; then
737 undo_local_patches
738 fi
739 fail_build
740 fi
741}
742
743apply_tftf_patch() {
744 pushd "$tftf_root"
745 patch_record="$tftf_patch_record" apply_patch "$1"
746 popd
747}
748
749apply_tf_patch() {
750 pushd "$tf_root"
751 patch_record="$tf_patch_record" apply_patch "$1"
752 popd
753}
754
755# Clear workspace for a local run
756if not_upon "$jenkins_run"; then
757 rm -rf "$workspace"
758
759 # Clear residue from previous runs
760 rm -rf "$archive"
761fi
762
763mkdir -p "$workspace"
764mkdir -p "$archive"
765set_package_var "TEST_CONFIG" "$test_config"
766
767{
768echo
769echo "CONFIGURATION: $test_group/$test_config"
770echo
771} |& log_separator
772
773tf_config="$(echo "$build_configs" | awk -F, '{print $1}')"
774tftf_config="$(echo "$build_configs" | awk -F, '{print $2}')"
775scp_config="$(echo "$build_configs" | awk -F, '{print $3}')"
776
777test_config_file="$ci_root/group/$test_group/$test_config"
778
779tf_config_file="$ci_root/tf_config/$tf_config"
780tftf_config_file="$ci_root/tftf_config/$tftf_config"
781scp_config_file="$ci_root/scp_config/$scp_config"
782
783# File that keeps track of applied patches
784tf_patch_record="$workspace/tf_patches"
785tftf_patch_record="$workspace/tftf_patches"
786
787pushd "$workspace"
788
789if ! config_valid "$tf_config"; then
790 tf_config=
791else
792 echo "Trusted Firmware config:"
793 echo
794 sort "$tf_config_file" | sed '/^\s*$/d;s/^/\t/'
795 echo
796fi
797
798if ! config_valid "$tftf_config"; then
799 tftf_config=
800else
801 echo "Trusted Firmware TF config:"
802 echo
803 sort "$tftf_config_file" | sed '/^\s*$/d;s/^/\t/'
804 echo
805fi
806
807if ! config_valid "$scp_config"; then
808 scp_config=
809else
810 echo "SCP firmware config:"
811 echo
812 sort "$scp_config_file" | sed '/^\s*$/d;s/^/\t/'
813 echo
814fi
815
816if ! config_valid "$run_config"; then
817 run_config=
818fi
819
820if [ "$tf_config" ] && assert_can_git_clone "tf_root"; then
821 # If the Trusted Firmware repository has already been checked out, use
822 # that location. Otherwise, clone one ourselves.
823 echo "Cloning Trusted Firmware..."
824 clone_url="${TF_CHECKOUT_LOC:-$tf_src_repo_url}" where="$tf_root" \
825 refspec="$TF_REFSPEC" clone_repo &>>"$build_log"
826 show_head "$tf_root"
827fi
828
829if [ "$tftf_config" ] && assert_can_git_clone "tftf_root"; then
830 # If the Trusted Firmware TF repository has already been checked out,
831 # use that location. Otherwise, clone one ourselves.
832 echo "Cloning Trusted Firmware TF..."
833 clone_url="${TFTF_CHECKOUT_LOC:-$tftf_src_repo_url}" where="$tftf_root" \
834 refspec="$TFTF_REFSPEC" clone_repo &>>"$build_log"
835 show_head "$tftf_root"
836fi
837
838if [ "$scp_config" ] && assert_can_git_clone "scp_root"; then
839 # If the SCP firmware repository has already been checked out,
840 # use that location. Otherwise, clone one ourselves.
841 echo "Cloning SCP Firmware..."
842 clone_url="${SCP_CHECKOUT_LOC:-$scp_src_repo_url}" where="$scp_root" \
843 refspec="${SCP_REFSPEC-master-upstream}" clone_repo &>>"$build_log"
844
845 pushd "$scp_root"
846
847 # Use filer submodule as a reference if it exists
848 if [ -d "$SCP_CHECKOUT_LOC/cmsis" ]; then
849 cmsis_reference="--reference $SCP_CHECKOUT_LOC/cmsis"
850 fi
851
852 # If we don't have a reference yet, fall back to $cmsis_root if set, or
853 # then to project filer if accessible.
854 if [ -z "$cmsis_reference" ]; then
855 cmsis_ref_repo="${cmsis_root:-$project_filer/ref-repos/cmsis}"
856 if [ -d "$cmsis_ref_repo" ]; then
857 cmsis_reference="--reference $cmsis_ref_repo"
858 fi
859 fi
860
861 git submodule -q update $cmsis_reference --init
862
863 popd
864
865 show_head "$scp_root"
866fi
867
868if [ "$run_config" ]; then
869 # Get candidates for run config
870 run_config_candiates="$("$ci_root/script/gen_run_config_candidates.py" \
871 "$run_config")"
872 if [ -z "$run_config_candiates" ]; then
873 die "No run config candidates!"
874 else
875 echo
876 echo "Chosen fragments:"
877 echo
878 echo "$run_config_candiates" | sed 's/^\|\n/\t/g'
879 echo
880 fi
881fi
882
883call_hook "test_setup"
884echo
885
886if upon "$local_ci"; then
887 # For local runs, since each config is tried in sequence, it's
888 # advantageous to run jobs in parallel
889 if [ "$make_j" ]; then
890 make_j_opts="-j $make_j"
891 else
892 n_cores="$(getconf _NPROCESSORS_ONLN)" 2>/dev/null || true
893 if [ "$n_cores" ]; then
894 make_j_opts="-j $n_cores"
895 fi
896 fi
897fi
898
899modes="${bin_mode:-debug release}"
900for mode in $modes; do
901 # Build with a temporary archive
902 build_archive="$archive/$mode"
903 mkdir "$build_archive"
904
905 if [ "$mode" = "debug" ]; then
906 DEBUG=1
907 else
908 DEBUG=0
909 fi
910
911 # Perform builds in a subshell so as not to pollute the current and
912 # subsequent builds' environment
913
914 # SCP build
915 if config_valid "$scp_config"; then
916 (
917 echo "##########"
918
919 # Source platform-specific utilities
920 plat="$(get_scp_opt PRODUCT)"
921 plat_utils="$ci_root/${plat}_utils.sh"
922 if [ -f "$plat_utils" ]; then
923 source "$plat_utils"
924 fi
925
926 archive="$build_archive"
927 scp_build_root="$scp_root/build"
928
929 echo "Building SCP Firmware ($mode) ..." |& log_separator
930
931 build_scp
932
933 to="$archive" collect_scp_artefacts
934
935 echo "##########"
936 echo
937 )
938 fi
939
940 # TFTF build
941 if config_valid "$tftf_config"; then
942 (
943 echo "##########"
944
945 # Source platform-specific utilities
946 plat="$(get_tftf_opt PLAT)"
947 plat_utils="$ci_root/${plat}_utils.sh"
948 if [ -f "$plat_utils" ]; then
949 source "$plat_utils"
950 fi
951
952 archive="$build_archive"
953 tftf_build_root="$tftf_root/build"
954
955 echo "Building Trusted Firmware TF ($mode) ..." |& log_separator
956
957 # Call pre-build hook
958 call_hook pre_tftf_build
959
960 build_tftf
961
962 from="$tftf_build_root" to="$archive" collect_build_artefacts
963
964 # Clear any local changes made by applied patches
965 undo_tftf_patches
966
967 echo "##########"
968 echo
969 )
970 fi
971
972 # TF build
973 if config_valid "$tf_config"; then
974 (
975 echo "##########"
976
977 # Source platform-specific utilities
978 plat="$(get_tf_opt PLAT)"
979 plat_utils="$ci_root/${plat}_utils.sh"
980 if [ -f "$plat_utils" ]; then
981 source "$plat_utils"
982 fi
983
984 archive="$build_archive"
985 tf_build_root="$tf_root/build"
986
987 echo "Building Trusted Firmware ($mode) ..." |& log_separator
988
989 # Call pre-build hook
990 call_hook pre_tf_build
991
992 build_tf
993
994 # Call post-build hook
995 call_hook post_tf_build
996
997 # Pre-archive hook
998 call_hook pre_tf_archive
999
1000 from="$tf_build_root" to="$archive" collect_build_artefacts
1001
1002 # Post-archive hook
1003 call_hook post_tf_archive
1004
1005 call_hook fetch_tf_resource
1006 call_hook post_fetch_tf_resource
1007
1008 # Clear any local changes made by applied patches
1009 undo_tf_patches
1010
1011 echo "##########"
1012 )
1013 fi
1014
1015 echo
1016 echo
1017done
1018
1019call_hook pre_package
1020
1021call_hook post_package
1022
1023if upon "$jenkins_run" && upon "$artefacts_receiver" && [ -d "artefacts" ]; then
1024 tar -cJf "artefacts.tar.xz" "artefacts"
1025 where="$artefacts_receiver/$test_group/$test_config/artefacts.tar.xz"
1026 where+="?j=$JOB_NAME&b=$BUILD_NUMBER"
1027 if wget -q --method=PUT --body-file="artefacts.tar.xz" "$where"; then
1028 echo "Artefacts submitted to $where."
1029 else
1030 echo "Error submitting artefacts to $where."
1031 fi
1032fi
1033
1034echo
1035echo "Done"