blob: 69eedfd476b702f1b258df04c5ec3869c9d533a5 [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"
Madhukar Pappireddy4b686cf2020-03-31 13:05:14 -0500435 extract_tarball $mbedtls_ar $mbedtls_dir
436 mbedtls_dir="$mbedtls_dir/$mbedtls_repo_name"
Fathi Boudra422bf772019-12-02 11:10:16 +0200437
438 fi
439
440 emit_env "MBEDTLS_DIR" "$mbedtls_dir"
441 fi
442
443 if [ -f "$env_file" ]; then
444 set -a
445 source "$env_file"
446 set +a
447 fi
448
449 cd "$tf_root"
450
451 # Always distclean when running on Jenkins. Skip distclean when running
452 # locally and explicitly requested.
453 if upon "$jenkins_run" || not_upon "$dont_clean"; then
454 make distclean &>>"$build_log" || fail_build
455 fi
456
457 # Log build command line. It is left unfolded on purpose to assist
458 # copying to clipboard.
459 cat <<EOF | log_separator >/dev/null
460
461Build command line:
462 $tf_build_wrapper make $make_j_opts $(cat "$config_file" | tr '\n' ' ') DEBUG=$DEBUG V=1 $build_targets
463
464EOF
465
466 # Build TF. Since build output is being directed to the build log, have
467 # descriptor 3 point to the current terminal for build wrappers to vent.
468 $tf_build_wrapper make $make_j_opts $(cat "$config_file") \
469 DEBUG="$DEBUG" V=1 \
470 $build_targets 3>&1 &>>"$build_log" || fail_build
471 )
472}
473
474build_tftf() {
475 (
476 config_file="${tftf_build_config:-$tftf_config_file}"
477
478 # Build tftf target by default
479 build_targets="${tftf_build_targets:-all}"
480
481 source "$config_file"
482
483 cd "$tftf_root"
484
485 # Always distclean when running on Jenkins. Skip distclean when running
486 # locally and explicitly requested.
487 if upon "$jenkins_run" || not_upon "$dont_clean"; then
488 make distclean &>>"$build_log" || fail_build
489 fi
490
491 # TFTF build system cannot reliably deal with -j option, so we avoid
492 # using that.
493
494 # Log build command line
495 cat <<EOF | log_separator >/dev/null
496
497Build command line:
498 make $(cat "$config_file" | tr '\n' ' ') DEBUG=$DEBUG V=1 $build_targets
499
500EOF
501
502 make $(cat "$config_file") DEBUG="$DEBUG" V=1 \
503 $build_targets &>>"$build_log" || fail_build
504 )
505}
506
507build_scp() {
508 (
509 config_file="${scp_build_config:-$scp_config_file}"
510
511 source "$config_file"
512
513 cd "$scp_root"
514
515 # Always distclean when running on Jenkins. Skip distclean when running
516 # locally and explicitly requested.
517 if upon "$jenkins_run" || not_upon "$dont_clean"; then
518 make clean &>>"$build_log" || fail_build
519 fi
520
521 # Log build command line. It is left unfolded on purpose to assist
522 # copying to clipboard.
523 cat <<EOF | log_separator >/dev/null
524
525SCP build command line:
526 make $(cat "$config_file" | tr '\n' ' ') MODE=$mode V=1
527
528EOF
529
530 # Build SCP
531 make $(cat "$config_file") MODE="$mode" V=1 &>>"$build_log" \
532 || fail_build
533 )
534}
535
536# Set metadata for the whole package so that it can be used by both Jenkins and
537# shell
538set_package_var() {
539 env_file="$artefacts/env" emit_env "$@"
540}
541
542set_tf_build_targets() {
543 echo "Set build target to '${targets:?}'"
544 set_hook_var "tf_build_targets" "$targets"
545}
546
547set_tftf_build_targets() {
548 echo "Set build target to '${targets:?}'"
549 set_hook_var "tftf_build_targets" "$targets"
550}
551
552set_scp_build_targets() {
553 echo "Set build target to '${targets:?}'"
554 set_hook_var "scp_build_targets" "$targets"
555}
556
557# Look under $archive directory for known files such as blX images, kernel, DTB,
558# initrd etc. For each known file foo, if foo.bin exists, then set variable
559# foo_bin to the path of the file. Make the path relative to the workspace so as
560# to remove any @ characters, which Jenkins inserts for parallel runs. If the
561# file doesn't exist, unset its path.
562set_default_bin_paths() {
563 local image image_name image_path path
564 local archive="${archive:?}"
565 local set_vars
566 local var
567
568 pushd "$archive"
569
570 for file in *.bin; do
571 # Get a shell variable from the file's stem
572 var_name="${file%%.*}_bin"
573 var_name="$(echo "$var_name" | sed -r 's/[^[:alnum:]]/_/g')"
574
575 # Skip setting the variable if it's already
576 if [ "${!var_name}" ]; then
577 echo "Note: not setting $var_name; already set to ${!var_name}"
578 continue
579 else
580 set_vars+="$var_name "
581 fi
582
583 eval "$var_name=$file"
584 done
585
586 echo "Binary paths set for: "
587 {
588 for var in $set_vars; do
589 echo -n "\$$var "
590 done
591 } | fmt -80 | sed 's/^/ /'
592 echo
593
594 popd
595}
596
597gen_model_params() {
598 local model_param_file="$archive/model_params"
599
600 set_default_bin_paths
601 echo "Generating model parameter for $model..."
602 source "$ci_root/model/${model:?}.sh"
603 archive_file "$model_param_file"
604}
605
606set_model_path() {
607 set_run_env "model_path" "${1:?}"
608}
609
610set_run_env() {
611 local var="${1:?}"
612 local val="${2?}"
613 local run_root="${archive:?}/run"
614
615 mkdir -p "$run_root"
616 env_file="$run_root/env" quote="1" emit_env "$var" "$val"
617}
618
619show_head() {
620 # Display HEAD descripton
621 pushd "$1"
622 git show --quiet --no-color | sed 's/^/ > /g'
623 echo
624 popd
625}
626
627# Choose debug binaries to run; by default, release binaries are chosen to run
628use_debug_bins() {
629 local run_root="${archive:?}/run"
630
631 echo "Choosing debug binaries for execution"
632 set_package_var "BIN_MODE" "debug"
633}
634
635assert_can_git_clone() {
636 local name="${1:?}"
637 local dir="${!name}"
638
639 # If it doesn't exist, it can be cloned into
640 if [ ! -e "$dir" ]; then
641 return 0
642 fi
643
644 # If it's a directory, it must be a Git clone already
645 if [ -d "$dir" ] && [ -d "$dir/.git" ]; then
646 # No need to clone again
647 echo "Using existing git clone for $name: $dir"
648 return 1
649 fi
650
651 die "Path $dir exists but is not a git clone"
652}
653
654clone_repo() {
655 if ! is_url "${clone_url?}"; then
656 # For --depth to take effect on local paths, it needs to use the
657 # file:// scheme.
658 clone_url="file://$clone_url"
659 fi
660
661 git clone -q --depth 1 "$clone_url" "${where?}"
662 if [ "$refspec" ]; then
663 pushd "$where"
664 git fetch -q --depth 1 origin "$refspec"
665 git checkout -q FETCH_HEAD
666 popd
667 fi
668}
669
670build_unstable() {
671 echo "--BUILD UNSTABLE--" | tee -a "$build_log"
672}
673
674undo_patch_record() {
675 if [ ! -f "${patch_record:?}" ]; then
676 return
677 fi
678
679 # Undo patches in reverse
680 echo
681 for patch_name in $(tac "$patch_record"); do
682 echo "Undoing $patch_name..."
683 if ! git apply -R "$ci_root/patch/$patch_name"; then
684 if upon "$local_ci"; then
685 echo
686 echo "Your local directory may have been dirtied."
687 echo
688 fi
689 fail_build
690 fi
691 done
692
693 rm -f "$patch_record"
694}
695
696undo_local_patches() {
697 pushd "$tf_root"
698 patch_record="$tf_patch_record" undo_patch_record
699 popd
700
701 if [ -d "$tftf_root" ]; then
702 pushd "$tftf_root"
703 patch_record="$tftf_patch_record" undo_patch_record
704 popd
705 fi
706}
707
708undo_tftf_patches() {
709 pushd "$tftf_root"
710 patch_record="$tftf_patch_record" undo_patch_record
711 popd
712}
713
714undo_tf_patches() {
715 pushd "$tf_root"
716 patch_record="$tf_patch_record" undo_patch_record
717 popd
718}
719
720apply_patch() {
721 # If skip_patches is set, the developer has applied required patches
722 # manually. They probably want to keep them applied for debugging
723 # purposes too. This means we don't have to apply/revert them as part of
724 # build process.
725 if upon "$skip_patches"; then
726 echo "Skipped applying ${1:?}..."
727 return 0
728 else
729 echo "Applying ${1:?}..."
730 fi
731
732 if git apply < "$ci_root/patch/$1"; then
733 echo "$1" >> "${patch_record:?}"
734 else
735 if upon "$local_ci"; then
736 undo_local_patches
737 fi
738 fail_build
739 fi
740}
741
742apply_tftf_patch() {
743 pushd "$tftf_root"
744 patch_record="$tftf_patch_record" apply_patch "$1"
745 popd
746}
747
748apply_tf_patch() {
749 pushd "$tf_root"
750 patch_record="$tf_patch_record" apply_patch "$1"
751 popd
752}
753
754# Clear workspace for a local run
755if not_upon "$jenkins_run"; then
756 rm -rf "$workspace"
757
758 # Clear residue from previous runs
759 rm -rf "$archive"
760fi
761
762mkdir -p "$workspace"
763mkdir -p "$archive"
764set_package_var "TEST_CONFIG" "$test_config"
765
766{
767echo
768echo "CONFIGURATION: $test_group/$test_config"
769echo
770} |& log_separator
771
772tf_config="$(echo "$build_configs" | awk -F, '{print $1}')"
773tftf_config="$(echo "$build_configs" | awk -F, '{print $2}')"
774scp_config="$(echo "$build_configs" | awk -F, '{print $3}')"
775
776test_config_file="$ci_root/group/$test_group/$test_config"
777
778tf_config_file="$ci_root/tf_config/$tf_config"
779tftf_config_file="$ci_root/tftf_config/$tftf_config"
780scp_config_file="$ci_root/scp_config/$scp_config"
781
782# File that keeps track of applied patches
783tf_patch_record="$workspace/tf_patches"
784tftf_patch_record="$workspace/tftf_patches"
785
786pushd "$workspace"
787
788if ! config_valid "$tf_config"; then
789 tf_config=
790else
791 echo "Trusted Firmware config:"
792 echo
793 sort "$tf_config_file" | sed '/^\s*$/d;s/^/\t/'
794 echo
795fi
796
797if ! config_valid "$tftf_config"; then
798 tftf_config=
799else
800 echo "Trusted Firmware TF config:"
801 echo
802 sort "$tftf_config_file" | sed '/^\s*$/d;s/^/\t/'
803 echo
804fi
805
806if ! config_valid "$scp_config"; then
807 scp_config=
808else
809 echo "SCP firmware config:"
810 echo
811 sort "$scp_config_file" | sed '/^\s*$/d;s/^/\t/'
812 echo
813fi
814
815if ! config_valid "$run_config"; then
816 run_config=
817fi
818
819if [ "$tf_config" ] && assert_can_git_clone "tf_root"; then
820 # If the Trusted Firmware repository has already been checked out, use
821 # that location. Otherwise, clone one ourselves.
822 echo "Cloning Trusted Firmware..."
823 clone_url="${TF_CHECKOUT_LOC:-$tf_src_repo_url}" where="$tf_root" \
824 refspec="$TF_REFSPEC" clone_repo &>>"$build_log"
825 show_head "$tf_root"
826fi
827
828if [ "$tftf_config" ] && assert_can_git_clone "tftf_root"; then
829 # If the Trusted Firmware TF repository has already been checked out,
830 # use that location. Otherwise, clone one ourselves.
831 echo "Cloning Trusted Firmware TF..."
832 clone_url="${TFTF_CHECKOUT_LOC:-$tftf_src_repo_url}" where="$tftf_root" \
833 refspec="$TFTF_REFSPEC" clone_repo &>>"$build_log"
834 show_head "$tftf_root"
835fi
836
837if [ "$scp_config" ] && assert_can_git_clone "scp_root"; then
838 # If the SCP firmware repository has already been checked out,
839 # use that location. Otherwise, clone one ourselves.
840 echo "Cloning SCP Firmware..."
841 clone_url="${SCP_CHECKOUT_LOC:-$scp_src_repo_url}" where="$scp_root" \
842 refspec="${SCP_REFSPEC-master-upstream}" clone_repo &>>"$build_log"
843
844 pushd "$scp_root"
845
846 # Use filer submodule as a reference if it exists
847 if [ -d "$SCP_CHECKOUT_LOC/cmsis" ]; then
848 cmsis_reference="--reference $SCP_CHECKOUT_LOC/cmsis"
849 fi
850
851 # If we don't have a reference yet, fall back to $cmsis_root if set, or
852 # then to project filer if accessible.
853 if [ -z "$cmsis_reference" ]; then
854 cmsis_ref_repo="${cmsis_root:-$project_filer/ref-repos/cmsis}"
855 if [ -d "$cmsis_ref_repo" ]; then
856 cmsis_reference="--reference $cmsis_ref_repo"
857 fi
858 fi
859
860 git submodule -q update $cmsis_reference --init
861
862 popd
863
864 show_head "$scp_root"
865fi
866
867if [ "$run_config" ]; then
868 # Get candidates for run config
869 run_config_candiates="$("$ci_root/script/gen_run_config_candidates.py" \
870 "$run_config")"
871 if [ -z "$run_config_candiates" ]; then
872 die "No run config candidates!"
873 else
874 echo
875 echo "Chosen fragments:"
876 echo
877 echo "$run_config_candiates" | sed 's/^\|\n/\t/g'
878 echo
879 fi
880fi
881
882call_hook "test_setup"
883echo
884
885if upon "$local_ci"; then
886 # For local runs, since each config is tried in sequence, it's
887 # advantageous to run jobs in parallel
888 if [ "$make_j" ]; then
889 make_j_opts="-j $make_j"
890 else
891 n_cores="$(getconf _NPROCESSORS_ONLN)" 2>/dev/null || true
892 if [ "$n_cores" ]; then
893 make_j_opts="-j $n_cores"
894 fi
895 fi
896fi
897
898modes="${bin_mode:-debug release}"
899for mode in $modes; do
900 # Build with a temporary archive
901 build_archive="$archive/$mode"
902 mkdir "$build_archive"
903
904 if [ "$mode" = "debug" ]; then
905 DEBUG=1
906 else
907 DEBUG=0
908 fi
909
910 # Perform builds in a subshell so as not to pollute the current and
911 # subsequent builds' environment
912
913 # SCP build
914 if config_valid "$scp_config"; then
915 (
916 echo "##########"
917
918 # Source platform-specific utilities
919 plat="$(get_scp_opt PRODUCT)"
920 plat_utils="$ci_root/${plat}_utils.sh"
921 if [ -f "$plat_utils" ]; then
922 source "$plat_utils"
923 fi
924
925 archive="$build_archive"
926 scp_build_root="$scp_root/build"
927
928 echo "Building SCP Firmware ($mode) ..." |& log_separator
929
930 build_scp
931
932 to="$archive" collect_scp_artefacts
933
934 echo "##########"
935 echo
936 )
937 fi
938
939 # TFTF build
940 if config_valid "$tftf_config"; then
941 (
942 echo "##########"
943
944 # Source platform-specific utilities
945 plat="$(get_tftf_opt PLAT)"
946 plat_utils="$ci_root/${plat}_utils.sh"
947 if [ -f "$plat_utils" ]; then
948 source "$plat_utils"
949 fi
950
951 archive="$build_archive"
952 tftf_build_root="$tftf_root/build"
953
954 echo "Building Trusted Firmware TF ($mode) ..." |& log_separator
955
956 # Call pre-build hook
957 call_hook pre_tftf_build
958
959 build_tftf
960
961 from="$tftf_build_root" to="$archive" collect_build_artefacts
962
963 # Clear any local changes made by applied patches
964 undo_tftf_patches
965
966 echo "##########"
967 echo
968 )
969 fi
970
971 # TF build
972 if config_valid "$tf_config"; then
973 (
974 echo "##########"
975
976 # Source platform-specific utilities
977 plat="$(get_tf_opt PLAT)"
978 plat_utils="$ci_root/${plat}_utils.sh"
979 if [ -f "$plat_utils" ]; then
980 source "$plat_utils"
981 fi
982
983 archive="$build_archive"
984 tf_build_root="$tf_root/build"
985
986 echo "Building Trusted Firmware ($mode) ..." |& log_separator
987
988 # Call pre-build hook
989 call_hook pre_tf_build
990
991 build_tf
992
993 # Call post-build hook
994 call_hook post_tf_build
995
996 # Pre-archive hook
997 call_hook pre_tf_archive
998
999 from="$tf_build_root" to="$archive" collect_build_artefacts
1000
1001 # Post-archive hook
1002 call_hook post_tf_archive
1003
1004 call_hook fetch_tf_resource
1005 call_hook post_fetch_tf_resource
1006
1007 # Clear any local changes made by applied patches
1008 undo_tf_patches
1009
1010 echo "##########"
1011 )
1012 fi
1013
1014 echo
1015 echo
1016done
1017
1018call_hook pre_package
1019
1020call_hook post_package
1021
1022if upon "$jenkins_run" && upon "$artefacts_receiver" && [ -d "artefacts" ]; then
1023 tar -cJf "artefacts.tar.xz" "artefacts"
1024 where="$artefacts_receiver/$test_group/$test_config/artefacts.tar.xz"
1025 where+="?j=$JOB_NAME&b=$BUILD_NUMBER"
1026 if wget -q --method=PUT --body-file="artefacts.tar.xz" "$where"; then
1027 echo "Artefacts submitted to $where."
1028 else
1029 echo "Error submitting artefacts to $where."
1030 fi
1031fi
1032
1033echo
1034echo "Done"