aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSandrine Bailleux <sandrine.bailleux@arm.com>2015-11-26 16:31:34 +0000
committerAchin Gupta <achin.gupta@arm.com>2015-11-26 21:32:04 +0000
commit4c117f6c49330682cabdbf6d082e7c02dd32e84b (patch)
treeb7cc8fc019dda1562d0712a0e413e7518da69070
parent862b5dc2d1f45b0195678dcb6556b0721444505f (diff)
downloadplatform_external_arm-trusted-firmware-4c117f6c49330682cabdbf6d082e7c02dd32e84b.tar.gz
platform_external_arm-trusted-firmware-4c117f6c49330682cabdbf6d082e7c02dd32e84b.tar.bz2
platform_external_arm-trusted-firmware-4c117f6c49330682cabdbf6d082e7c02dd32e84b.zip
CSS: Enable booting of EL3 payloads
This patch adds support for booting EL3 payloads on CSS platforms, for example Juno. In this scenario, the Trusted Firmware follows its normal boot flow up to the point where it would normally pass control to the BL31 image. At this point, it jumps to the EL3 payload entry point address instead. Before handing over to the EL3 payload, the data SCP writes for AP at the beginning of the Trusted SRAM is restored, i.e. we zero the first 128 bytes and restore the SCP Boot configuration. The latter is saved before transferring the BL30 image to SCP and is restored just after the transfer (in BL2). The goal is to make it appear that the EL3 payload is the first piece of software to run on the target. The BL31 entrypoint info structure is updated to make the primary CPU jump to the EL3 payload instead of the BL31 image. The mailbox is populated with the EL3 payload entrypoint address, which releases the secondary CPUs out of their holding pen (if the SCP has powered them on). The arm_program_trusted_mailbox() function has been exported for this purpose. The TZC-400 configuration in BL2 is simplified: it grants secure access only to the whole DRAM. Other security initialization is unchanged. This alternative boot flow is disabled by default. A new build option EL3_PAYLOAD_BASE has been introduced to enable it and provide the EL3 payload's entry point address. The build system has been modified such that BL31 and BL33 are not compiled and/or not put in the FIP in this case, as those images are not used in this boot flow. Change-Id: Id2e26fa57988bbc32323a0effd022ab42f5b5077
-rw-r--r--Makefile17
-rw-r--r--bl2/bl2_main.c19
-rw-r--r--docs/porting-guide.md9
-rw-r--r--include/plat/arm/common/plat_arm.h1
-rw-r--r--plat/arm/common/arm_bl1_setup.c14
-rw-r--r--plat/arm/common/arm_common.mk5
-rw-r--r--plat/arm/common/arm_pm.c2
-rw-r--r--plat/arm/common/arm_security.c14
-rw-r--r--plat/arm/css/common/css_bl2_setup.c39
9 files changed, 114 insertions, 6 deletions
diff --git a/Makefile b/Makefile
index c3252c23b..80e05fa63 100644
--- a/Makefile
+++ b/Makefile
@@ -235,6 +235,10 @@ INCLUDE_TBBR_MK := 1
################################################################################
ifneq (${SPD},none)
+ifdef EL3_PAYLOAD_BASE
+ $(warning "SPD and EL3_PAYLOAD_BASE are incompatible build options.")
+ $(warning "The SPD and its BL32 companion will be present but ignored.")
+endif
# We expect to locate an spd.mk under the specified SPD directory
SPD_MAKE := $(shell m="services/spd/${SPD}/${SPD}.mk"; [ -f "$$m" ] && echo "$$m")
@@ -300,7 +304,12 @@ endif
# supplied for the FIP and Certificate generation tools. This flag can be
# overridden by the platform.
ifdef BL2_SOURCES
+ifndef EL3_PAYLOAD_BASE
NEED_BL33 ?= yes
+else
+# The BL33 image is not needed when booting an EL3 payload.
+NEED_BL33 := no
+endif
endif
# Process TBB related flags
@@ -375,6 +384,10 @@ $(eval $(call add_define,PSCI_EXTENDED_STATE_ID))
$(eval $(call add_define,ERROR_DEPRECATED))
$(eval $(call add_define,ENABLE_PLAT_COMPAT))
$(eval $(call add_define,SPIN_ON_BL1_EXIT))
+# Define the EL3_PAYLOAD_BASE flag only if it is provided.
+ifdef EL3_PAYLOAD_BASE
+$(eval $(call add_define,EL3_PAYLOAD_BASE))
+endif
################################################################################
@@ -392,9 +405,13 @@ include bl2/bl2.mk
endif
ifdef BL31_SOURCES
+# When booting an EL3 payload, there is no need to compile the BL31 image nor
+# put it in the FIP.
+ifndef EL3_PAYLOAD_BASE
NEED_BL31 := yes
include bl31/bl31.mk
endif
+endif
################################################################################
diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
index f8a2372fe..a3f016f9c 100644
--- a/bl2/bl2_main.c
+++ b/bl2/bl2_main.c
@@ -83,6 +83,7 @@ static int load_bl30(void)
return e;
}
+#ifndef EL3_PAYLOAD_BASE
/*******************************************************************************
* Load the BL3-1 image.
* The bl2_to_bl31_params and bl31_ep_info params will be updated with the
@@ -190,6 +191,7 @@ static int load_bl33(bl31_params_t *bl2_to_bl31_params)
return e;
}
+#endif /* EL3_PAYLOAD_BASE */
/*******************************************************************************
* The only thing to do in BL2 is to load further images and pass control to
@@ -232,6 +234,22 @@ void bl2_main(void)
bl2_to_bl31_params = bl2_plat_get_bl31_params();
bl31_ep_info = bl2_plat_get_bl31_ep_info();
+#ifdef EL3_PAYLOAD_BASE
+ /*
+ * In the case of an EL3 payload, we don't need to load any further
+ * images. Just update the BL31 entrypoint info structure to make BL1
+ * jump to the EL3 payload.
+ * The pointer to the memory the platform has set aside to pass
+ * information to BL3-1 in the normal boot flow is reused here, even
+ * though only a fraction of the information contained in the
+ * bl31_params_t structure makes sense in the context of EL3 payloads.
+ * This will be refined in the future.
+ */
+ VERBOSE("BL2: Populating the entrypoint info for the EL3 payload\n");
+ bl31_ep_info->pc = EL3_PAYLOAD_BASE;
+ bl31_ep_info->args.arg0 = (unsigned long) bl2_to_bl31_params;
+ bl2_plat_set_bl31_ep_info(NULL, bl31_ep_info);
+#else
e = load_bl31(bl2_to_bl31_params, bl31_ep_info);
if (e) {
ERROR("Failed to load BL3-1 (%i)\n", e);
@@ -253,6 +271,7 @@ void bl2_main(void)
ERROR("Failed to load BL3-3 (%i)\n", e);
plat_error_handler(e);
}
+#endif /* EL3_PAYLOAD_BASE */
/* Flush the params to be passed to memory */
bl2_plat_flush_bl31_params();
diff --git a/docs/porting-guide.md b/docs/porting-guide.md
index 2c828c271..5e823e815 100644
--- a/docs/porting-guide.md
+++ b/docs/porting-guide.md
@@ -1001,10 +1001,13 @@ structure in BL2 memory.
Argument : image_info *, entry_point_info *
Return : void
-This function is called after loading BL3-1 image and it can be used to
-overwrite the entry point set by loader and also set the security state
-and SPSR which represents the entry point system state for BL3-1.
+In the normal boot flow, this function is called after loading BL3-1 image and
+it can be used to overwrite the entry point set by loader and also set the
+security state and SPSR which represents the entry point system state for BL3-1.
+When booting an EL3 payload instead, this function is called after populating
+its entry point address and can be used for the same purpose for the payload
+image. It receives a null pointer as its first argument in this case.
### Function : bl2_plat_set_bl32_ep_info() [mandatory]
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 044e18ef7..aadf58d83 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -149,6 +149,7 @@ int arm_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state);
int arm_validate_ns_entrypoint(uintptr_t entrypoint);
void arm_system_pwr_domain_resume(void);
+void arm_program_trusted_mailbox(uintptr_t address);
/* Topology utility function */
int arm_check_mpidr(u_register_t mpidr);
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index ddf383fe2..887223cf4 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -145,6 +145,20 @@ void bl1_platform_setup(void)
arm_bl1_platform_setup();
}
+void bl1_plat_prepare_exit(entry_point_info_t *ep_info)
+{
+#ifdef EL3_PAYLOAD_BASE
+ /*
+ * Program the EL3 payload's entry point address into the CPUs mailbox
+ * in order to release secondary CPUs from their holding pen and make
+ * them jump there.
+ */
+ arm_program_trusted_mailbox(ep_info->pc);
+ dsbsy();
+ sev();
+#endif
+}
+
/*******************************************************************************
* Before calling this function BL2 is loaded in memory and its entrypoint
* is set by load_image. This is a placeholder for the platform to change
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index eb5ae1116..7b2352759 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -81,6 +81,11 @@ BL1_SOURCES += drivers/arm/cci/cci.c \
plat/arm/common/arm_bl1_setup.c \
plat/arm/common/arm_io_storage.c \
plat/common/aarch64/platform_up_stack.S
+ifdef EL3_PAYLOAD_BASE
+# Need the arm_program_trusted_mailbox() function to release secondary CPUs from
+# their holding pen
+BL1_SOURCES += plat/arm/common/arm_pm.c
+endif
BL2_SOURCES += drivers/arm/tzc400/tzc400.c \
drivers/io/io_fip.c \
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c
index d13d2683c..cae65970f 100644
--- a/plat/arm/common/arm_pm.c
+++ b/plat/arm/common/arm_pm.c
@@ -175,7 +175,7 @@ void arm_system_pwr_domain_resume(void)
* from reset. This function assumes that the Trusted mail box base is within
* the ARM_SHARED_RAM region
******************************************************************************/
-static void arm_program_trusted_mailbox(uintptr_t address)
+void arm_program_trusted_mailbox(uintptr_t address)
{
uintptr_t *mailbox = (void *) PLAT_ARM_TRUSTED_MAILBOX_BASE;
diff --git a/plat/arm/common/arm_security.c b/plat/arm/common/arm_security.c
index 990d8d4a6..8b46aaedd 100644
--- a/plat/arm/common/arm_security.c
+++ b/plat/arm/common/arm_security.c
@@ -40,8 +40,13 @@
/*******************************************************************************
* Initialize the TrustZone Controller for ARM standard platforms.
- * Configure Region 0 with no access, Region 1 with secure access only, and
- * the remaining DRAM regions access from the given Non-Secure masters.
+ * Configure:
+ * - Region 0 with no access;
+ * - Region 1 with secure access only;
+ * - the remaining DRAM regions access from the given Non-Secure masters.
+ *
+ * When booting an EL3 payload, this is simplified: we configure region 0 with
+ * secure access only and do not enable any other region.
******************************************************************************/
void arm_tzc_setup(void)
{
@@ -52,6 +57,7 @@ void arm_tzc_setup(void)
/* Disable filters. */
tzc_disable_filters();
+#ifndef EL3_PAYLOAD_BASE
/* Region 0 set to no access by default */
tzc_configure_region0(TZC_REGION_S_NONE, 0);
@@ -73,6 +79,10 @@ void arm_tzc_setup(void)
ARM_DRAM2_BASE, ARM_DRAM2_END,
TZC_REGION_S_NONE,
PLAT_ARM_TZC_NS_DEV_ACCESS);
+#else
+ /* Allow secure access only to DRAM for EL3 payloads. */
+ tzc_configure_region0(TZC_REGION_S_RDWR, 0);
+#endif /* EL3_PAYLOAD_BASE */
/*
* Raise an exception if a NS device tries to access secure memory
diff --git a/plat/arm/css/common/css_bl2_setup.c b/plat/arm/css/common/css_bl2_setup.c
index 2e423d962..6054f7a56 100644
--- a/plat/arm/css/common/css_bl2_setup.c
+++ b/plat/arm/css/common/css_bl2_setup.c
@@ -29,7 +29,11 @@
*/
#include <bl_common.h>
+#include <css_def.h>
#include <debug.h>
+#include <mmio.h>
+#include <plat_arm.h>
+#include <string.h>
#include "css_scp_bootloader.h"
/* Weak definition may be overridden in specific CSS based platform */
@@ -55,3 +59,38 @@ int bl2_plat_handle_bl30(image_info_t *bl30_image_info)
return ret;
}
+
+#ifdef EL3_PAYLOAD_BASE
+/*
+ * We need to override some of the platform functions when booting an EL3
+ * payload.
+ */
+
+static unsigned int scp_boot_config;
+
+void bl2_early_platform_setup(meminfo_t *mem_layout)
+{
+ arm_bl2_early_platform_setup(mem_layout);
+
+ /* Save SCP Boot config before it gets overwritten by BL30 loading */
+ scp_boot_config = mmio_read_32(SCP_BOOT_CFG_ADDR);
+ VERBOSE("BL2: Saved SCP Boot config = 0x%x\n", scp_boot_config);
+}
+
+void bl2_platform_setup(void)
+{
+ arm_bl2_platform_setup();
+
+ /*
+ * Before releasing the AP cores out of reset, the SCP writes some data
+ * at the beginning of the Trusted SRAM. It is is overwritten before
+ * reaching this function. We need to restore this data, as if the
+ * target had just come out of reset. This implies:
+ * - zeroing the first 128 bytes of Trusted SRAM;
+ * - restoring the SCP boot configuration.
+ */
+ VERBOSE("BL2: Restoring SCP reset data in Trusted SRAM\n");
+ memset((void *) ARM_TRUSTED_SRAM_BASE, 0, 128);
+ mmio_write_32(SCP_BOOT_CFG_ADDR, scp_boot_config);
+}
+#endif /* EL3_PAYLOAD_BASE */