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