mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-15 09:04:17 +00:00
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:
parent
a3050ed521
commit
35ca35119d
8 changed files with 172 additions and 50 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
|
@ -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)
|
||||
------------------------------------------------
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
Loading…
Add table
Reference in a new issue