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/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);
+}