diff options
author | Achin Gupta <achin.gupta@arm.com> | 2014-02-19 17:58:33 +0000 |
---|---|---|
committer | Dan Handley <dan.handley@arm.com> | 2014-02-20 19:06:34 +0000 |
commit | 35ca35119d9dc51f1665184ab6db5e2861c213b4 (patch) | |
tree | ad063c1d5bb7b529603570e53a17340d53d19c8b /bl31 | |
parent | a3050ed521ec1fd6d34d7d8ba5105ac8bc024992 (diff) |
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
Diffstat (limited to 'bl31')
-rw-r--r-- | bl31/aarch64/bl31_arch_setup.c | 34 | ||||
-rw-r--r-- | bl31/aarch64/bl31_entrypoint.S | 12 | ||||
-rw-r--r-- | bl31/bl31_main.c | 92 |
3 files changed, 102 insertions, 36 deletions
diff --git a/bl31/aarch64/bl31_arch_setup.c b/bl31/aarch64/bl31_arch_setup.c index 492c45bb..03b9623c 100644 --- a/bl31/aarch64/bl31_arch_setup.c +++ b/bl31/aarch64/bl31_arch_setup.c @@ -73,10 +73,12 @@ void bl31_arch_setup(void) } /******************************************************************************* - * Detect what is the next Non-Secure EL and setup the required architectural - * state + * Detect what the security state of the next EL is and setup the minimum + * required architectural state: program SCTRL to reflect the RES1 bits, and to + * have MMU and caches disabled ******************************************************************************/ -void bl31_arch_next_el_setup(void) { +void bl31_next_el_arch_setup(uint32_t security_state) +{ unsigned long id_aa64pfr0 = read_id_aa64pfr0_el1(); unsigned long current_sctlr, next_sctlr; unsigned long el_status; @@ -89,16 +91,20 @@ void bl31_arch_next_el_setup(void) { /* Find out which EL we are going to */ el_status = (id_aa64pfr0 >> ID_AA64PFR0_EL2_SHIFT) & ID_AA64PFR0_ELX_MASK; - /* Check what if EL2 is supported */ - if (el_status && (scr & SCR_HCE_BIT)) { - /* Set SCTLR EL2 */ - next_sctlr |= SCTLR_EL2_RES1; - - write_sctlr_el2(next_sctlr); - } else { - /* Set SCTLR Non-Secure EL1 */ - next_sctlr |= SCTLR_EL1_RES1; - - write_sctlr_el1(next_sctlr); + if (security_state == NON_SECURE) { + /* Check if EL2 is supported */ + if (el_status && (scr & SCR_HCE_BIT)) { + /* Set SCTLR EL2 */ + next_sctlr |= SCTLR_EL2_RES1; + write_sctlr_el2(next_sctlr); + return; + } } + + /* + * SCTLR_EL1 needs the same programming irrespective of the + * security state of EL1. + */ + next_sctlr |= SCTLR_EL1_RES1; + write_sctlr_el1(next_sctlr); } diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S index c72b3633..97f59f3e 100644 --- a/bl31/aarch64/bl31_entrypoint.S +++ b/bl31/aarch64/bl31_entrypoint.S @@ -166,18 +166,6 @@ bl31_entrypoint: ; .type bl31_entrypoint, %function */ bl bl31_main - /* --------------------------------------------- - * Use the more complex exception vectors now - * that context management is setup. SP_EL3 is - * pointing to a 'cpu_context' structure which - * has an exception stack allocated. Since - * we're just about to leave this EL with ERET, - * we don't need an ISB here - * --------------------------------------------- - */ - adr x1, runtime_exceptions - msr vbar_el3, x1 - zero_callee_saved_regs b el3_exit 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 @@ -41,6 +41,12 @@ #include <context_mgmt.h> /******************************************************************************* + * 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. ******************************************************************************/ void bl31_lib_init() @@ -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(); @@ -80,15 +87,80 @@ void bl31_main(void) 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; /* |