From 35ca35119d9dc51f1665184ab6db5e2861c213b4 Mon Sep 17 00:00:00 2001 From: Achin Gupta Date: Wed, 19 Feb 2014 17:58:33 +0000 Subject: Add support for BL3-2 in BL3-1 This patch adds the following support to the BL3-1 stage: 1. BL3-1 allows runtime services to specify and determine the security state of the next image after BL3-1. This has been done by adding the `bl31_set_next_image_type()` & `bl31_get_next_image_type()` apis. The default security state is non-secure. The platform api `bl31_get_next_image_info()` has been modified to let the platform decide which is the next image in the desired security state. 2. BL3-1 exports the `bl31_prepare_next_image_entry()` function to program entry into the target security state. It uses the apis introduced in 1. to do so. 3. BL3-1 reads the information populated by BL2 about the BL3-2 image into its internal data structures. 4. BL3-1 introduces a weakly defined reference `bl32_init()` to allow initialisation of a BL3-2 image. A runtime service like the Secure payload dispatcher will define this function if present. Change-Id: Icc46dcdb9e475ce6575dd3f9a5dc7a48a83d21d1 --- bl31/bl31_main.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 82 insertions(+), 10 deletions(-) (limited to 'bl31/bl31_main.c') diff --git a/bl31/bl31_main.c b/bl31/bl31_main.c index 9d2dc299..ea44871c 100644 --- a/bl31/bl31_main.c +++ b/bl31/bl31_main.c @@ -40,6 +40,12 @@ #include #include +/******************************************************************************* + * Variable to indicate whether next image to execute after BL31 is BL33 + * (non-secure & default) or BL32 (secure). + ******************************************************************************/ +static uint32_t next_image_type = NON_SECURE; + /******************************************************************************* * Simple function to initialise all BL31 helper libraries. ******************************************************************************/ @@ -50,16 +56,17 @@ void bl31_lib_init() /******************************************************************************* * BL31 is responsible for setting up the runtime services for the primary cpu - * before passing control to the bootloader (UEFI) or Linux. This function calls - * runtime_svc_init() which initializes all registered runtime services. The run - * time services would setup enough context for the core to swtich to the next - * exception level. When this function returns, the core will switch to the - * programmed exception level via. an ERET. + * before passing control to the bootloader or an Operating System. This + * function calls runtime_svc_init() which initializes all registered runtime + * services. The run time services would setup enough context for the core to + * swtich to the next exception level. When this function returns, the core will + * switch to the programmed exception level via. an ERET. ******************************************************************************/ void bl31_main(void) { - el_change_info *next_image_info; - uint32_t scr; +#if DEBUG + unsigned long mpidr = read_mpidr(); +#endif /* Perform remaining generic architectural setup from EL3 */ bl31_arch_setup(); @@ -79,16 +86,81 @@ void bl31_main(void) /* Clean caches before re-entering normal world */ dcsw_op_all(DCCSW); + /* + * Use the more complex exception vectors now that context + * management is setup. SP_EL3 should point to a 'cpu_context' + * structure which has an exception stack allocated. The PSCI + * service should have set the context. + */ + assert(cm_get_context(mpidr, NON_SECURE)); + cm_set_next_eret_context(NON_SECURE); + write_vbar_el3((uint64_t) runtime_exceptions); + + /* + * All the cold boot actions on the primary cpu are done. We + * now need to decide which is the next image (BL32 or BL33) + * and how to execute it. If the SPD runtime service is + * present, it would want to pass control to BL32 first in + * S-EL1. It will export the bl32_init() routine where it takes + * responsibility of entering S-EL1 and returning control back + * to bl31_main. Once this is done we can prepare entry into + * BL33 as normal. + */ + + /* Tell BL32 about it memory extents as well */ + if (bl32_init) + bl32_init(bl31_plat_get_bl32_mem_layout()); + + /* + * We are ready to enter the next EL. Prepare entry into the image + * corresponding to the desired security state after the next ERET. + */ + bl31_prepare_next_image_entry(); +} + +/******************************************************************************* + * Accessor functions to help runtime services decide which image should be + * executed after BL31. This is BL33 or the non-secure bootloader image by + * default but the Secure payload dispatcher could override this by requesting + * an entry into BL32 (Secure payload) first. If it does so then it should use + * the same API to program an entry into BL33 once BL32 initialisation is + * complete. + ******************************************************************************/ +void bl31_set_next_image_type(uint32_t security_state) +{ + assert(security_state == NON_SECURE || security_state == SECURE); + next_image_type = security_state; +} + +uint32_t bl31_get_next_image_type(void) +{ + return next_image_type; +} + +/******************************************************************************* + * This function programs EL3 registers and performs other setup to enable entry + * into the next image after BL31 at the next ERET. + ******************************************************************************/ +void bl31_prepare_next_image_entry() +{ + el_change_info *next_image_info; + uint32_t scr, image_type; + + /* Determine which image to execute next */ + image_type = bl31_get_next_image_type(); + /* * Setup minimal architectural state of the next highest EL to * allow execution in it immediately upon entering it. */ - bl31_arch_next_el_setup(); + bl31_next_el_arch_setup(image_type); /* Program EL3 registers to enable entry into the next EL */ - next_image_info = bl31_get_next_image_info(); + next_image_info = bl31_get_next_image_info(image_type); + assert(next_image_info); + scr = read_scr(); - if (next_image_info->security_state == NON_SECURE) + if (image_type == NON_SECURE) scr |= SCR_NS_BIT; /* -- cgit v1.2.3