1#!/usr/bin/env bash
2# Copyright 2019 The Hafnium Authors.
3#
4# Use of this source code is governed by a BSD-style
5# license that can be found in the LICENSE file or at
6# https://opensource.org/licenses/BSD-3-Clause.
7
8set -euo pipefail
9
10SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11ROOT_DIR="$(dirname ${SCRIPT_DIR})"
12
13source "${SCRIPT_DIR}/docker/common.inc"
14
15if [ "${HAFNIUM_HERMETIC_BUILD:-}" == "inside" ]
16then
17	echo "ERROR: Invoked $0 recursively" 1>&2
18	exit 1
19fi
20
21# Set up a temp directory and register a cleanup function on exit.
22TMP_DIR="$(mktemp -d)"
23function cleanup() {
24	rm -rf "${TMP_DIR}"
25}
26trap cleanup EXIT
27
28# Build local image and write its hash to a temporary file.
29IID_FILE="${TMP_DIR}/imgid.txt"
30"${DOCKER}" build \
31	--build-arg LOCAL_UID="$(id -u)" \
32	--build-arg LOCAL_GID="$(id -g)" \
33	--iidfile="${IID_FILE}" \
34	-f "${SCRIPT_DIR}/docker/Dockerfile" \
35	"${SCRIPT_DIR}/docker"
36IMAGE_ID="$(cat ${IID_FILE})"
37
38# Parse command line arguments
39INTERACTIVE=false
40ALLOW_PTRACE=false
41TTY=true
42while true
43do
44	case "${1:-}" in
45	--tty)
46	 	TTY=${2:-}
47		shift; shift
48		;;
49	-i)
50		INTERACTIVE=true
51		shift
52		;;
53	-p)
54		ALLOW_PTRACE=true
55		shift
56		;;
57	-*)
58		echo "ERROR: Unknown command line flag: $1" 1>&2
59		echo "Usage: $0 [-i] [-p] [--tty true|false] <command>"
60		exit 1
61		;;
62	*)
63		break
64		;;
65	esac
66done
67
68ARGS=()
69# Run with a pseduo-TTY for nicer logging.
70ARGS+=(--tty=${TTY})
71# Run interactive if this script was invoked with '-i'.
72if [ "${INTERACTIVE}" == "true" ]
73then
74	ARGS+=(-i)
75fi
76# Allow ptrace() syscall if invoked with '-p'.
77if [ "${ALLOW_PTRACE}" == "true" ]
78then
79	echo "WARNING: Docker seccomp profile is disabled!" 1>&2
80	ARGS+=(--cap-add=SYS_PTRACE --security-opt seccomp=unconfined)
81fi
82
83if [ -z "${HAFNIUM_FVP-}" ]
84then
85	HAFNIUM_FVP_DIR="${ROOT_DIR}/../fvp"
86else
87	HAFNIUM_FVP_DIR=$(dirname "$HAFNIUM_FVP")
88fi
89
90echo "Using FVP in: ${HAFNIUM_FVP_DIR}"
91
92# Propagate "HAFNIUM_*" environment variables.
93# Note: Cannot use `env | while` because the loop would run inside a child
94# process and would not have any effect on variables in the parent.
95while read -r ENV_LINE
96do
97	VAR_NAME="$(echo ${ENV_LINE} | cut -d= -f1)"
98	case "${VAR_NAME}" in
99	HAFNIUM_HERMETIC_BUILD)
100		# Skip this one. It will be overridden below.
101		;;
102	HAFNIUM_*)
103		ARGS+=(-e "${ENV_LINE}")
104		;;
105	esac
106done <<< "$(env)"
107
108# Forward PLATFORM to ensure it's preserved inside the container.
109if [ -n "${PLATFORM:-}" ]; then
110    ARGS+=(-e "PLATFORM=${PLATFORM}")
111fi
112# Set environment variable informing the build that we are running inside
113# a container.
114ARGS+=(-e HAFNIUM_HERMETIC_BUILD=inside)
115# Bind-mount the Hafnium root directory and the FVP directory. We mount them at
116# the same absolute location so that all paths match across the host and guest.
117ARGS+=(-v "${ROOT_DIR}":"${ROOT_DIR}")
118ARGS+=(-v "${HAFNIUM_FVP_DIR}":"${HAFNIUM_FVP_DIR}")
119
120# Mount TF-A and TF-A-Tests source directories for use in shrinkwrap
121# Allow overriding via environment variables.
122TFA_DIR="${TFA_DIR:-${ROOT_DIR}/../trusted-firmware-a}"
123TFTF_DIR="${TFTF_DIR:-${ROOT_DIR}/../tf-a-tests}"
124
125# Note:
126# By default, this setup assumes that TF-A and TF-A-Tests repositories are checked
127# out in directories adjacent to the Hafnium source tree.
128# You can override these paths by setting TFA_DIR and TFTF_DIR environment variables.
129ARGS+=(-v "${TFA_DIR}:${TFA_DIR}")
130ARGS+=(-v "${TFTF_DIR}:${TFTF_DIR}")
131
132# Make all files outside of the Hafnium directory read-only to ensure that all
133# generated files are written there.
134ARGS+=(--read-only)
135# Mount a writable /tmp folder. Required by LLVM/Clang for intermediate files.
136ARGS+=(--tmpfs /tmp)
137# Set working directory.
138ARGS+=(-w "${ROOT_DIR}")
139
140# Initialize Shrinkwrap environment before running the user-provided command
141# inside the container.
142echo "Running in container: $*" 1>&2
143
144# NOTE:
145# shrinkwrap_setup_env.sh is sourced here at runtime (not configured within the Dockerfile)
146# because it depends on host-mounted Hafnium repo paths that are only available
147# when the container is launched. This approach ensures compatibility with
148# the Hafnium developer Docker environment under build/docker/.
149CMD="export PATH=${HAFNIUM_FVP_DIR}/Base_RevC_AEMvA_pkg/models/Linux64_GCC-9.3:\$PATH && \
150     source tools/shrinkwrap/shrinkwrap_setup_env.sh && \
151     bash -c \"$*\""
152${DOCKER} run \
153    "${ARGS[@]}" \
154    "${IMAGE_ID}" \
155    /bin/bash -c "$CMD"
156