aboutsummaryrefslogtreecommitdiff
path: root/el3_payload
diff options
context:
space:
mode:
Diffstat (limited to 'el3_payload')
-rw-r--r--el3_payload/.gitignore6
-rw-r--r--el3_payload/Makefile91
-rw-r--r--el3_payload/README141
-rw-r--r--el3_payload/arch.h20
-rw-r--r--el3_payload/asm_macros.S22
-rw-r--r--el3_payload/el3_payload.ld.S28
-rw-r--r--el3_payload/entrypoint.S65
-rw-r--r--el3_payload/plat/fvp/platform.S51
-rw-r--r--el3_payload/plat/fvp/platform.h21
-rw-r--r--el3_payload/plat/fvp/platform.mk8
-rw-r--r--el3_payload/plat/juno/platform.S34
-rw-r--r--el3_payload/plat/juno/platform.h17
-rw-r--r--el3_payload/plat/juno/platform.mk8
-rwxr-xr-xel3_payload/scripts/fvp/run_foundation.sh51
-rwxr-xr-xel3_payload/scripts/fvp/run_fvp.sh56
-rw-r--r--el3_payload/scripts/juno/load_el3_payload.ds11
-rwxr-xr-xel3_payload/scripts/juno/run_ds5_script.sh49
-rw-r--r--el3_payload/spin.S77
-rw-r--r--el3_payload/uart.S56
19 files changed, 812 insertions, 0 deletions
diff --git a/el3_payload/.gitignore b/el3_payload/.gitignore
new file mode 100644
index 000000000..381e35464
--- /dev/null
+++ b/el3_payload/.gitignore
@@ -0,0 +1,6 @@
+*.o
+*~
+*.elf
+*.bin
+*.ld
+*.dump
diff --git a/el3_payload/Makefile b/el3_payload/Makefile
new file mode 100644
index 000000000..f6e809f2c
--- /dev/null
+++ b/el3_payload/Makefile
@@ -0,0 +1,91 @@
+#
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+CROSS_COMPILE := aarch64-linux-gnu-
+CC := ${CROSS_COMPILE}gcc
+AS := ${CROSS_COMPILE}as
+LD := ${CROSS_COMPILE}ld
+OC := ${CROSS_COMPILE}objcopy
+OD := ${CROSS_COMPILE}objdump
+
+PLAT ?= fvp
+
+ASFLAGS := -nostdinc -ffreestanding -Wa,--fatal-warnings -Werror
+ASFLAGS += -Iplat/${PLAT}/ -I.
+
+PLAT_BUILD_DIR := build/${PLAT}
+SOURCES := entrypoint.S spin.S uart.S plat/${PLAT}/platform.S
+OBJS := $(patsubst %,$(PLAT_BUILD_DIR)/%,$(notdir $(SOURCES:.S=.o)))
+
+PROGRAM := el3_payload
+LINKER_SCRIPT := ${PLAT_BUILD_DIR}/${PROGRAM}.ld
+ELF := ${PLAT_BUILD_DIR}/${PROGRAM}.elf
+BIN := ${PLAT_BUILD_DIR}/${PROGRAM}.bin
+DUMP := ${PLAT_BUILD_DIR}/${PROGRAM}.dump
+
+include plat/${PLAT}/platform.mk
+
+all: ${BIN}
+
+${PLAT_BUILD_DIR}:
+ mkdir -p $@
+
+${PLAT_BUILD_DIR}/%.o: %.S ${PLAT_BUILD_DIR}
+ @echo " CC $<"
+ ${CC} ${ASFLAGS} -c $< -o $@
+
+# Specific rule for this '.o' file to avoid worrying about
+# plat/${PLAT}/platform.S being in a sub-directory...
+# TODO: Fix this workaround.
+${PLAT_BUILD_DIR}/platform.o: plat/${PLAT}/platform.S ${PLAT_BUILD_DIR}
+ @echo " CC $<"
+ ${CC} ${ASFLAGS} -c $< -o $@
+
+${PLAT_BUILD_DIR}/%.ld: %.ld.S ${PLAT_BUILD_DIR}
+ @echo " PP $<"
+ ${CC} -DDRAM_BASE=${DRAM_BASE} -DDRAM_SIZE=${DRAM_SIZE} -E -P -o $@ $<
+
+${ELF}: ${LINKER_SCRIPT} ${OBJS}
+ @echo " LD $<"
+ ${LD} ${LDFLAGS} ${OBJS} --script ${LINKER_SCRIPT} -o $@
+
+${BIN}: ${ELF}
+ @echo " BIN $@"
+ ${OC} -O binary $< $@
+
+${DUMP}: $(ELF)
+ @echo " OD $$@"
+ ${OD} -dx $< > $@
+
+dump: ${DUMP}
+
+clean:
+ rm -rf ${PLAT_BUILD_DIR}
+
+distclean: clean
+ rm -rf build/
+
+run: run_${PLAT}
+
+run_juno: ${ELF} scripts/juno/run_ds5_script.sh scripts/juno/load_el3_payload.ds
+ scripts/juno/run_ds5_script.sh scripts/juno/load_el3_payload.ds
+
+run_fvp: scripts/fvp/run_fvp.sh
+ scripts/fvp/run_fvp.sh
+
+help:
+ @echo "EL3 test payload"
+ @echo
+ @echo "To build:"
+ @echo "make [PLAT=fvp|juno] [TARGETS]"
+ @echo ""
+ @echo "The default platform is fvp."
+ @echo
+ @echo "TARGETS:"
+ @echo " all Build the payload [default target]"
+ @echo " dump Generate a dump file of the program"
+ @echo " run Run the payload on the given platform."
+ @echo " /!\ For Juno, requires a connection to a Juno board via DSTREAM"
diff --git a/el3_payload/README b/el3_payload/README
new file mode 100644
index 000000000..fcb3ae106
--- /dev/null
+++ b/el3_payload/README
@@ -0,0 +1,141 @@
+EL3 test payload
+================
+
+This program is a very simple EL3 baremetal application. It has been developed
+to test the ability of the Trusted Firmware-A to load an EL3 payload. All it
+does is making sure that all CPUs enter this image and if so, reports it through
+the UART.
+
+
+Building
+--------
+
+$ make PLAT=juno
+or
+$ make PLAT=fvp
+
+
+Preparing Juno board configuration files
+----------------------------------------
+
+You should have the following line in your 'SITE1/HBI0262X/board.txt' Juno
+configuration file on the SD card (where X depends on the revision of your Juno
+board):
+
+ SCC: 0x0F4 0x000003F8
+
+This:
+ - ensures all CPUs are powered on at reset;
+ - designates the Cortex-A53 #0 as the primary CPU.
+
+See the 'Assumptions' section below' for more details.
+
+
+Running on Juno
+---------------
+
+The Trusted Firmware-A must be compiled with SPIN_ON_BL1_EXIT=1. This will
+introduce an infinite loop in BL1 that gives you some time to load and run the
+EL3 payload over JTAG.
+
+Boot the board and wait until you see the following messages on the UART.
+(Note that the "INFO" messages appear only in a debug build of the Trusted
+Firmware but you should see the "NOTICE" messages in any case.)
+
+ NOTICE: BL1: Booting BL31
+ INFO: BL1: BL31 address = 0x80000000
+ INFO: BL1: BL31 spsr = 0x3cd
+ INFO: BL1: BL31 params address = 0x0
+ INFO: BL1: BL31 plat params address = 0xf1e2d3c4b5a6978
+ INFO: BL1: BL31 address = 0x80000000
+ INFO: BL1: BL31 spsr = 0x3cd
+ INFO: BL1: BL31 params address = 0x0
+ INFO: BL1: BL31 plat params address = 0xf1e2d3c4b5a6978
+ NOTICE: BL1: Debug loop, spinning forever
+ NOTICE: BL1: Please connect the debugger to jump over it
+
+TODO: Update the above messages.
+
+At this point, type the following command in a shell from the EL3 test payload
+top directory:
+
+$ make PLAT=juno run
+
+You should see something like this in your shell (it takes a few seconds):
+
+ Trying to detect your DSTREAM unit...
+ Available connections:
+ USB:000765
+ Connecting to USB:000765...
+ Connected to running target Cortex-A53_0
+ Execution stopped in EL3h mode at EL3:0x000000000BEC2548
+ EL3:0x000000000BEC2548 B {pc} ; 0xbec2548
+ Loaded section ro: EL3:0x0000000080000000 ~ EL3:0x0000000080000123 (size 0x124)
+ Loaded section .data: EL3:0x0000000080000128 ~ EL3:0x0000000080000197 (size 0x70)
+ Entry point EL3:0x0000000080000000
+ Disconnected from running target Cortex-A53_0
+
+And on the Juno UART, this should print the following messages:
+
+ Booting the EL3 test payload
+ All CPUs booted!
+
+
+Running on FVP (AEMv8A)
+-----------------------
+
+First, copy the "bl1.bin" and "fip.bin" files into the current directory.
+Alternatively, symbolic links might be created.
+
+Then run:
+
+$ make PLAT=fvp run
+
+Note: The EL3 payload does not work on the Foundation FVP.
+(This is because it expects 8 CPUs and the Foundation FVP has maximum 4.)
+
+
+How does it work?
+-----------------
+
+There is a per-cpu array. Each entry is initialised to a "dead" value. On entry
+into the payload, each CPU writes its MPID to its entry, which allows it to
+signal its presence.
+
+Secondary CPUs then spin forever.
+
+The primary CPU carries on.
+ 1) It prints a "welcome" string.
+ 2) It waits for each entry in the CPUs array to be updated.
+ 3) Once all CPUs have been detected in that way, it prints a success message.
+ 4) Finally, it spins forever.
+
+
+Assumptions
+-----------
+
+- All CPUs enter the EL3 test payload at some point.
+ The order doesn't matter, though.
+ If some CPU doesn't boot then the EL3 payload will wait forever.
+
+- On FVP, the number of cores is hard-coded to 8.
+ If the FVP model is configured to disable some CPUs then the EL3 payload will
+ hang, waiting forever for absent CPUs.
+ For the same reason, the EL3 payload hangs on the Foundation FVP (which has
+ 4 CPUs only).
+
+- The UART is already configured.
+
+- On Juno, the primary CPU is hard-coded to the Cortex-A53 #0.
+ Any CPU could be the primary CPU, though. However, the DS-5 scripts launched
+ by 'make run' assumes the Cortex-A53 #0 is the primary CPU.
+
+ On FVP, the primary CPU is hard-coded to the CPU with MPID 0x0.
+
+ Designating a CPU as the primary one simplifies the code, More particularly,
+ only the primary CPU accesses the UART, which removes the need for
+ synchronisation locks to avoid interleaved messages.
+
+- The EL3 test pyaload runs from RAM.
+ It can't execute from flash, as we would need to relocate the .data section
+ in RAM at run-time and this is not implemented for now.
diff --git a/el3_payload/arch.h b/el3_payload/arch.h
new file mode 100644
index 000000000..a6a480c65
--- /dev/null
+++ b/el3_payload/arch.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __ARCH_H__
+#define __ARCH_H__
+
+#define MPIDR_MT_MASK (1 << 24)
+#define MPIDR_AFFLVL_MASK 0xff
+#define MPIDR_AFFINITY_BITS 8
+#define MPIDR_CPU_MASK MPIDR_AFFLVL_MASK
+#define MPIDR_CLUSTER_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFFINITY_BITS)
+#define MPIDR_AFF0_SHIFT 0
+#define MPIDR_AFF1_SHIFT 8
+#define MPIDR_AFF2_SHIFT 16
+#define MPIDR_AFFINITY_MASK 0xff00ffffff
+
+#endif /* __ARCH_H__ */
diff --git a/el3_payload/asm_macros.S b/el3_payload/asm_macros.S
new file mode 100644
index 000000000..d02afba2d
--- /dev/null
+++ b/el3_payload/asm_macros.S
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ /*
+ * This macro is used to create a function label.
+ */
+ .macro func _name
+ .type \_name, %function
+ .func \_name
+ \_name:
+ .endm
+
+ /*
+ * This macro is used to mark the end of a function.
+ */
+ .macro endfunc _name
+ .endfunc
+ .size \_name, . - \_name
+ .endm
diff --git a/el3_payload/el3_payload.ld.S b/el3_payload/el3_payload.ld.S
new file mode 100644
index 000000000..b1c28dc00
--- /dev/null
+++ b/el3_payload/el3_payload.ld.S
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+OUTPUT_FORMAT("elf64-littleaarch64")
+OUTPUT_ARCH("aarch64")
+ENTRY(entrypoint)
+
+MEMORY {
+ RAM (rwx): ORIGIN = DRAM_BASE, LENGTH = (DRAM_BASE + DRAM_SIZE)
+}
+
+SECTIONS
+{
+ . = DRAM_BASE;
+
+ ro . : {
+ */entrypoint.o(.text)
+ *(.text*)
+ *(.rodata*)
+ } >RAM
+
+ .data : {
+ *(.data*)
+ } >RAM
+}
diff --git a/el3_payload/entrypoint.S b/el3_payload/entrypoint.S
new file mode 100644
index 000000000..2da49363c
--- /dev/null
+++ b/el3_payload/entrypoint.S
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "arch.h"
+#include "asm_macros.S"
+#include "platform.h"
+
+#define EOT_ASCII_CODE 4
+
+ .data
+welcome_str:
+ .asciz "Booting the EL3 test payload\r\n"
+all_cpus_booted_str:
+ .asciz "All CPUs booted!\r\n"
+
+ .text
+ .global entrypoint
+
+func entrypoint
+ bl mark_cpu_presence
+
+ /* Distinguish primary from secondary CPUs */
+ mrs x0, mpidr_el1
+ ldr x1, =MPIDR_AFFINITY_MASK
+ and x0, x0, x1
+
+ ldr x1, =PRIMARY_CPU_MPID
+ cmp x0, x1
+ b.ne spin_forever
+
+ /*
+ * Only the primary CPU executes the code below
+ */
+
+ adr x0, welcome_str
+ bl print_string
+
+ /* Wait to see each CPU */
+ mov x3, xzr
+1:
+ mov x0, x3
+ bl is_cpu_present
+ cbz x0, 1b
+
+ /* Next CPU, if any */
+ add x3, x3, #1
+ mov x0, #CPUS_COUNT
+ cmp x3, x0
+ b.lt 1b
+
+ /* All CPUs have been detected, announce the good news! */
+ adr x0, all_cpus_booted_str
+ bl print_string
+
+ /* Send EOT (End of Transmission character) character over the UART */
+ mov x0, #EOT_ASCII_CODE
+ bl print_char
+
+spin_forever:
+ wfe
+ b spin_forever
+endfunc entrypoint
diff --git a/el3_payload/plat/fvp/platform.S b/el3_payload/plat/fvp/platform.S
new file mode 100644
index 000000000..5855ca754
--- /dev/null
+++ b/el3_payload/plat/fvp/platform.S
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "arch.h"
+#include "asm_macros.S"
+#include "platform.h"
+
+ .text
+ .global platform_get_core_pos
+
+/*----------------------------------------------------------------------
+ * unsigned int platform_get_core_pos(unsigned long mpid)
+ *
+ * Function to calculate the core position on FVP.
+ *
+ * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) +
+ * (CPUId * FVP_MAX_PE_PER_CPU) +
+ * ThreadId
+ *
+ * which can be simplified as:
+ *
+ * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU)
+ * + ThreadId
+ *
+ * clobbers: x0, x1, x3, x4
+ * ---------------------------------------------------------------------
+ */
+func platform_get_core_pos
+ /*
+ * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
+ * look as if in a multi-threaded implementation.
+ */
+ tst x0, #MPIDR_MT_MASK
+ lsl x3, x0, #MPIDR_AFFINITY_BITS
+ csel x3, x3, x0, eq
+
+ /* Extract individual affinity fields from MPIDR */
+ ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+ ubfx x4, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+ /* Compute linear position */
+ mov x3, #FVP_MAX_CPUS_PER_CLUSTER
+ madd x1, x4, x3, x1
+ mov x3, #FVP_MAX_PE_PER_CPU
+ madd x0, x1, x3, x0
+ ret
+endfunc platform_get_core_pos
diff --git a/el3_payload/plat/fvp/platform.h b/el3_payload/plat/fvp/platform.h
new file mode 100644
index 000000000..809ae7eb2
--- /dev/null
+++ b/el3_payload/plat/fvp/platform.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLATFORM_H__
+#define __PLATFORM_H__
+
+#define PRIMARY_CPU_MPID 0x0
+
+/* Always expect 8 cores, although this is configurable on FVP */
+#define CPUS_COUNT 8
+
+#define UART_BASE 0x1c090000
+
+#define FVP_MAX_CPUS_PER_CLUSTER 4
+/* Currently multi-threaded CPUs only have a single thread */
+#define FVP_MAX_PE_PER_CPU 1
+
+#endif /* __PLATFORM_H__ */
diff --git a/el3_payload/plat/fvp/platform.mk b/el3_payload/plat/fvp/platform.mk
new file mode 100644
index 000000000..b4cda9b65
--- /dev/null
+++ b/el3_payload/plat/fvp/platform.mk
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+DRAM_BASE := 0x80000000
+DRAM_SIZE := 0x80000000
diff --git a/el3_payload/plat/juno/platform.S b/el3_payload/plat/juno/platform.S
new file mode 100644
index 000000000..6c8773b66
--- /dev/null
+++ b/el3_payload/plat/juno/platform.S
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "arch.h"
+#include "asm_macros.S"
+
+ .text
+ .global platform_get_core_pos
+
+ /* --------------------------------------------------------------------
+ * unsigned int get_core_pos(uint64_t mpidr);
+ *
+ * Helper function to calculate the core position from its MPID.
+ * Core positions must be consecutive, there must be no holes.
+ *
+ * MPID -> core position:
+ * 0x100 -> 0
+ * 0x101 -> 1
+ * 0x102 -> 2
+ * 0x103 -> 3
+ * 0x0 -> 4
+ * 0x1 -> 5
+ * --------------------------------------------------------------------
+ */
+func platform_get_core_pos
+ and x1, x0, #MPIDR_CPU_MASK
+ and x0, x0, #MPIDR_CLUSTER_MASK
+ eor x0, x0, #(1 << MPIDR_AFFINITY_BITS) /* swap cluster order */
+ add x0, x1, x0, LSR #6
+ ret
+endfunc platform_get_core_pos
diff --git a/el3_payload/plat/juno/platform.h b/el3_payload/plat/juno/platform.h
new file mode 100644
index 000000000..7fdcb3ee5
--- /dev/null
+++ b/el3_payload/plat/juno/platform.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLATFORM_H__
+#define __PLATFORM_H__
+
+/* Designate the Cortex-A53 #0 as the primary CPU */
+#define PRIMARY_CPU_MPID 0x100
+
+#define CPUS_COUNT 6
+
+#define UART_BASE 0x7ff80000
+
+#endif /* __PLATFORM_H__ */
diff --git a/el3_payload/plat/juno/platform.mk b/el3_payload/plat/juno/platform.mk
new file mode 100644
index 000000000..b4cda9b65
--- /dev/null
+++ b/el3_payload/plat/juno/platform.mk
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+DRAM_BASE := 0x80000000
+DRAM_SIZE := 0x80000000
diff --git a/el3_payload/scripts/fvp/run_foundation.sh b/el3_payload/scripts/fvp/run_foundation.sh
new file mode 100755
index 000000000..f8ec343d3
--- /dev/null
+++ b/el3_payload/scripts/fvp/run_foundation.sh
@@ -0,0 +1,51 @@
+#! /bin/bash
+
+#
+# Script to run the EL3 payload on the Foundation FVP.
+#
+# /!\ The EL3 payload is not supported on the Foundation FVP without tweaking
+# the code. You need to modify the number of expected cores in
+# plat/fvp/platform.h:
+# -#define CPUS_COUNT 8
+# +#define CPUS_COUNT 4
+#
+
+set -e
+
+# usage: check_file_is_present <filename>
+# Check that <filename> exists in the current directory.
+# If not, print an error message and exit.
+function check_file_is_present
+{
+ BIN_FILE=$1
+ if [ ! -e "$BIN_FILE" ]; then
+ echo "ERROR: Can't find \"$BIN_FILE\" file"
+ echo "Please copy $BIN_FILE into the current working directory."
+ echo "Alternatively, a symbolic link might be created."
+ echo
+ exit 1
+ fi
+}
+
+check_file_is_present "bl1.bin"
+check_file_is_present "fip.bin"
+
+# Create an 8-byte file containing all zero bytes.
+# It will be loaded at the beginning of the Trusted SRAM to zero the mailbox.
+MAILBOX_FILE=mailbox.dat
+rm -f $MAILBOX_FILE
+dd if=/dev/zero of=$MAILBOX_FILE bs=1 count=8
+
+# The path to the Foundation model must be provided by the user.
+MODEL_EXEC="${MODEL_EXEC:?}"
+MODEL_PARAMETERS=" \
+ --cores=4 \
+ --visualization \
+ --data=bl1.bin@0x0 \
+ --data=fip.bin@0x08000000 \
+ --data=$MAILBOX_FILE@0x04000000 \
+ --data=build/fvp/el3_payload.bin@0x80000000 \
+"
+
+echo $MODEL_EXEC $MODEL_PARAMETERS
+$MODEL_EXEC $MODEL_PARAMETERS
diff --git a/el3_payload/scripts/fvp/run_fvp.sh b/el3_payload/scripts/fvp/run_fvp.sh
new file mode 100755
index 000000000..788c90cb6
--- /dev/null
+++ b/el3_payload/scripts/fvp/run_fvp.sh
@@ -0,0 +1,56 @@
+#! /bin/bash
+
+set -e
+
+UART_OUTPUT_FILE=uart0.log
+
+# usage: check_file_is_present <filename>
+# Check that <filename> exists in the current directory.
+# If not, print an error message and exit.
+function check_file_is_present
+{
+ BIN_FILE=$1
+ if [ ! -e "$BIN_FILE" ]; then
+ echo "ERROR: Can't find \"$BIN_FILE\" file"
+ echo "Please copy $BIN_FILE into the current working directory."
+ echo "Alternatively, a symbolic link might be created."
+ echo
+ exit 1
+ fi
+}
+
+check_file_is_present "bl1.bin"
+check_file_is_present "fip.bin"
+
+# The path to the Foundation model must be provided by the user.
+MODEL_EXEC="${MODEL_EXEC:?}"
+MODEL_PARAMETERS="
+ -C pctl.startup=0.0.*.*,0.1.*.* \
+ -C bp.secureflashloader.fname=bl1.bin \
+ -C bp.flashloader0.fname=fip.bin \
+ --data cluster0.cpu0=build/fvp/el3_payload.bin@0x80000000 \
+ -C bp.secureSRAM.fill1=0x00000000 \
+ -C bp.secureSRAM.fill2=0x00000000 \
+ -C bp.pl011_uart0.out_file=$UART_OUTPUT_FILE \
+ -C bp.pl011_uart0.shutdown_on_eot=1 \
+"
+
+echo $MODEL_EXEC $MODEL_PARAMETERS
+$MODEL_EXEC $MODEL_PARAMETERS
+
+# Print results
+green='\033[1;32;40m'
+no_color='\033[0m'
+echo
+echo -e "$green"
+echo "============"
+echo " COMPLETE!"
+echo "============"
+echo -e "$no_color"
+echo "UART output:"
+echo "--------------------------------8<------------------------------"
+cat $UART_OUTPUT_FILE
+echo "--------------------------------8<------------------------------"
+echo
+echo "Output saved in $UART_OUTPUT_FILE file."
+echo
diff --git a/el3_payload/scripts/juno/load_el3_payload.ds b/el3_payload/scripts/juno/load_el3_payload.ds
new file mode 100644
index 000000000..23db44dbd
--- /dev/null
+++ b/el3_payload/scripts/juno/load_el3_payload.ds
@@ -0,0 +1,11 @@
+# Stop target
+interrupt
+
+# Load EL3 payload
+load build/juno/el3_payload.elf
+
+# Jump over BL1 infinite loop
+set var $pc = $pc + 4
+
+# Resume execution
+continue
diff --git a/el3_payload/scripts/juno/run_ds5_script.sh b/el3_payload/scripts/juno/run_ds5_script.sh
new file mode 100755
index 000000000..67d07365a
--- /dev/null
+++ b/el3_payload/scripts/juno/run_ds5_script.sh
@@ -0,0 +1,49 @@
+#! /bin/sh
+
+set -e
+
+# Expect the script to run in argument
+if [ $# != 1 ]; then
+ echo "ERROR: No script provided"
+ echo "usage: $(basename $0) <ds5_script_to_run>"
+ exit 1
+fi
+
+# Is DS-5 command-line debugger found?
+if [ ! $(which debugger) ]; then
+ echo 'ERROR: Failed to find DS-5 command-line debugger.'
+ echo 'Please add the path to the command-line debugger in your PATH.'
+ echo 'E.g.: export PATH=<DS-5 install dir>/bin:$PATH'
+ exit 1
+fi
+
+# DS-5 configuration database entry for Juno r0
+juno_cdb_entry='ARM Development Boards::Juno ARM Development Platform (r0)::Bare Metal Debug::Bare Metal Debug::Debug Cortex-A53_0::DSTREAM'
+
+# Browse for available DSTREAM connections and lists targets that match the
+# connection type specified in the configuration database entry
+echo "Trying to detect your DSTREAM unit..."
+connections_list=available_connections
+debugger --cdb-entry "$juno_cdb_entry" --browse \
+ | tee $connections_list
+
+# Remove first line in the file (i.e. "Available connections:")
+tail -n +2 $connections_list > ${connections_list}_stripped
+mv ${connections_list}_stripped ${connections_list}
+
+# Use first available connection
+read connection < $connections_list || true
+rm $connections_list
+
+if [ -z "$connection" ] ; then
+ echo "ERROR: Found no connection"
+ exit 1
+fi
+
+# Run DS-5 script
+echo "Connecting to $connection..."
+debugger \
+ --cdb-entry "$juno_cdb_entry" \
+ --cdb-entry-param "Connection=$connection" \
+ --stop_on_connect=false \
+ --script=$1
diff --git a/el3_payload/spin.S b/el3_payload/spin.S
new file mode 100644
index 000000000..8cf067f20
--- /dev/null
+++ b/el3_payload/spin.S
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "arch.h"
+#include "asm_macros.S"
+#include "platform.h"
+
+/* Initial value of each entry in the cpus_table[] array */
+#define NO_CPU 0xDEADDEADDEADDEAD
+
+/*
+ * Declare a per-CPU array to mark the CPUs presence.
+ *
+ * If cpus_table[i] == NO_CPU then CPU 'i' hasn't successfully booted to the
+ * to the EL3 test payload yet.
+ *
+ * Otherwise, it successfully booted (and cpus_table[i] should contain the
+ * CPU MPID).
+ */
+ .data
+ .align 3
+cpus_table:
+ .rept CPUS_COUNT
+ .quad NO_CPU
+ .endr
+
+
+ .text
+ .global mark_cpu_presence
+ .global is_cpu_present
+
+ /*
+ * void mark_cpu_presence();
+ * Mark the calling CPU present in the CPUs array.
+ * clobbers: x0, x1, x2, x9
+ */
+func mark_cpu_presence
+ /* Store masked MPID in x2 */
+ mrs x0, mpidr_el1
+ ldr x1, =MPIDR_AFFINITY_MASK
+ and x2, x0, x1
+
+ /* Store core position in x0 */
+ mov x9, x30
+ bl platform_get_core_pos
+ mov x30, x9
+
+ /* Write masked CPU MPID in the CPU entry */
+ adr x1, cpus_table
+ add x1, x1, x0, lsl #3
+ str x2, [x1]
+
+ ret
+endfunc mark_cpu_presence
+
+ /*
+ * unsigned int is_cpu_present(unsigned int core_pos);
+ * Return 0 if CPU is absent, 1 if it is present.
+ * clobbers: x0, x1
+ */
+func is_cpu_present
+ adr x1, cpus_table
+ add x1, x1, x0, lsl #3
+ ldr x0, [x1]
+
+ ldr x1, =NO_CPU
+ cmp x0, x1
+ b.eq 1f
+ mov x0, #1
+ ret
+1:
+ mov x0, #0
+ ret
+endfunc is_cpu_present
diff --git a/el3_payload/uart.S b/el3_payload/uart.S
new file mode 100644
index 000000000..b7c5e9444
--- /dev/null
+++ b/el3_payload/uart.S
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "asm_macros.S"
+#include "platform.h"
+
+/*
+ * PL011 UART registers
+ */
+/* UART Flag Register */
+#define UARTFR 0x018
+/* Transmit FIFO full bit in UARTFR register */
+#define PL011_UARTFR_TXFF_BIT 5
+/* UART Data Register */
+#define UARTDR 0x000
+
+ .text
+ .global print_string
+ .global print_char
+
+ /*
+ * void print_char(unsigned int c);
+ * clobbers: x3, x4
+ */
+func print_char
+ ldr x3, =UART_BASE
+1:
+ /* Check if the transmit FIFO is full */
+ ldr w4, [x3, #UARTFR]
+ tbnz w4, #PL011_UARTFR_TXFF_BIT, 1b
+ str w0, [x3, #UARTDR]
+ ret
+endfunc print_char
+
+ /*
+ * void print_string(const char *str);
+ * clobbers: x0, x1, x2, x9
+ */
+func print_string
+ ldr x1, =UART_BASE
+ mov x2, x0
+1:
+ ldrb w0, [x2], #1
+ cmp wzr, w0
+ b.eq 2f
+
+ mov x9, x30
+ bl print_char
+ mov x30, x9
+ b 1b
+2:
+ ret
+endfunc print_string