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
This commit is contained in:
Achin Gupta 2014-02-19 17:58:33 +00:00 committed by Dan Handley
parent a3050ed521
commit 35ca35119d
8 changed files with 172 additions and 50 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -40,6 +40,12 @@
#include <runtime_svc.h>
#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.
******************************************************************************/
@ -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;
/*

View File

@ -709,6 +709,12 @@ CPUs. BL3-1 executes at EL3 and is responsible for:
service. See Section 3.3 below for details of porting the PSCI
implementation.
4. Optionally passing control to the BL3-2 image, pre-loaded at a platform-
specific address by BL2. BL3-1 exports a set of apis that allow runtime
services to specify the security state in which the next image should be
executed and run the corresponding image. BL3-1 uses the `el_change_info`
and `meminfo` structure populated by BL2 to do this.
The following functions must be implemented by the platform port to enable BL3-1
to perform the above tasks.
@ -771,16 +777,18 @@ The ARM FVP port does the following:
### Function : bl31_get_next_image_info() [mandatory]
Argument : unsigned long
Argument : unsigned int
Return : el_change_info *
This function may execute with the MMU and data caches enabled if the platform
port does the necessary initializations in `bl31_plat_arch_setup()`.
This function is called by `bl31_main()` to retrieve information provided by
BL2, so that BL3-1 can pass control to the normal world software image. This
function must return a pointer to the `el_change_info` structure (that was
copied during `bl31_early_platform_setup()`).
BL2 for the next image in the security state specified by the argument. BL3-1
uses this information to pass control to that image in the specified security
state. This function must return a pointer to the `el_change_info` structure
(that was copied during `bl31_early_platform_setup()`) if the image exists. It
should return NULL otherwise.
### Function : bl31_plat_sec_mem_layout() [mandatory]
@ -798,6 +806,21 @@ populated with the extents of secure RAM available for BL3-1 to use. See
`bl31_early_platform_setup()` above.
### Function : bl31_plat_get_bl32_mem_layout() [mandatory]
Argument : void
Return : meminfo *
This function should only be called on the cold boot path. This function may
execute with the MMU and data caches enabled if the platform port does the
necessary initializations in `bl31_plat_arch_setup()`. It is only called by the
primary CPU.
The purpose of this function is to return a pointer to a `meminfo` structure
populated with the extents of memory available for BL3-2 to use. See
`bl31_early_platform_setup()` above.
3.3 Power State Coordination Interface (in BL3-1)
------------------------------------------------

View File

@ -955,6 +955,13 @@ memory address populated by BL2.
[SMCCC].
### BL3-2 (Secure Payload) image initialization
BL2 is responsible for loading a BL3-2 image in memory specified by the platform.
BL3-1 provides an api that uses the entrypoint and memory layout information for
the BL3-2 image provided by BL2 to initialise BL3-2 in S-EL1.
### Normal world software execution
BL3-1 uses the entrypoint information provided by BL2 to jump to the normal

View File

@ -320,7 +320,6 @@ extern void runtime_exceptions(void);
extern void bl1_arch_setup(void);
extern void bl2_arch_setup(void);
extern void bl31_arch_setup(void);
extern void bl31_arch_next_el_setup(void);
#endif /*__ASSEMBLY__*/
#endif /* __ARCH_H__ */

View File

@ -41,7 +41,19 @@ extern unsigned long bl31_entrypoint;
/*******************************************************************************
* Function prototypes
******************************************************************************/
extern void bl31_next_el_arch_setup(uint32_t security_state);
extern void bl31_set_next_image_type(uint32_t type);
extern uint32_t bl31_get_next_image_type(void);
extern void bl31_prepare_next_image_entry();
extern el_change_info *bl31_get_next_image_info(uint32_t type);
extern void bl31_platform_setup(void);
extern meminfo *bl31_plat_get_bl32_mem_layout(void);
extern meminfo *bl31_plat_sec_mem_layout(void);
extern el_change_info* bl31_get_next_image_info(void);
/*
* This function is used to initialise the BL32 image. It is a weak
* declaration to cope with a system where the Secure Payload
* Dispatcher is absent.
*/
extern int32_t bl32_init(meminfo *) __attribute__ ((weak));
#endif /* __BL31_H__ */

View File

@ -72,15 +72,30 @@ meminfo *bl31_plat_sec_mem_layout(void)
return &bl2_to_bl31_args->bl31_meminfo;
}
/*******************************************************************************
* Return information about passing control to the non-trusted software images
* to common code.TODO: In the initial architecture, the image after BL31 will
* always run in the non-secure state. In the final architecture there
* will be a series of images. This function will need enhancement then
******************************************************************************/
el_change_info *bl31_get_next_image_info(void)
meminfo *bl31_plat_get_bl32_mem_layout(void)
{
return &bl2_to_bl31_args->bl33_image_info;
return &bl2_to_bl31_args->bl32_meminfo;
}
/*******************************************************************************
* Return a pointer to the 'el_change_info' structure of the next image for the
* security state specified. BL33 corresponds to the non-secure image type
* while BL32 corresponds to the secure image type. A NULL pointer is returned
* if the image does not exist.
******************************************************************************/
el_change_info *bl31_get_next_image_info(uint32_t type)
{
el_change_info *next_image_info;
next_image_info = (type == NON_SECURE) ?
&bl2_to_bl31_args->bl33_image_info :
&bl2_to_bl31_args->bl32_image_info;
/* None of the images on this platform can have 0x0 as the entrypoint */
if (next_image_info->entrypoint)
return next_image_info;
else
return NULL;
}
/*******************************************************************************