AArch32: Add `TRUSTED_BOARD_BOOT` support
This patch adds `TRUSTED_BOARD_BOOT` support for AArch32 mode.
To build this patch the "mbedtls/include/mbedtls/bignum.h"
needs to be modified to remove `#define MBEDTLS_HAVE_UDBL`
when `MBEDTLS_HAVE_INT32` is defined. This is a workaround
for "https://github.com/ARMmbed/mbedtls/issues/708"
NOTE: TBBR support on Juno AArch32 is not currently supported.
Change-Id: I86d80e30b9139adc4d9663f112801ece42deafcf
Signed-off-by: dp-arm <dimitris.papastamos@arm.com>
Co-Authored-By: Yatharth Kochar <yatharth.kochar@arm.com>
diff --git a/Makefile b/Makefile
index a263c4e..78860b3 100644
--- a/Makefile
+++ b/Makefile
@@ -261,6 +261,25 @@
# This can be overridden by the platform.
include lib/cpus/cpu-ops.mk
+ifeq (${ARCH},aarch32)
+NEED_BL32 := yes
+
+################################################################################
+# Build `AARCH32_SP` as BL32 image for AArch32
+################################################################################
+ifneq (${AARCH32_SP},none)
+# We expect to locate an sp.mk under the specified AARCH32_SP directory
+AARCH32_SP_MAKE := $(wildcard bl32/${AARCH32_SP}/${AARCH32_SP}.mk)
+
+ifeq (${AARCH32_SP_MAKE},)
+ $(error Error: No bl32/${AARCH32_SP}/${AARCH32_SP}.mk located)
+endif
+
+$(info Including ${AARCH32_SP_MAKE})
+include ${AARCH32_SP_MAKE}
+endif
+
+endif
################################################################################
# Check incompatible options
@@ -285,15 +304,11 @@
endif
endif
+# For AArch32, LOAD_IMAGE_V2 must be enabled.
ifeq (${ARCH},aarch32)
- # For AArch32, LOAD_IMAGE_V2 must be enabled.
ifeq (${LOAD_IMAGE_V2}, 0)
$(error "For AArch32, LOAD_IMAGE_V2 must be enabled.")
endif
- # TRUSTED_BOARD_BOOT is currently not supported for AArch32.
- ifeq (${TRUSTED_BOARD_BOOT},1)
- $(error "TRUSTED_BOARD_BOOT is currently not supported for AArch32")
- endif
endif
# When building for systems with hardware-assisted coherency, there's no need to
@@ -398,26 +413,6 @@
endif
endif
-ifeq (${ARCH},aarch32)
-NEED_BL32 := yes
-
-################################################################################
-# Build `AARCH32_SP` as BL32 image for AArch32
-################################################################################
-ifneq (${AARCH32_SP},none)
-# We expect to locate an sp.mk under the specified AARCH32_SP directory
-AARCH32_SP_MAKE := $(wildcard bl32/${AARCH32_SP}/${AARCH32_SP}.mk)
-
-ifeq (${AARCH32_SP_MAKE},)
- $(error Error: No bl32/${AARCH32_SP}/${AARCH32_SP}.mk located)
-endif
-
-$(info Including ${AARCH32_SP_MAKE})
-include ${AARCH32_SP_MAKE}
-endif
-
-endif
-
################################################################################
# Build options checks
################################################################################
diff --git a/bl1/aarch32/bl1_entrypoint.S b/bl1/aarch32/bl1_entrypoint.S
index e3d915f..39ebcf7 100644
--- a/bl1/aarch32/bl1_entrypoint.S
+++ b/bl1/aarch32/bl1_entrypoint.S
@@ -71,9 +71,21 @@
*/
/*
- * MMU needs to be disabled because both BL1 and BL2 execute
+ * Get the smc_context for next BL image,
+ * program the gp/system registers and save it in `r4`.
+ */
+ bl smc_get_next_ctx
+ mov r4, r0
+
+ /* Only turn-off MMU if going to secure world */
+ ldr r5, [r4, #SMC_CTX_SCR]
+ tst r5, #SCR_NS_BIT
+ bne skip_mmu_off
+
+ /*
+ * MMU needs to be disabled because both BL1 and BL2/BL2U execute
* in PL1, and therefore share the same address space.
- * BL2 will initialize the address space according to its
+ * BL2/BL2U will initialize the address space according to its
* own requirement.
*/
bl disable_mmu_icache_secure
@@ -81,11 +93,8 @@
dsb sy
isb
- /*
- * Get the smc_context for next BL image,
- * program the gp/system registers and exit
- * secure monitor mode
- */
- bl smc_get_next_ctx
+skip_mmu_off:
+ /* Restore smc_context from `r4` and exit secure monitor mode. */
+ mov r0, r4
monitor_exit
endfunc bl1_entrypoint
diff --git a/bl1/aarch32/bl1_exceptions.S b/bl1/aarch32/bl1_exceptions.S
index de7ddc5..f73db40 100644
--- a/bl1/aarch32/bl1_exceptions.S
+++ b/bl1/aarch32/bl1_exceptions.S
@@ -8,11 +8,18 @@
#include <asm_macros.S>
#include <bl1.h>
#include <bl_common.h>
+#include <context.h>
+#include <smcc_helpers.h>
+#include <smcc_macros.S>
+#include <xlat_tables.h>
.globl bl1_aarch32_smc_handler
func bl1_aarch32_smc_handler
+ /* On SMC entry, `sp` points to `smc_ctx_t`. Save `lr`. */
+ str lr, [sp, #SMC_CTX_LR_MON]
+
/* ------------------------------------------------
* SMC in BL1 is handled assuming that the MMU is
* turned off by BL2.
@@ -20,12 +27,12 @@
*/
/* ----------------------------------------------
- * Only RUN_IMAGE SMC is supported.
+ * Detect if this is a RUN_IMAGE or other SMC.
* ----------------------------------------------
*/
- mov r8, #BL1_SMC_RUN_IMAGE
- cmp r8, r0
- blne report_exception
+ mov lr, #BL1_SMC_RUN_IMAGE
+ cmp lr, r0
+ bne smc_handler
/* ------------------------------------------------
* Make sure only Secure world reaches here.
@@ -70,3 +77,76 @@
ldm r8, {r0, r1, r2, r3}
eret
endfunc bl1_aarch32_smc_handler
+
+ /* -----------------------------------------------------
+ * Save Secure/Normal world context and jump to
+ * BL1 SMC handler.
+ * -----------------------------------------------------
+ */
+func smc_handler
+ /* -----------------------------------------------------
+ * Save the GP registers.
+ * -----------------------------------------------------
+ */
+ smcc_save_gp_mode_regs
+
+ /*
+ * `sp` still points to `smc_ctx_t`. Save it to a register
+ * and restore the C runtime stack pointer to `sp`.
+ */
+ mov r6, sp
+ ldr sp, [r6, #SMC_CTX_SP_MON]
+
+ ldr r0, [r6, #SMC_CTX_SCR]
+ and r7, r0, #SCR_NS_BIT /* flags */
+
+ /* Switch to Secure Mode */
+ bic r0, #SCR_NS_BIT
+ stcopr r0, SCR
+ isb
+
+ /* If caller is from Secure world then turn on the MMU */
+ tst r7, #SCR_NS_BIT
+ bne skip_mmu_on
+
+ /* Turn on the MMU */
+ mov r0, #DISABLE_DCACHE
+ bl enable_mmu_secure
+
+ /* Enable the data cache. */
+ ldcopr r9, SCTLR
+ orr r9, r9, #SCTLR_C_BIT
+ stcopr r9, SCTLR
+ isb
+
+skip_mmu_on:
+ /* Prepare arguments for BL1 SMC wrapper. */
+ ldr r0, [r6, #SMC_CTX_GPREG_R0] /* smc_fid */
+ mov r1, #0 /* cookie */
+ mov r2, r6 /* handle */
+ mov r3, r7 /* flags */
+ bl bl1_smc_wrapper
+
+ /* Get the smc_context for next BL image */
+ bl smc_get_next_ctx
+ mov r4, r0
+
+ /* Only turn-off MMU if going to secure world */
+ ldr r5, [r4, #SMC_CTX_SCR]
+ tst r5, #SCR_NS_BIT
+ bne skip_mmu_off
+
+ /* Disable the MMU */
+ bl disable_mmu_icache_secure
+ stcopr r0, TLBIALL
+ dsb sy
+ isb
+
+skip_mmu_off:
+ /* -----------------------------------------------------
+ * Do the transition to next BL image.
+ * -----------------------------------------------------
+ */
+ mov r0, r4
+ monitor_exit
+endfunc smc_handler
diff --git a/bl1/bl1_fwu.c b/bl1/bl1_fwu.c
index b098532..ace364d 100644
--- a/bl1/bl1_fwu.c
+++ b/bl1/bl1_fwu.c
@@ -47,6 +47,8 @@
*/
static unsigned int sec_exec_image_id = INVALID_IMAGE_ID;
+void cm_set_next_context(void *cpu_context);
+
/*******************************************************************************
* Top level handler for servicing FWU SMCs.
******************************************************************************/
@@ -364,8 +366,10 @@
INFO("BL1-FWU: Executing Secure image\n");
+#ifdef AARCH64
/* Save NS-EL1 system registers. */
cm_el1_sysregs_context_save(NON_SECURE);
+#endif
/* Prepare the image for execution. */
bl1_prepare_next_image(image_id);
@@ -373,7 +377,11 @@
/* Update the secure image id. */
sec_exec_image_id = image_id;
+#ifdef AARCH64
*handle = cm_get_context(SECURE);
+#else
+ *handle = smc_get_ctx(SECURE);
+#endif
return 0;
}
@@ -419,6 +427,10 @@
resume_sec_state = SECURE;
}
+ INFO("BL1-FWU: Resuming %s world context\n",
+ (resume_sec_state == SECURE) ? "secure" : "normal");
+
+#ifdef AARCH64
/* Save the EL1 system registers of calling world. */
cm_el1_sysregs_context_save(caller_sec_state);
@@ -428,10 +440,16 @@
/* Update the next context. */
cm_set_next_eret_context(resume_sec_state);
- INFO("BL1-FWU: Resuming %s world context\n",
- (resume_sec_state == SECURE) ? "secure" : "normal");
-
*handle = cm_get_context(resume_sec_state);
+#else
+ /* Update the next context. */
+ cm_set_next_context(cm_get_context(resume_sec_state));
+
+ /* Prepare the smc context for the next BL image. */
+ smc_set_next_ctx(resume_sec_state);
+
+ *handle = smc_get_ctx(resume_sec_state);
+#endif
return image_param;
}
@@ -461,6 +479,8 @@
image_desc->state = IMAGE_STATE_RESET;
sec_exec_image_id = INVALID_IMAGE_ID;
+ INFO("BL1-FWU: Resuming Normal world context\n");
+#ifdef AARCH64
/*
* Secure world is done so no need to save the context.
* Just restore the Non-Secure context.
@@ -470,9 +490,16 @@
/* Update the next context. */
cm_set_next_eret_context(NON_SECURE);
- INFO("BL1-FWU: Resuming Normal world context\n");
-
*handle = cm_get_context(NON_SECURE);
+#else
+ /* Update the next context. */
+ cm_set_next_context(cm_get_context(NON_SECURE));
+
+ /* Prepare the smc context for the next BL image. */
+ smc_set_next_ctx(NON_SECURE);
+
+ *handle = smc_get_ctx(NON_SECURE);
+#endif
return 0;
}
diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c
index 71ece00..fa4f3a4 100644
--- a/bl1/bl1_main.c
+++ b/bl1/bl1_main.c
@@ -279,3 +279,20 @@
WARN("Unimplemented BL1 SMC Call: 0x%x \n", smc_fid);
SMC_RET1(handle, SMC_UNK);
}
+
+/*******************************************************************************
+ * BL1 SMC wrapper. This function is only used in AArch32 mode to ensure ABI
+ * compliance when invoking bl1_smc_handler.
+ ******************************************************************************/
+register_t bl1_smc_wrapper(uint32_t smc_fid,
+ void *cookie,
+ void *handle,
+ unsigned int flags)
+{
+ register_t x1, x2, x3, x4;
+
+ assert(handle);
+
+ get_smc_params_from_ctx(handle, x1, x2, x3, x4);
+ return bl1_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags);
+}
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 7a42c98..23e7867 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -224,9 +224,10 @@
/*******************************************************************************
* BL2 specific defines.
******************************************************************************/
-#if ARM_BL31_IN_DRAM
+#if ARM_BL31_IN_DRAM || defined(AARCH32)
/*
- * BL31 is loaded in the DRAM.
+ * For AArch32 BL31 is not applicable.
+ * For AArch64 BL31 is loaded in the DRAM.
* Put BL2 just below BL1.
*/
#define BL2_BASE (BL1_RW_BASE - PLAT_ARM_MAX_BL2_SIZE)
diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk
index 4912c90..610ccb8 100644
--- a/make_helpers/tbbr/tbbr_tools.mk
+++ b/make_helpers/tbbr/tbbr_tools.mk
@@ -75,6 +75,7 @@
$(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/scp_fw_key.crt,--scp-fw-key-cert))
endif
+ifeq (${ARCH},aarch64)
# Add the BL31 CoT (key cert + img cert + image)
$(if ${BL31},$(eval $(call CERT_ADD_CMD_OPT,${BL31},--soc-fw,true)),\
$(eval $(call CERT_ADD_CMD_OPT,$(call IMG_BIN,31),--soc-fw,true)))
@@ -83,6 +84,7 @@
$(eval $(call CERT_ADD_CMD_OPT,${BUILD_PLAT}/soc_fw_key.crt,--soc-fw-key-cert))
$(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_content.crt,--soc-fw-cert))
$(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_key.crt,--soc-fw-key-cert))
+endif
# Add the BL32 CoT (key cert + img cert + image)
ifeq (${NEED_BL32},yes)
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index afcb4b5..6a759c5 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -137,5 +137,9 @@
PLAT_BL_COMMON_SOURCES += plat/arm/board/fvp/fvp_stack_protector.c
endif
+ifeq (${ARCH},aarch32)
+ NEED_BL32 := yes
+endif
+
include plat/arm/board/common/board_common.mk
include plat/arm/common/arm_common.mk