blob: da75a874dd4f39abbfbf2717cad7458a4cac6dde [file] [log] [blame]
Leonardo Sandoval9dfdd1b2020-08-06 17:08:11 -05001#!/usr/bin/env bash
Fathi Boudra422bf772019-12-02 11:10:16 +02002#
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=(
Zelalem1af7a7b2020-08-04 17:34:32 -0500323 "fw-config"
Fathi Boudra422bf772019-12-02 11:10:16 +0200324 "hw-config"
325 "tb-fw-config"
326 "nt-fw-config"
327 "soc-fw-config"
328 "tos-fw-config"
329 )
330
331 # Binaries without key certificates
332 declare -A has_no_key_cert
333 for bin in "tb-fw" "${dyn_config_opts[@]}"; do
334 has_no_key_cert["$bin"]="1"
335 done
336
337 # Binaries without certificates
338 declare -A has_no_cert
339 for bin in "hw-config" "${dyn_config_opts[@]}"; do
340 has_no_cert["$bin"]="1"
341 done
342
343 pushd "$fip_dir"
344
345 # Unpack FIP
346 "$fiptool" unpack "$archive/fip.bin" &>>"$build_log"
347
348 # Remove all existing certificates
349 rm -f *-cert.bin
350
351 # Copy the binary to be updated
352 cp -f "$src" "${bin_name}.bin"
353
354 # FIP unpack dumps binaries with the same name as the option
355 # used to pack it; likewise for certificates. Reverse-engineer
356 # the command line from the binary output.
357 common_args="--trusted-key-cert trusted_key.crt"
358 for bin in *.bin; do
359 stem="${bin%%.bin}"
360 common_args+=" --$stem $bin"
361 if not_upon "${has_no_cert[$stem]}"; then
362 common_args+=" --$stem-cert $stem.crt"
363 fi
364 if not_upon "${has_no_key_cert[$stem]}"; then
365 common_args+=" --$stem-key-cert $stem-key.crt"
366 fi
367 done
368
369 # Create certificates
370 "$cert_create" $cert_args $common_args &>>"$build_log"
371
372 # Recreate and archive FIP
373 "$fiptool" create $common_args "fip.bin" &>>"$build_log"
374 archive_file "fip.bin"
375
376 popd
377 fi
378}
379
380# Update hw-config in FIP, and remove the original DTB afterwards.
381update_fip_hw_config() {
382 # The DTB needs to be loaded by the model (and not updated in the FIP)
383 # in configs where BL2 isn't present
384 case "1" in
385 "$(get_tf_opt RESET_TO_BL31)" | \
386 "$(get_tf_opt RESET_TO_SP_MIN)" | \
387 "$(get_tf_opt BL2_AT_EL3)")
388 return 0;;
389 esac
390
391 if bin_name="hw-config" src="$archive/dtb.bin" fip_update; then
392 # Remove the DTB so that model won't load it
393 rm -f "$archive/dtb.bin"
394 fi
395}
396
397get_scp_opt() {
398 (
399 name="${1:?}"
400 if config_valid "$scp_config_file"; then
401 source "$scp_config_file"
402 echo "${!name}"
403 fi
404 )
405}
406
407get_tftf_opt() {
408 (
409 name="${1:?}"
410 if config_valid "$tftf_config_file"; then
411 source "$tftf_config_file"
412 echo "${!name}"
413 fi
414 )
415}
416
417get_tf_opt() {
418 (
419 name="${1:?}"
420 if config_valid "$tf_config_file"; then
421 source "$tf_config_file"
422 echo "${!name}"
423 fi
424 )
425}
426
427build_tf() {
428 (
429 env_file="$workspace/tf.env"
430 config_file="${tf_build_config:-$tf_config_file}"
431
432 # Build fiptool and all targets by default
433 build_targets="${tf_build_targets:-fiptool all}"
434
435 source "$config_file"
436
437 # If it is a TBBR build, extract the MBED TLS library from archive
438 if [ "$(get_tf_opt TRUSTED_BOARD_BOOT)" = 1 ]; then
439 mbedtls_dir="$workspace/mbedtls"
440 if [ ! -d "$mbedtls_dir" ]; then
441 mbedtls_ar="$workspace/mbedtls.tar.gz"
442
443 url="$mbedtls_archive" saveas="$mbedtls_ar" fetch_file
444 mkdir "$mbedtls_dir"
Leonardo Sandovalec9e16c2020-09-09 14:32:40 -0500445 extract_tarball $mbedtls_ar $mbedtls_dir --strip-components=1
Fathi Boudra422bf772019-12-02 11:10:16 +0200446 fi
447
448 emit_env "MBEDTLS_DIR" "$mbedtls_dir"
449 fi
450
451 if [ -f "$env_file" ]; then
452 set -a
453 source "$env_file"
454 set +a
455 fi
456
457 cd "$tf_root"
458
459 # Always distclean when running on Jenkins. Skip distclean when running
460 # locally and explicitly requested.
461 if upon "$jenkins_run" || not_upon "$dont_clean"; then
462 make distclean &>>"$build_log" || fail_build
463 fi
464
465 # Log build command line. It is left unfolded on purpose to assist
466 # copying to clipboard.
467 cat <<EOF | log_separator >/dev/null
468
469Build command line:
470 $tf_build_wrapper make $make_j_opts $(cat "$config_file" | tr '\n' ' ') DEBUG=$DEBUG V=1 $build_targets
471
472EOF
473
474 # Build TF. Since build output is being directed to the build log, have
475 # descriptor 3 point to the current terminal for build wrappers to vent.
476 $tf_build_wrapper make $make_j_opts $(cat "$config_file") \
477 DEBUG="$DEBUG" V=1 \
478 $build_targets 3>&1 &>>"$build_log" || fail_build
479 )
480}
481
482build_tftf() {
483 (
484 config_file="${tftf_build_config:-$tftf_config_file}"
485
486 # Build tftf target by default
487 build_targets="${tftf_build_targets:-all}"
488
489 source "$config_file"
490
491 cd "$tftf_root"
492
493 # Always distclean when running on Jenkins. Skip distclean when running
494 # locally and explicitly requested.
495 if upon "$jenkins_run" || not_upon "$dont_clean"; then
496 make distclean &>>"$build_log" || fail_build
497 fi
498
499 # TFTF build system cannot reliably deal with -j option, so we avoid
500 # using that.
501
502 # Log build command line
503 cat <<EOF | log_separator >/dev/null
504
505Build command line:
506 make $(cat "$config_file" | tr '\n' ' ') DEBUG=$DEBUG V=1 $build_targets
507
508EOF
509
510 make $(cat "$config_file") DEBUG="$DEBUG" V=1 \
511 $build_targets &>>"$build_log" || fail_build
512 )
513}
514
515build_scp() {
516 (
517 config_file="${scp_build_config:-$scp_config_file}"
518
519 source "$config_file"
520
521 cd "$scp_root"
522
523 # Always distclean when running on Jenkins. Skip distclean when running
524 # locally and explicitly requested.
525 if upon "$jenkins_run" || not_upon "$dont_clean"; then
526 make clean &>>"$build_log" || fail_build
527 fi
528
529 # Log build command line. It is left unfolded on purpose to assist
530 # copying to clipboard.
531 cat <<EOF | log_separator >/dev/null
532
533SCP build command line:
534 make $(cat "$config_file" | tr '\n' ' ') MODE=$mode V=1
535
536EOF
537
538 # Build SCP
539 make $(cat "$config_file") MODE="$mode" V=1 &>>"$build_log" \
540 || fail_build
541 )
542}
543
Zelalem219df412020-05-17 19:21:20 -0500544clone_scp_tools() {
545
546 if [ ! -d "$scp_tools_root" ]; then
547 echo "Cloning SCP-tools ... $scp_tools_commit" |& log_separator
548
549 clone_url="${SCP_TOOLS_CHECKOUT_LOC:-$scp_tools_src_repo_url}" \
550 where="$scp_tools_root" \
551 refspec="${scp_tools_commit}"
552 clone_repo &>>"$build_log"
553 else
554 echo "Already cloned SCP-tools ..." |& log_separator
555 fi
556
557 show_head "$scp_tools_root"
558
559 cd "$scp_tools_root"
560
561 echo "Updating submodules"
562
563 git submodule init
564
565 git submodule update
566
567 cd "scmi"
568
569 git show --quiet --no-color | sed 's/^/ > /g'
570}
571
572clone_tf_for_scp_tools() {
573 scp_tools_arm_tf="$scp_tools_root/arm-tf"
574
575 if [ ! -d "$scp_tools_arm_tf" ]; then
576 echo "Cloning TF-4-SCP-tools ..." |& log_separator
577
578 clone_url="$tf_for_scp_tools_src_repo_url"
579 where="$scp_tools_arm_tf"
580
581 git clone "$clone_url" "$where"
582
583 cd "$scp_tools_arm_tf"
584
585 git checkout --track origin/dev/pedro/juno
586
587 git show --quiet --no-color | sed 's/^/ > /g'
588
589 else
590 echo "Already cloned TF-4-SCP-tools ..." |& log_separator
591 fi
592}
593
594build_scmi_lib_scp_tools() {
595 (
596 cd "$scp_tools_root"
597
598 cd "scmi"
599
600 scp_tools_arm_tf="$scp_tools_root/arm-tf"
601
602 cross_compile="/arm/pdsw/tools/gcc-linaro-6.2.1-2016.11-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-"
603
604 std_libs="-I$scp_tools_arm_tf/include/common"
605 std_libs="$std_libs -I$scp_tools_arm_tf/include/common/tbbr"
606 std_libs="$std_libs -I$scp_tools_arm_tf/include/drivers/arm"
607 std_libs="$std_libs -I$scp_tools_arm_tf/include/lib"
608 std_libs="$std_libs -I$scp_tools_arm_tf/include/lib/aarch64"
609 std_libs="$std_libs -I$scp_tools_arm_tf/include/lib/stdlib"
610 std_libs="$std_libs -I$scp_tools_arm_tf/include/lib/stdlib/sys"
611 std_libs="$std_libs -I$scp_tools_arm_tf/include/lib/xlat_tables"
612 std_libs="$std_libs -I$scp_tools_arm_tf/include/plat/common"
613 std_libs="$std_libs -I$scp_tools_arm_tf/include/plat/arm/common"
614 std_libs="$std_libs -I$scp_tools_arm_tf/include/plat/arm/css/common"
615 std_libs="$std_libs -I$scp_tools_arm_tf/include/plat/arm/board/common"
616 std_libs="$std_libs -I$scp_tools_arm_tf/include/plat/arm/soc/common"
617 std_libs="$std_libs -I$scp_tools_arm_tf/plat/arm/board/juno/include"
618
619 cflags="-Og -g"
620 cflags="$cflags -mgeneral-regs-only"
621 cflags="$cflags -mstrict-align"
622 cflags="$cflags -nostdinc"
623 cflags="$cflags -fno-inline"
624 cflags="$cflags -ffreestanding"
625 cflags="$cflags -ffunction-sections"
626 cflags="$cflags -fdata-sections"
627 cflags="$cflags -DAARCH64"
628 cflags="$cflags -DPRId32=\"ld\""
629
630 cflags="$cflags $std_libs"
631
632 protocols="power,system_power,performance,sensor"
633
634 echo "Building SCMI library (SCP-tools) ..."
635
636 make "CROSS_COMPILE=$cross_compile" \
637 "CFLAGS=$cflags" \
638 "PROTOCOLS=$protocols" \
639 "clean" \
640 "all"
641 )
642}
643
644build_tf_for_scp_tools() {
645
646 cd "$scp_tools_root/arm-tf"
647
648 cross_compile="/arm/pdsw/tools/gcc-linaro-6.2.1-2016.11-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-"
649
650 if [ "$1" = "release" ]; then
651 echo "Build TF-4-SCP-Tools rls..."
652 else
653 echo "Build TF-4-SCP-Tools dbg..."
654
655 make realclean
656
657 make "BM_TEST=scmi" \
658 "ARM_BOARD_OPTIMISE_MEM=1" \
659 "BM_CSS=juno" \
660 "CSS_USE_SCMI_SDS_DRIVER=1" \
661 "PLAT=juno" \
662 "DEBUG=1" \
663 "PLATFORM=juno" \
664 "CROSS_COMPILE=$cross_compile" \
665 "BM_WORKSPACE=$scp_tools_root/baremetal"
666
667 archive_file "build/juno/debug/bl1.bin"
668
669 archive_file "build/juno/debug/bl2.bin"
670
671 archive_file "build/juno/debug/bl31.bin"
672 fi
673}
674
675build_fip_for_scp_tools() {
676
677 cd "$scp_tools_root/arm-tf"
678
679 cross_compile="/arm/pdsw/tools/gcc-linaro-6.2.1-2016.11-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-"
680
681 if [ ! -d "$scp_root/build/product/juno/scp_ramfw/debug" ]; then
682 make fiptool
683 echo "Make FIP 4 SCP-Tools rls..."
684
685 else
686 make fiptool
687 echo "Make FIP 4 SCP-Tools dbg..."
688
689 make "PLAT=juno" \
690 "all" \
691 "fip" \
692 "DEBUG=1" \
693 "CROSS_COMPILE=$cross_compile" \
694 "BL31=$scp_tools_root/arm-tf/build/juno/debug/bl31.bin" \
695 "BL33=$scp_tools_root/baremetal/dummy_bl33" \
696 "SCP_BL2=$scp_root/build/product/juno/scp_ramfw/debug/bin/firmware.bin"
697
698 archive_file "$scp_tools_root/arm-tf/build/juno/debug/fip.bin"
699 fi
700}
701
702build_cc() {
703# Building code coverage plugin
704 ARM_DIR=/arm
705 pvlibversion=$(/arm/devsys-tools/abs/detag "SysGen:PVModelLib:$model_version::trunk")
706 PVLIB_HOME=$warehouse/SysGen/PVModelLib/$model_version/${pvlibversion}/external
707 if [ -n "$(find "$ARM_DIR" -maxdepth 0 -type d -empty 2>/dev/null)" ]; then
708 echo "Error: Arm warehouse not mounted. Please mount the Arm warehouse to your /arm local folder"
709 exit -1
710 fi # Error if arm warehouse not found
711 cd "$ccpathspec/scripts/tools/code_coverage/fastmodel_baremetal/bmcov"
712
713 make -C model-plugin PVLIB_HOME=$PVLIB_HOME &>>"$build_log"
714}
715
716
Fathi Boudra422bf772019-12-02 11:10:16 +0200717# Set metadata for the whole package so that it can be used by both Jenkins and
718# shell
719set_package_var() {
720 env_file="$artefacts/env" emit_env "$@"
721}
722
723set_tf_build_targets() {
724 echo "Set build target to '${targets:?}'"
725 set_hook_var "tf_build_targets" "$targets"
726}
727
728set_tftf_build_targets() {
729 echo "Set build target to '${targets:?}'"
730 set_hook_var "tftf_build_targets" "$targets"
731}
732
733set_scp_build_targets() {
734 echo "Set build target to '${targets:?}'"
735 set_hook_var "scp_build_targets" "$targets"
736}
737
738# Look under $archive directory for known files such as blX images, kernel, DTB,
739# initrd etc. For each known file foo, if foo.bin exists, then set variable
740# foo_bin to the path of the file. Make the path relative to the workspace so as
741# to remove any @ characters, which Jenkins inserts for parallel runs. If the
742# file doesn't exist, unset its path.
743set_default_bin_paths() {
744 local image image_name image_path path
745 local archive="${archive:?}"
746 local set_vars
747 local var
748
749 pushd "$archive"
750
751 for file in *.bin; do
752 # Get a shell variable from the file's stem
753 var_name="${file%%.*}_bin"
754 var_name="$(echo "$var_name" | sed -r 's/[^[:alnum:]]/_/g')"
755
756 # Skip setting the variable if it's already
757 if [ "${!var_name}" ]; then
758 echo "Note: not setting $var_name; already set to ${!var_name}"
759 continue
760 else
761 set_vars+="$var_name "
762 fi
763
764 eval "$var_name=$file"
765 done
766
767 echo "Binary paths set for: "
768 {
769 for var in $set_vars; do
770 echo -n "\$$var "
771 done
772 } | fmt -80 | sed 's/^/ /'
773 echo
774
775 popd
776}
777
778gen_model_params() {
779 local model_param_file="$archive/model_params"
780
781 set_default_bin_paths
782 echo "Generating model parameter for $model..."
783 source "$ci_root/model/${model:?}.sh"
784 archive_file "$model_param_file"
785}
786
787set_model_path() {
788 set_run_env "model_path" "${1:?}"
789}
790
Zelalem1af7a7b2020-08-04 17:34:32 -0500791set_model_env() {
792 local var="${1:?}"
793 local val="${2?}"
794 local run_root="${archive:?}/run"
795
796 mkdir -p "$run_root"
797 echo "export $var=$val" >> "$run_root/model_env"
798}
Fathi Boudra422bf772019-12-02 11:10:16 +0200799set_run_env() {
800 local var="${1:?}"
801 local val="${2?}"
802 local run_root="${archive:?}/run"
803
804 mkdir -p "$run_root"
805 env_file="$run_root/env" quote="1" emit_env "$var" "$val"
806}
807
808show_head() {
809 # Display HEAD descripton
810 pushd "$1"
811 git show --quiet --no-color | sed 's/^/ > /g'
812 echo
813 popd
814}
815
816# Choose debug binaries to run; by default, release binaries are chosen to run
817use_debug_bins() {
818 local run_root="${archive:?}/run"
819
820 echo "Choosing debug binaries for execution"
821 set_package_var "BIN_MODE" "debug"
822}
823
824assert_can_git_clone() {
825 local name="${1:?}"
826 local dir="${!name}"
827
828 # If it doesn't exist, it can be cloned into
829 if [ ! -e "$dir" ]; then
830 return 0
831 fi
832
833 # If it's a directory, it must be a Git clone already
834 if [ -d "$dir" ] && [ -d "$dir/.git" ]; then
835 # No need to clone again
836 echo "Using existing git clone for $name: $dir"
837 return 1
838 fi
839
840 die "Path $dir exists but is not a git clone"
841}
842
843clone_repo() {
844 if ! is_url "${clone_url?}"; then
845 # For --depth to take effect on local paths, it needs to use the
846 # file:// scheme.
847 clone_url="file://$clone_url"
848 fi
849
850 git clone -q --depth 1 "$clone_url" "${where?}"
851 if [ "$refspec" ]; then
852 pushd "$where"
853 git fetch -q --depth 1 origin "$refspec"
854 git checkout -q FETCH_HEAD
855 popd
856 fi
857}
858
859build_unstable() {
860 echo "--BUILD UNSTABLE--" | tee -a "$build_log"
861}
862
863undo_patch_record() {
864 if [ ! -f "${patch_record:?}" ]; then
865 return
866 fi
867
868 # Undo patches in reverse
869 echo
870 for patch_name in $(tac "$patch_record"); do
871 echo "Undoing $patch_name..."
872 if ! git apply -R "$ci_root/patch/$patch_name"; then
873 if upon "$local_ci"; then
874 echo
875 echo "Your local directory may have been dirtied."
876 echo
877 fi
878 fail_build
879 fi
880 done
881
882 rm -f "$patch_record"
883}
884
885undo_local_patches() {
886 pushd "$tf_root"
887 patch_record="$tf_patch_record" undo_patch_record
888 popd
889
890 if [ -d "$tftf_root" ]; then
891 pushd "$tftf_root"
892 patch_record="$tftf_patch_record" undo_patch_record
893 popd
894 fi
895}
896
897undo_tftf_patches() {
898 pushd "$tftf_root"
899 patch_record="$tftf_patch_record" undo_patch_record
900 popd
901}
902
903undo_tf_patches() {
904 pushd "$tf_root"
905 patch_record="$tf_patch_record" undo_patch_record
906 popd
907}
908
909apply_patch() {
910 # If skip_patches is set, the developer has applied required patches
911 # manually. They probably want to keep them applied for debugging
912 # purposes too. This means we don't have to apply/revert them as part of
913 # build process.
914 if upon "$skip_patches"; then
915 echo "Skipped applying ${1:?}..."
916 return 0
917 else
918 echo "Applying ${1:?}..."
919 fi
920
921 if git apply < "$ci_root/patch/$1"; then
922 echo "$1" >> "${patch_record:?}"
923 else
924 if upon "$local_ci"; then
925 undo_local_patches
926 fi
927 fail_build
928 fi
929}
930
931apply_tftf_patch() {
932 pushd "$tftf_root"
933 patch_record="$tftf_patch_record" apply_patch "$1"
934 popd
935}
936
937apply_tf_patch() {
938 pushd "$tf_root"
939 patch_record="$tf_patch_record" apply_patch "$1"
940 popd
941}
942
943# Clear workspace for a local run
944if not_upon "$jenkins_run"; then
945 rm -rf "$workspace"
946
947 # Clear residue from previous runs
948 rm -rf "$archive"
949fi
950
951mkdir -p "$workspace"
952mkdir -p "$archive"
953set_package_var "TEST_CONFIG" "$test_config"
954
955{
956echo
957echo "CONFIGURATION: $test_group/$test_config"
958echo
959} |& log_separator
960
961tf_config="$(echo "$build_configs" | awk -F, '{print $1}')"
962tftf_config="$(echo "$build_configs" | awk -F, '{print $2}')"
963scp_config="$(echo "$build_configs" | awk -F, '{print $3}')"
Zelalem219df412020-05-17 19:21:20 -0500964scp_tools_config="$(echo "$build_configs" | awk -F, '{print $4}')"
Fathi Boudra422bf772019-12-02 11:10:16 +0200965
966test_config_file="$ci_root/group/$test_group/$test_config"
967
968tf_config_file="$ci_root/tf_config/$tf_config"
969tftf_config_file="$ci_root/tftf_config/$tftf_config"
970scp_config_file="$ci_root/scp_config/$scp_config"
Zelalem219df412020-05-17 19:21:20 -0500971scp_tools_config_file="$ci_root/scp_tools_config/$scp_tools_config"
Fathi Boudra422bf772019-12-02 11:10:16 +0200972
973# File that keeps track of applied patches
974tf_patch_record="$workspace/tf_patches"
975tftf_patch_record="$workspace/tftf_patches"
976
977pushd "$workspace"
978
979if ! config_valid "$tf_config"; then
980 tf_config=
981else
982 echo "Trusted Firmware config:"
983 echo
984 sort "$tf_config_file" | sed '/^\s*$/d;s/^/\t/'
985 echo
986fi
987
988if ! config_valid "$tftf_config"; then
989 tftf_config=
990else
991 echo "Trusted Firmware TF config:"
992 echo
993 sort "$tftf_config_file" | sed '/^\s*$/d;s/^/\t/'
994 echo
995fi
996
997if ! config_valid "$scp_config"; then
998 scp_config=
999else
1000 echo "SCP firmware config:"
1001 echo
1002 sort "$scp_config_file" | sed '/^\s*$/d;s/^/\t/'
1003 echo
1004fi
1005
Zelalem219df412020-05-17 19:21:20 -05001006if ! config_valid "$scp_tools_config"; then
1007 scp_tools_config=
1008else
1009 echo "SCP Tools config:"
1010 echo
1011 sort "$scp_tools_config_file" | sed '/^\s*$/d;s/^/\t/'
1012 echo
1013fi
1014
Fathi Boudra422bf772019-12-02 11:10:16 +02001015if ! config_valid "$run_config"; then
1016 run_config=
1017fi
1018
1019if [ "$tf_config" ] && assert_can_git_clone "tf_root"; then
1020 # If the Trusted Firmware repository has already been checked out, use
1021 # that location. Otherwise, clone one ourselves.
1022 echo "Cloning Trusted Firmware..."
1023 clone_url="${TF_CHECKOUT_LOC:-$tf_src_repo_url}" where="$tf_root" \
1024 refspec="$TF_REFSPEC" clone_repo &>>"$build_log"
1025 show_head "$tf_root"
1026fi
1027
1028if [ "$tftf_config" ] && assert_can_git_clone "tftf_root"; then
1029 # If the Trusted Firmware TF repository has already been checked out,
1030 # use that location. Otherwise, clone one ourselves.
1031 echo "Cloning Trusted Firmware TF..."
1032 clone_url="${TFTF_CHECKOUT_LOC:-$tftf_src_repo_url}" where="$tftf_root" \
1033 refspec="$TFTF_REFSPEC" clone_repo &>>"$build_log"
1034 show_head "$tftf_root"
1035fi
1036
1037if [ "$scp_config" ] && assert_can_git_clone "scp_root"; then
1038 # If the SCP firmware repository has already been checked out,
1039 # use that location. Otherwise, clone one ourselves.
1040 echo "Cloning SCP Firmware..."
1041 clone_url="${SCP_CHECKOUT_LOC:-$scp_src_repo_url}" where="$scp_root" \
1042 refspec="${SCP_REFSPEC-master-upstream}" clone_repo &>>"$build_log"
1043
1044 pushd "$scp_root"
1045
1046 # Use filer submodule as a reference if it exists
1047 if [ -d "$SCP_CHECKOUT_LOC/cmsis" ]; then
1048 cmsis_reference="--reference $SCP_CHECKOUT_LOC/cmsis"
1049 fi
1050
1051 # If we don't have a reference yet, fall back to $cmsis_root if set, or
1052 # then to project filer if accessible.
1053 if [ -z "$cmsis_reference" ]; then
1054 cmsis_ref_repo="${cmsis_root:-$project_filer/ref-repos/cmsis}"
1055 if [ -d "$cmsis_ref_repo" ]; then
1056 cmsis_reference="--reference $cmsis_ref_repo"
1057 fi
1058 fi
1059
1060 git submodule -q update $cmsis_reference --init
1061
1062 popd
1063
1064 show_head "$scp_root"
1065fi
1066
Zelalem219df412020-05-17 19:21:20 -05001067if [ -n "$cc_config" ] ; then
1068 if [ "$cc_config" -eq 1 ] && assert_can_git_clone "cc_root"; then
1069 # Copy code coverage repository
1070 echo "Cloning Code Coverage..."
1071 git clone -q $cc_src_repo_url cc_plugin --depth 1 -b $cc_src_repo_tag > /dev/null
1072 show_head "$cc_root"
1073 fi
1074fi
1075
Fathi Boudra422bf772019-12-02 11:10:16 +02001076if [ "$run_config" ]; then
1077 # Get candidates for run config
1078 run_config_candiates="$("$ci_root/script/gen_run_config_candidates.py" \
1079 "$run_config")"
1080 if [ -z "$run_config_candiates" ]; then
1081 die "No run config candidates!"
1082 else
1083 echo
1084 echo "Chosen fragments:"
1085 echo
1086 echo "$run_config_candiates" | sed 's/^\|\n/\t/g'
1087 echo
1088 fi
1089fi
1090
1091call_hook "test_setup"
1092echo
1093
1094if upon "$local_ci"; then
1095 # For local runs, since each config is tried in sequence, it's
1096 # advantageous to run jobs in parallel
1097 if [ "$make_j" ]; then
1098 make_j_opts="-j $make_j"
1099 else
1100 n_cores="$(getconf _NPROCESSORS_ONLN)" 2>/dev/null || true
1101 if [ "$n_cores" ]; then
1102 make_j_opts="-j $n_cores"
1103 fi
1104 fi
1105fi
1106
1107modes="${bin_mode:-debug release}"
1108for mode in $modes; do
1109 # Build with a temporary archive
1110 build_archive="$archive/$mode"
1111 mkdir "$build_archive"
1112
1113 if [ "$mode" = "debug" ]; then
Zelalem219df412020-05-17 19:21:20 -05001114 export bin_mode="debug"
Fathi Boudra422bf772019-12-02 11:10:16 +02001115 DEBUG=1
1116 else
Zelalem219df412020-05-17 19:21:20 -05001117 export bin_mode="release"
Fathi Boudra422bf772019-12-02 11:10:16 +02001118 DEBUG=0
1119 fi
1120
1121 # Perform builds in a subshell so as not to pollute the current and
1122 # subsequent builds' environment
1123
Zelalem219df412020-05-17 19:21:20 -05001124 if config_valid "$cc_config"; then
1125 # Build code coverage plugin
1126 build_cc
1127 fi
1128
Fathi Boudra422bf772019-12-02 11:10:16 +02001129 # SCP build
1130 if config_valid "$scp_config"; then
1131 (
1132 echo "##########"
1133
1134 # Source platform-specific utilities
1135 plat="$(get_scp_opt PRODUCT)"
1136 plat_utils="$ci_root/${plat}_utils.sh"
1137 if [ -f "$plat_utils" ]; then
1138 source "$plat_utils"
1139 fi
1140
1141 archive="$build_archive"
1142 scp_build_root="$scp_root/build"
1143
1144 echo "Building SCP Firmware ($mode) ..." |& log_separator
1145
1146 build_scp
Fathi Boudra422bf772019-12-02 11:10:16 +02001147 to="$archive" collect_scp_artefacts
1148
1149 echo "##########"
1150 echo
1151 )
1152 fi
1153
Zelalem219df412020-05-17 19:21:20 -05001154 # SCP-tools build
1155 if config_valid "$scp_tools_config"; then
1156 (
1157 echo "##########"
1158
1159 archive="$build_archive"
1160 scp_tools_build_root="$scp_tools_root/build"
1161
1162 clone_scp_tools
1163
1164 echo "##########"
1165 echo
1166
1167 echo "##########"
1168 clone_tf_for_scp_tools
1169 echo "##########"
1170 echo
1171 )
1172 fi
1173
Fathi Boudra422bf772019-12-02 11:10:16 +02001174 # TFTF build
1175 if config_valid "$tftf_config"; then
1176 (
1177 echo "##########"
1178
1179 # Source platform-specific utilities
1180 plat="$(get_tftf_opt PLAT)"
1181 plat_utils="$ci_root/${plat}_utils.sh"
1182 if [ -f "$plat_utils" ]; then
1183 source "$plat_utils"
1184 fi
1185
1186 archive="$build_archive"
1187 tftf_build_root="$tftf_root/build"
1188
1189 echo "Building Trusted Firmware TF ($mode) ..." |& log_separator
1190
1191 # Call pre-build hook
1192 call_hook pre_tftf_build
1193
1194 build_tftf
1195
1196 from="$tftf_build_root" to="$archive" collect_build_artefacts
1197
1198 # Clear any local changes made by applied patches
1199 undo_tftf_patches
1200
1201 echo "##########"
1202 echo
1203 )
1204 fi
1205
1206 # TF build
1207 if config_valid "$tf_config"; then
1208 (
1209 echo "##########"
1210
1211 # Source platform-specific utilities
1212 plat="$(get_tf_opt PLAT)"
1213 plat_utils="$ci_root/${plat}_utils.sh"
1214 if [ -f "$plat_utils" ]; then
1215 source "$plat_utils"
1216 fi
1217
1218 archive="$build_archive"
1219 tf_build_root="$tf_root/build"
1220
1221 echo "Building Trusted Firmware ($mode) ..." |& log_separator
1222
1223 # Call pre-build hook
1224 call_hook pre_tf_build
1225
1226 build_tf
1227
1228 # Call post-build hook
1229 call_hook post_tf_build
1230
1231 # Pre-archive hook
1232 call_hook pre_tf_archive
1233
1234 from="$tf_build_root" to="$archive" collect_build_artefacts
1235
1236 # Post-archive hook
1237 call_hook post_tf_archive
1238
1239 call_hook fetch_tf_resource
1240 call_hook post_fetch_tf_resource
1241
1242 # Clear any local changes made by applied patches
1243 undo_tf_patches
1244
1245 echo "##########"
1246 )
1247 fi
1248
1249 echo
1250 echo
1251done
1252
1253call_hook pre_package
1254
1255call_hook post_package
1256
1257if upon "$jenkins_run" && upon "$artefacts_receiver" && [ -d "artefacts" ]; then
Zelalem219df412020-05-17 19:21:20 -05001258 source "$CI_ROOT/script/send_artefacts.sh" "artefacts"
Fathi Boudra422bf772019-12-02 11:10:16 +02001259fi
1260
1261echo
1262echo "Done"