aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Bonnici <marc.bonnici@arm.com>2020-09-17 11:59:35 +0100
committerMarc Bonnici <marc.bonnici@arm.com>2020-09-25 15:04:41 +0100
commitf4ac0e63b997a7e58c420fa7fd0c897de9503154 (patch)
tree0fa40c0d71ab9ae87588f76d750d6080ff98ebf7
parente67a8d2365227eed1c8658088433f782518e08d5 (diff)
downloadtrusted-firmware-a-f4ac0e63b997a7e58c420fa7fd0c897de9503154.tar.gz
Add build script and README for prototype
Adds a PROTOTYPE_README detailing the required environment and a `multi_build.sh` script to build/run the prototype. The script is able to run the prototype both with and without EL-2 enabled in the normal and secure world independently. For more usage information please consult the README or invoke the script with `--help`. Change-Id: Id489ad943399ff1da8976553f9d1318b3be6e4b5
-rw-r--r--PROTOTYPE_README166
-rwxr-xr-xmulti_build.sh617
2 files changed, 783 insertions, 0 deletions
diff --git a/PROTOTYPE_README b/PROTOTYPE_README
new file mode 100644
index 0000000000..1947a59c84
--- /dev/null
+++ b/PROTOTYPE_README
@@ -0,0 +1,166 @@
+--------------------------------------------------------------------------
+Disclaimer: This branch contains prototype code which is for demonstrative
+purposes only and to serve as proof of concept. It is designed to allow
+prototyping of new features and any productization paths if taken
+forward would be delivered through the master branch.
+--------------------------------------------------------------------------
+
+Getting Started
+---------------
+
+These instructions will help to recreate the FF-A prototype. This end goal is to
+run the OP-TEE xtest suite on linux from the normal world, with OP-TEE running
+in the secure world. Optionally Hafnium can be used as the hypervisor in the
+Normal world and/or the SPM in the secure world which is configurable via
+arguments passed to the build script provided.
+
+
+Steps to clone the relevant repos
+---------------------------------
+
+Note: These set of instructions assume you have a "Base Directory" where the
+multi_build.sh script has been copied to and will be the parent directory to
+the required repository checkouts. Please see the final repo structure below.
+
+BASE_DIR=$(pwd)
+
+# Clone Hafnium:
+git clone $HAFNIUM_FFA_REL_PROTO_REPO hafnium
+cd $BASE_DIR/hafnium
+git checkout $HAFNIUM_FFA_REL_PROTO_BRANCH
+
+cd $BASE_DIR/hafnium/project/
+git clone $HF_PROJECT_REFERENCE_FFA_REL_PROTO_REPO reference
+cd reference
+git checkout $HF_PROJECT_REFERENCE_FFA_REL_PROTO_BRANCH
+cd $BASE_DIR/hafnium/
+
+# Initialise remaining submodules
+git submodule update --init prebuilts
+git submodule update --init third_party/googletest
+git submodule update --init third_party/dtc
+git submodule update --init third_party/linux
+cd $BASE_DIR
+
+
+# Clone ATF:
+git clone $ATF_FFA_REL_PROTO_REPO arm-trusted-firmware
+cd $BASE_DIR/arm-trusted-firmware
+git checkout $ATF_FFA_REL_PROTO_BRANCH
+cd $BASE_DIR/
+
+# Clone OP-TEE OS
+git clone $OPTEE_FFA_REL_PROTO_REPO optee_os
+cd $BASE_DIR/optee_os
+git checkout $OPTEE_FFA_REL_PROTO_BRANCH
+cd $BASE_DIR
+
+# Clone Linux Kernel
+git clone $LINUX_FFA_REL_PROTO_REPO linux_kernel
+cd $BASE_DIR/linux_kernel
+git checkout $LINUX_FFA_REL_PROTO_BRANCH
+cd $BASE_DIR
+
+
+Download FVP
+------------
+
+Download Armv8-A Base RevC AEM FVP from:
+https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms/arm-ecosystem-models
+
+Extract into the `fvp` directory (the final file path should be
+$BASE_DIR/fvp/Base_RevC_AEMv8A_pkg/...)
+
+
+Prebuilts
+---------
+
+The script requires toolchains and prebuilt images that are reused from the
+OP-TEE build system. The script can automatically pull and build a full checkout
+of the OP-TEE build system with the `-e` option.
+
+To source a set of required pre-builts, either the script can pull the required
+files by providing it a file path to a full OP-TEE build with `-E <dir>`
+otherwise please populate the following directories:
+
+Required pre-builts to be placed in `prebuilts` directory with the following
+names.
+
+ - optee_rd.img (rootfs.cpio.gz from OP_TEE build)
+
+ - FVP_AARCH64_EFI.fd (from OP-TEE Build)
+
+ - boot-fat.uefi.img (from OP-TEE, required if running without EL2)
+
+Toolchains from OP-TEE to be placed in `toolchains` directory (or specified with
+`-T <dir>`)
+
+ - aarch32/...
+ - aarch64/...
+
+
+ Final Repo Structure
+--------------------
+
+.
+├── arm-trusted-firmware
+├── fvp
+│ └── Base_RevC_AEMv8A_pkg
+├── hafnium
+│ ├── ...
+│ └── project
+│ └── reference
+├── linux_kernel
+├── multi_build.sh
+├── optee_os
+├── prebuilts
+│ ├── optee_rd.img
+│ ├── FVP_AARCH64_EFI.fd
+│ └── boot-fat.uefi.img
+└── toolchains
+ ├── aarch32
+ └── aarch64
+
+
+Running the Prototype
+---------------------
+
+Subsequent common run commands are as follows:
+
+./multi_build.sh -y 1 -Y 1 # Build the prototype with EL2 and S-EL2 enabled.
+
+By default the script will build the required repositories and launch the FVP.
+
+This should drop into a shell which can be logged in with the username: `root`.
+From here you can run the entire xtest suite with the command `xtest` or a
+specific test with xtest <test_num>.
+
++------------------+--------------------------------------------------------+
+| Common Arguments | Description |
++------------------+--------------------------------------------------------+
+| -y 0 -Y 0 | Build and run the prototype, use the arguments, `-y X` |
+| | and `-Y X` to indicate the presence of a hypervisor |
+| | in the normal and secure world respectively. |
++------------------+--------------------------------------------------------+
+| -m | Run with 8 CPUs instead of the default single core |
+| | mode (configured via dtb). |
++------------------+--------------------------------------------------------+
+| -k | Re-build the linux kernel, to save time this is not |
+| | performed by default. |
++------------------+--------------------------------------------------------+
+| -B | Build only mode, perform the usual compilation but |
+| | without running the FVP. |
++------------------+--------------------------------------------------------+
+| -r | Run only, launch the FVP with existing files. |
++------------------+--------------------------------------------------------+
+| -d | Launch the FVP and instruct it to wait to connect |
+| | to a debugger. |
++------------------+--------------------------------------------------------+
+| -x | Don't launch the xterm windows and instead wait for |
+| | connection via telnet. |
++------------------+--------------------------------------------------------+
+| -X | Don't launch the xterm windows and automatically use |
+| | tmux to connect via telnet. |
++------------------+--------------------------------------------------------+
+
+*Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.* \ No newline at end of file
diff --git a/multi_build.sh b/multi_build.sh
new file mode 100755
index 0000000000..8b1efcfa51
--- /dev/null
+++ b/multi_build.sh
@@ -0,0 +1,617 @@
+#!/bin/bash
+#
+# Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+
+set -e
+set +x
+
+# Define known paths
+BASE_DIR=$(pwd)
+MODEL_DIR=$BASE_DIR/fvp/Base_RevC_AEMv8A_pkg/models/Linux64_GCC-6.4/
+OUT=$BASE_DIR/out
+TOOL_CHAINS_DIR=$BASE_DIR/toolchains
+
+PREBUILTS_DIR=${BASE_DIR}/prebuilts
+
+USAGE="$(basename "$0") - A build script to compile and run OP-TEE xtests on FVP prototype using FF-A.
+
+The following parameters are valid:
+ -e Rebuild the entire OP-TEE checkout, used to update the ramdisk.
+ -d Specify the FVP should wait for a debugger to connect before booting
+ -h Show this help
+ -j <num> Specify the number of threads to uses. Defaults to max available on system.
+ -k Specify to rebuild the linux kernel. Not performed by default to reduce time overhead.
+ -s Single core platform simulation (default uses 8 core declared in the dtb).
+ -r Do not recompile, only run FVP with existing files
+
+ # Directory Parameters
+ -A <ATF_dir> Specify the path to your ATF directory. Defaults to '$BASE_DIR/arm-trusted-firmware'
+ -H <*.bin|directory> BL33 image to use. Can be either a prebuilt bin image for BL33 or a hafnium directory to build. Defaults to '$BASE_DIR/hafnium'
+ -O <optee_os_dir> Specify the path to your optee_os directory. Defaults to '$BASE_DIR/optee_os'
+ -E <optee_checkout> Specify a path to a full optee checkout, used for rebuilding the ramdisk. Defaults to '$BASE_DIR/optee_full'
+ -L <linux_dir> Specify the path to your linux directory. Defaults to '$BASE_DIR/linux_kernel'
+ -T <toolchains_dir> Specify path to OP-TEE toolchains directory. Defauls to '$BASE_DIR/toolchains'
+
+ # Development Options
+ -B Build only mode, do not run the FVP after compilation
+ -C Enable cache state modeling
+ -c Clean each repository before building.
+ -v Verbose mode for build script
+ -x Disable the xterm display of uart outputs, allowing for use via telnet connections.
+ -X Use tmux to auto connect to telnet connections for uart outputs.
+"
+
+MULTI_CORE_DTB=1
+RUN_ONLY=0
+BUILD_ONLY=0
+DEBUG=0
+RESET=
+CLEAN=0
+CACHE_STATE=0
+NO_CPUS=$(nproc)
+KERNEL_ARGS=0
+VERBOSE=0
+OPTEE_FULL=0
+BUILD_HAFNIUM=1
+BUILD_S_HAFNIUM=1
+BUILD_LINUX_KERNEL=0
+
+BL33_BIN=0
+HAFNIUM_DIR=0
+ATF_DIR=0
+OPTEE_DIR=0
+OPTEE_OS_DIR=0
+OPTEE_LINUX_KERNEL_DIR=0
+
+XTERM=1
+TMUX=0
+
+while getopts cdehij:krsuvxy:A:BE:H:L:O:ST:XY: option; do
+ case "${option}" in
+
+ h)
+ echo "$USAGE"
+ exit 0
+ ;;
+ A) ATF_DIR=${OPTARG} ;;
+ B) BUILD_ONLY=1 ;;
+ E) OPTEE_DIR=${OPTARG} ;;
+ H) BL33_BIN=${OPTARG} ;;
+ L) OPTEE_LINUX_KERNEL_DIR=${OPTARG} ;;
+ O) OPTEE_OS_DIR=${OPTARG} ;;
+ S) CACHE_STATE=1 ;;
+ T) TOOL_CHAINS_DIR=${OPTARG} ;;
+ X)
+ TMUX=1
+ XTERM=0
+ ;;
+ Y) BUILD_S_HAFNIUM=${OPTARG} ;;
+ c) CLEAN=1 ;;
+ d) DEBUG=1 ;;
+ e) OPTEE_FULL=1 ;;
+ k) BUILD_LINUX_KERNEL=1 ;;
+ j) NO_CPUS=${OPTARG} ;;
+ r) RUN_ONLY=1 ;;
+ s) MULTI_CORE_DTB=0 ;;
+ v) VERBOSE=1 ;;
+ x) XTERM=0 ;;
+ y) BUILD_HAFNIUM=${OPTARG} ;;
+ esac
+done
+
+# Default for hafnium directory
+if [ $HAFNIUM_DIR == 0 ]; then
+ HAFNIUM_DIR=$BASE_DIR/hafnium
+fi
+# Default for atf directory
+if [ $ATF_DIR == 0 ]; then
+ ATF_DIR=$BASE_DIR/arm-trusted-firmware
+fi
+
+# Set DT dir
+DTS_DIR=${ATF_DIR}/fdts/
+
+# Default for optee_os directory
+if [ $OPTEE_OS_DIR == 0 ]; then
+ OPTEE_OS_DIR=$BASE_DIR/optee_os
+fi
+# Default for linux directory
+if [ $OPTEE_LINUX_KERNEL_DIR == 0 ]; then
+ OPTEE_LINUX_KERNEL_DIR=$BASE_DIR/linux_kernel
+fi
+
+# Default for full optee checkout directory
+if [ $OPTEE_DIR == 0 ]; then
+ OPTEE_DIR=$BASE_DIR/optee_full
+fi
+
+if [ $MULTI_CORE_DTB == 1 ]; then
+ NORMAL_WORLD_DT="normal_world_multi"
+else
+ NORMAL_WORLD_DT="normal_world_single"
+fi
+
+# Provide default for not using Hyp in normal world.
+if [ $BUILD_HAFNIUM == 0 ]; then
+ BL33_BIN="$PREBUILTS_DIR/FVP_AARCH64_EFI.fd"
+fi
+
+# Get absolute paths
+ATF_DIR=$(realpath -m $ATF_DIR)
+HAFNIUM_DIR=$(realpath -m $HAFNIUM_DIR)
+OPTEE_OS_DIR=$(realpath -m $OPTEE_OS_DIR)
+OPTEE_LINUX_KERNEL_DIR=$(realpath -m $OPTEE_LINUX_KERNEL_DIR)
+PREBUILTS_DIR=$(realpath -m $PREBUILTS_DIR)
+BL33_BIN=$(realpath -m $BL33_BIN)
+TOOL_CHAINS_DIR=$(realpath -m $TOOL_CHAINS_DIR)
+
+function env_check() {
+
+ # Check if prebuilts directory is present
+ if [ ! -d $PREBUILTS_DIR ]; then
+ clone_prebuilts
+ fi
+ # Check if toolchains directory is present
+ if [ ! -d $TOOL_CHAINS_DIR ]; then
+ check_toolchains
+ fi
+
+ # Check FVP is present
+ if [ ! -d $MODEL_DIR ]; then
+ check_fvp
+ fi
+
+ # Check if hafnium directory is present
+ if [ ! -d $HAFNIUM_DIR ]; then
+ echo "$HAFNIUM_DIR does not exist!"
+ exit 1
+ fi
+ # Check if ATF directory is present
+ if [ ! -d $ATF_DIR ]; then
+ echo "$ATF_DIR does not exist!"
+ exit 1
+ fi
+ # Check if optee_os directory is present
+ if [ ! -d $OPTEE_OS_DIR ]; then
+ echo "$OPTEE_OS_DIR does not exist!"
+ exit 1
+ fi
+ # Check if full optee directory is present
+ if [ $OPTEE_FULL == 1 ] && [ ! -d $OPTEE_DIR ]; then
+ echo "$OPTEE_DIR does not exist!"
+ exit 1
+ fi
+ # Check if linux kernel directory is present
+ if [[ ! -d $OPTEE_LINUX_KERNEL_DIR ]]; then
+ echo "$OPTEE_LINUX_KERNEL_DIR does not exist!"
+ exit 1
+ fi
+ # Check if dts directory is present
+ if [ ! -d $DTS_DIR ]; then
+ echo "$DTS_DIR does not exist!"
+ exit 1
+ fi
+
+ # Create output directory
+ mkdir -p $OUT
+
+ if [ ! $(which cpio) ]; then
+ echo "cpio" command not found. Please install "cpio".
+ exit 1
+ fi
+
+ if [ ! $(which dtc) ]; then
+ echo "dtc" command not found. Please install "device-tree-compiler".
+ exit 1
+ fi
+}
+
+function check_fvp() {
+ printf "Could not find fvp at $MODEL_DIR\nPlease download the FVPBaseRevC Model.\n"
+ exit 1
+}
+
+function check_toolchains() {
+
+ # Check if prebuilts directory is present
+ if [ ! -d $TOOL_CHAINS_DIR ]; then
+
+ if [ -d $OPTEE_DIR/toolchains/aarch32 ]; then
+ mkdir $TOOL_CHAINS_DIR || true
+ echo $TOOL_CHAINS_DIR
+ cp -r $OPTEE_DIR/toolchains/aarch32 $OPTEE_DIR/toolchains/aarch64 $TOOL_CHAINS_DIR/
+ else
+ printf "Could not find toolchains at $TOOL_CHAINS_DIR\nPlease do a full build of OP-TEE with and ensure the paths are correct.\n"
+ exit 1
+ fi
+ fi
+}
+
+function clone_prebuilts() {
+ # Check if prebuilts directory is present
+ if [ ! -d $PREBUILTS_DIR ]; then
+ if [ -f $BASE_DIR/prebuilts.tar.gz ]; then
+ mkdir -p $PREBUILTS_DIR
+ tar -xvf prebuilts.tar.gz -C $PREBUILTS_DIR
+ elif [ -f $OPTEE_DIR/out-br/images/rootfs.cpio.gz ] &&
+ [ -f $OPTEE_DIR/edk2-platforms/Build/ArmVExpress-FVP-AArch64/RELEASE_GCC49/FV/FVP_AARCH64_EFI.fd ]; then
+ mkdir -p $PREBUILTS_DIR
+ cp $OPTEE_DIR/out-br/images/rootfs.cpio.gz $PREBUILTS_DIR/optee_rd.img
+ cp $OPTEE_DIR/edk2-platforms/Build/ArmVExpress-FVP-AArch64/RELEASE_GCC49/FV/FVP_AARCH64_EFI.fd $PREBUILTS_DIR/FVP_AARCH64_EFI.fd
+ cp $OPTEE_DIR/out/boot-fat.uefi.img $PREBUILTS_DIR/boot-fat.uefi.img
+ fi
+ else
+ printf "Could not find prebuilts!\nPlease do a full build of OP-TEE with and ensure the paths are correct.\n"
+ exit 1
+ fi
+}
+
+function clone_optee_full() {
+ # Checkout and Build
+ mkdir -p $OPTEE_DIR
+ cd $OPTEE_DIR
+ mkdir $OPTEE_DIR/Foundation_Platformpkg || true
+ repo init -u https://github.com/OP-TEE/manifest.git -m fvp.xml
+ repo sync -j4 --no-clone-bundle
+ cd $OPTEE_DIR/build
+ make -j2 toolchains
+ make -j$NO_CPUS
+}
+
+function build_linux_kernel() {
+ cd $OPTEE_LINUX_KERNEL_DIR
+
+ ARCH=arm64
+
+ make ARCH=$ARCH CROSS_COMPILE="${TOOL_CHAINS_DIR}/aarch64/bin/aarch64-linux-gnu-" defconfig -j$NO_CPUS
+ make ARCH=$ARCH CROSS_COMPILE="${TOOL_CHAINS_DIR}/aarch64/bin/aarch64-linux-gnu-" -j$NO_CPUS
+
+ cp arch/arm64/boot/Image $OUT/
+}
+
+# Rebuild op-tee os with prototype flags
+function build_optee_os() {
+ cd $BASE_DIR/optee_os
+ if [ $CLEAN == 1 ]; then
+ make clean
+ rm -rf out
+ fi
+
+ # Build under S-EL2 or S-EL1
+ if [ $BUILD_S_HAFNIUM == 1 ]; then
+ SEL2=y
+ SEL1=n
+ else
+ SEL2=n
+ SEL1=y
+ fi
+
+ CROSS_COMPILE="${TOOL_CHAINS_DIR}/aarch64/bin/aarch64-linux-gnu-" \
+ make CFG_ARM64_core=y CROSS_COMPILE="${TOOL_CHAINS_DIR}/aarch64/bin/aarch64-linux-gnu-" \
+ CROSS_COMPILE_core="${TOOL_CHAINS_DIR}/aarch64/bin/aarch64-linux-gnu-" \
+ CROSS_COMPILE_ta_arm64=${TOOL_CHAINS_DIR}/aarch64/bin/aarch64-linux-gnu- \
+ CROSS_COMPILE_ta_arm32=${TOOL_CHAINS_DIR}/aarch32/bin/arm-linux-gnueabihf- \
+ CFG_TEE_CORE_LOG_LEVEL=3 DEBUG=1 CFG_TEE_BENCHMARK=n PLATFORM=vexpress-fvp CFG_ARM_GICV3=y \
+ CFG_CORE_BGET_BESTFIT=y \
+ CFG_ARM64_core=y CFG_CORE_SEL2_SPMC=$SEL2 CFG_CORE_SEL1_SPMC=$SEL1
+}
+
+# Rebuild ATF FIP
+function build_ATF-FIP() {
+ cd $ATF_DIR
+ # Always fully clean before rebuild.
+ make realclean
+
+ # Specify a SP layout file if we're building with SPM in S-EL2
+ SP_LAYOUT=""
+ if [ $BUILD_S_HAFNIUM == 1 ]; then
+ SP_LAYOUT="SP_LAYOUT_FILE=sp_layout.json"
+ fi
+
+ make -j$NO_CPUS CROSS_COMPILE="${TOOL_CHAINS_DIR}/aarch64/bin/aarch64-linux-gnu-" \
+ SPD=spmd \
+ CTX_INCLUDE_EL2_REGS=$BUILD_S_HAFNIUM \
+ SPMD_SPM_AT_SEL2=$BUILD_S_HAFNIUM \
+ PLAT=fvp \
+ BL33=$BL33_BIN \
+ DEBUG=1 \
+ BL32=$BL32_BIN \
+ ARM_ARCH_MINOR=4 \
+ FVP_NT_FW_CONFIG=$OUT/${NORMAL_WORLD_DT}.dtb \
+ $SP_LAYOUT all fip
+
+ cp $ATF_DIR/build/fvp/debug/fip.bin $OUT
+ cp $ATF_DIR/build/fvp/debug/bl1.bin $OUT
+}
+
+function build_hafnium() {
+ cd $HAFNIUM_DIR
+ if [ $CLEAN == 1 ]; then
+ make clean || true
+ cd third_party/linux
+ make mrproper
+ fi
+ cd $HAFNIUM_DIR
+ CROSS_COMPILE="${TOOL_CHAINS_DIR}/aarch64/bin/aarch64-linux-gnu-" make
+ cp out/reference/aem_v8a_fvp_clang/hafnium.bin $OUT
+ cp out/reference/secure_aem_v8a_fvp_clang/hafnium.bin $OUT/secure_hafnium.bin
+
+ # Choose appropriate BL33 image depending if we want N-Hyp.
+ if [ $BUILD_HAFNIUM == 1 ]; then
+ BL33_BIN=$OUT/hafnium.bin
+ fi
+
+ # Choose appropriate BL32 image depending if we want S-Hyp.
+ if [ $BUILD_S_HAFNIUM == 1 ]; then
+ BL32_BIN="$OUT/secure_hafnium.bin"
+ else
+ BL32_BIN="$OPTEE_OS_DIR/out/arm-plat-vexpress/core/tee-pager_v2.bin"
+ fi
+
+}
+
+function build_optee_ramdisk() {
+ # Copy from OP-TEE or use prebuilt.
+ cd $OUT
+ if [ $OPTEE_FULL == 1 ]; then
+ cp $OPTEE_DIR/out-br/images/rootfs.cpio.gz $PREBUILTS_DIR/optee_rd.img
+ fi
+
+ cp $PREBUILTS_DIR/optee_rd.img $OUT/optee_rd.img
+}
+
+function build_hafnium_ramdisk() {
+ cd $OUT
+ if [ -d "initrd" ]; then
+ rm -rf initrd
+ fi
+ mkdir initrd
+ cd initrd
+
+ # Using dtb for vm description.
+ build_dtb $DTS_DIR/inner_initrd.dts
+
+ cp $OUT/inner_initrd.dtb manifest.dtb
+ cp $OUT/optee_rd.img ./initrd.img
+ cp $OUT/Image vmlinuz
+
+ # The manifest file must be passed first to prevent alignment issues
+ # until we move to libfdt.
+ printf "manifest.dtb\ninitrd.img\nvmlinuz" | cpio -o >../initrd.img
+ cd ..
+ rm -rf initrd
+}
+
+function build_secure_hafnium_ramdisk() {
+ cd $OUT
+ if [ -d "secure_initrd" ]; then
+ rm -rf secure_initrd
+ fi
+
+ mkdir secure_initrd
+ cd secure_initrd
+
+ cp $DTS_DIR/secure_world_dt.dts manifest.dts
+ dtc -I dts -O dtb manifest.dts > manifest.dtb
+
+ cp $PREBUILTS_DIR/optee_rd.img ./initrd.img
+
+ # Copy OP-TEE and baremetal SP binaries.
+ # According to the Secure world manifest, the baremetal SP is a secondary SP and OPTEE is the "primary"
+ cp $HAFNIUM_DIR/out/reference/secure_aem_v8a_fvp_vm_clang/obj/test/secure_world_baremetal/secure_world_sp.bin bare_metal_sp
+ cp ${OPTEE_OS_DIR}/out/arm-plat-vexpress/core/tee-pager_v2.bin optee
+
+ # The manifest file must be passed first to prevent alignment issues
+ # until we move to libfdt.
+ printf "manifest.dtb\ninitrd.img\noptee\nbare_metal_sp" | cpio -o >../secure_initrd.img
+ cd ..
+ rm -rf secure_initrd
+}
+
+function build_dtb() {
+
+ SOURCE_DTS=$DTS_DIR/${NORMAL_WORLD_DT}.dts
+
+ if [[ -n $1 ]]; then
+ SOURCE_DTS=$1
+ fi
+ # Ouput file in $OUT/<source>.dtb
+ dtc -O dtb -o $OUT/"$(basename $SOURCE_DTS .dts).dtb" $SOURCE_DTS
+}
+
+function create_dtb() {
+ cd $OUT
+ cp $DTS_DIR/${NORMAL_WORLD_DT}.dts ${NORMAL_WORLD_DT}.dts
+
+ START_ADDR=0x84000000
+ FILESIZE=$(stat -c%s "$OUT/initrd.img")
+ END_ADDR=$(python -c "print(hex($START_ADDR+$FILESIZE))")
+
+ if [ $KERNEL_ARGS == 0 ]; then
+ KERNEL_ARGS="rdinit=/sbin/init"
+ fi
+
+ echo """
+ / {
+
+ spci {
+ compatible = \"arm,ffa\";
+ conduit = \"smc\";
+ /* \"tx\" or \"allocate\" */
+ mem_share_buffer = \"tx\";
+ };
+ chosen {
+ linux,initrd-start = <$START_ADDR>;
+ linux,initrd-end = <$END_ADDR>;
+ stdout-path = \"serial0:115200n8\";
+ bootargs = \"cpuidle.off=1\";
+
+ };
+ hypervisor {
+ compatible = \"hafnium,hafnium\";
+ vm1 {
+ debug_name = \"linux_test\";
+ kernel_filename = \"vmlinuz\";
+ ramdisk_filename = \"initrd.img\";
+ uuid = <0x0000 0x0 0x0 0x1>;
+ messaging_method = <0x2>;
+ smc_whitelist_permissive;
+ };
+ };
+ };""" >> $OUT/${NORMAL_WORLD_DT}.dts
+ cd $OUT
+
+ build_dtb $OUT/${NORMAL_WORLD_DT}.dts
+}
+
+function modify_eufi_image() {
+ cd $OUT
+ cp $PREBUILTS_DIR/boot-fat.uefi.img $OUT/boot-fat.uefi.img
+
+ # Modify the the grub config to supply the expected device tree path and ensure cpu idle is disabled.
+ echo """
+set prefix='/EFI/BOOT'
+
+set default="0"
+set timeout=5
+
+menuentry 'GNU/Linux (OP-TEE)' {
+ linux /Image console=tty0 console=ttyAMA0,115200 earlycon=pl011,0x1c090000 root=/dev/disk/by-partlabel/system rootwait rw ignore_loglevel efi=noruntime cpuidle.off=1
+ initrd /initrd.img
+ devicetree /fvp-base-gicv3-psci.dtb
+}""" > $OUT/grub.cfg
+
+ cp $OUT/${NORMAL_WORLD_DT}.dtb fvp-base-gicv3-psci.dtb
+ cp fvp-base-gicv3-psci.dtb foundation-v8-gicv3-psci.dtb
+ mcopy -o -i boot-fat.uefi.img Image ::
+ mcopy -o -i boot-fat.uefi.img fvp-base-gicv3-psci.dtb ::
+ mcopy -o -i boot-fat.uefi.img foundation-v8-gicv3-psci.dtb ::
+ mcopy -o -i boot-fat.uefi.img grub.cfg ::EFI/BOOT/
+}
+
+# Main compilation workflow
+function compile() {
+
+ if [ $BUILD_LINUX_KERNEL == 1 ] || [ ! -f $OUT/Image ]; then
+ printf "\nBuild Linux Kernel...\n"
+ build_linux_kernel
+ fi
+
+ # Build Hafnium & linux and generate ramdisks
+ printf "\nBuild Hafnium...\n"
+ build_hafnium
+ printf "\nBuild OP-TEE Ramdisk...\n"
+ build_optee_ramdisk
+ printf "\nBuild Hafnium Ramdisk...\n"
+ build_hafnium_ramdisk
+ printf "\nCreate DTB...\n"
+ create_dtb
+
+ # Update eufi image
+ if [ $BUILD_HAFNIUM == 0 ]; then
+ modify_eufi_image
+ fi
+ printf "\nBuild OP-TEE OS...\n"
+ build_optee_os
+ printf "\nBuild Secure-Hafnium Ramdisk...\n"
+ build_secure_hafnium_ramdisk
+ printf "\nBuild ATF FIP...\n"
+ build_ATF-FIP
+}
+
+# Run the FVP
+function run() {
+ # Allow for specifying additional arguments
+ ARGS=""
+ if [ $DEBUG == 1 ]; then
+ ARGS="$ARGS -S"
+ fi
+
+ DTB=''
+ if [[ $BUILD_HAFNIUM == 1 ]]; then
+ BOOT_IMAGES="--data cluster0.cpu0=$OUT/initrd.img@0x84000000"
+ DTB="--data cluster0.cpu0=$OUT/${NORMAL_WORLD_DT}.dtb@0x80000000"
+ else
+ BOOT_IMAGES="-C bp.virtioblockdevice.image_path=$OUT/boot-fat.uefi.img"
+ fi
+
+ if [ $BUILD_S_HAFNIUM == 1 ]; then
+ BOOT_IMAGES="${BOOT_IMAGES} --data cluster0.cpu0=$OUT/secure_initrd.img@0xA000000"
+ fi
+
+ cd $BASE_DIR
+ FVP_INVOCATION="""${MODEL_DIR}/FVP_Base_RevC-2xAEMv8A \
+ -C pctl.startup=0.0.0.0 \
+ -C bp.secure_memory=0 \
+ -C cluster0.NUM_CORES=4 \
+ -C cluster1.NUM_CORES=4 \
+ -C cache_state_modelled=$CACHE_STATE \
+ -C bp.pl011_uart0.untimed_fifos=1 \
+ -C bp.pl011_uart0.unbuffered_output=1 \
+ -C bp.pl011_uart1.untimed_fifos=1 \
+ -C bp.pl011_uart1.unbuffered_output=1 \
+ -C bp.pl011_uart0.out_file=$OUT/uart0.log \
+ -C bp.pl011_uart1.out_file=$OUT/uart1.log \
+ -C bp.terminal_0.start_telnet=$XTERM \
+ -C bp.terminal_1.start_telnet=$XTERM \
+ -C bp.vis.disable_visualisation=$((1 - XTERM)) \
+ -C bp.secureflashloader.fname=$OUT/bl1.bin \
+ -C bp.flashloader0.fname=$OUT/fip.bin \
+ -C bp.ve_sysregs.mmbSiteDefault=0 \
+ -C bp.ve_sysregs.exit_on_shutdown=1 \
+ -C cluster0.has_arm_v8-4=1 \
+ -C cluster1.has_arm_v8-4=1 \
+ ${BOOT_IMAGES} ${DTB} ${ARGS} """
+
+ if [ $TMUX == 0 ]; then
+ $FVP_INVOCATION
+ else
+ DELAY=2
+ export TMUX=''
+ tmux new-session \; \
+ send-keys """trap 'tmux kill-session' SIGINT
+ ${FVP_INVOCATION}""" C-m \; \
+ split-window -v \; \
+ send-keys "sleep $DELAY && telnet 0 5000" C-m \; \
+ split-window -h \; \
+ send-keys "sleep $DELAY && telnet 0 5001" C-m \; \
+ select-pane -t 1\;
+ fi
+}
+
+#################################################################################################
+# Main #
+#################################################################################################
+
+# Run only mode
+if [ $RUN_ONLY == 1 ]; then
+ printf "Running FVP...\n"
+ run
+ exit 0
+fi
+
+# Perform full build of OP-TEE
+if [ $OPTEE_FULL == 1 ]; then
+ printf "Building OP-TEE...\n"
+ clone_optee_full
+fi
+
+printf "Checking the Environment...\n"
+env_check
+
+# Enable verbose mode
+if [ $VERBOSE == 1 ]; then
+ set -x
+fi
+
+printf "Compiling...\n"
+compile
+printf "\nBuild Completed!\n\n"
+if [ $BUILD_ONLY == 0 ]; then
+ printf "Running FVP...\n"
+ run
+fi