mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-23 13:36:05 +00:00
Add support for BL3-0 image
- Add support for loading a BL3-0 image in BL2. Information about memory extents is populated by platform-specific code. Subsequent handling of BL3-0 is also platform specific. The BL2 main function has been broken down to improve readability. The BL3-2 image is now loaded before the BL3-3 image to align with the boot flow. - Build system: Add support for specifying a BL3-0 image that will be included into the FIP image. - IO FIP driver: Add support for identifying a BL3-0 image inside a FIP image. - Update the documentation to reflect the above changes. Change-Id: I067c184afd52ccaa86569f13664757570c86fc48
This commit is contained in:
parent
a1b6db6c62
commit
93d81d64d3
6 changed files with 259 additions and 88 deletions
18
Makefile
18
Makefile
|
@ -407,7 +407,23 @@ ifeq (${NEED_BL32},yes)
|
|||
$(eval $(call MAKE_BL,32,in_fip))
|
||||
endif
|
||||
|
||||
${BUILD_PLAT}/fip.bin: ${FIP_DEPS} ${BL33} ${FIPTOOL}
|
||||
ifeq (${NEED_BL30},yes)
|
||||
FIP_DEPS += ${BL30}
|
||||
FIP_ARGS += --bl30 ${BL30}
|
||||
endif
|
||||
|
||||
ifeq (${NEED_BL30},yes)
|
||||
# If BL3-0 is needed by the platform then 'BL30' variable must be defined.
|
||||
check_bl30:
|
||||
$(if ${BL30},,$(error "To build a FIP for platform ${PLAT}, please set BL30 to point to the SCP firmware"))
|
||||
else
|
||||
# If BL3-0 is not needed by the platform but the user still specified the path
|
||||
# to a BL3-0 image then warn him that it will be ignored.
|
||||
check_bl30:
|
||||
$(if ${BL30},$(warning "BL3-0 is not supported on platform ${PLAT}, it will just be ignored"),)
|
||||
endif
|
||||
|
||||
${BUILD_PLAT}/fip.bin: ${FIP_DEPS} ${BL33} ${FIPTOOL} check_bl30
|
||||
$(if ${BL33},,$(error "To build a FIP, please set BL33 to point to the Normal World binary, eg: BL33=../uefi/FVP_AARCH64_EFI.fd"))
|
||||
${Q}${FIPTOOL} --dump \
|
||||
${FIP_ARGS} \
|
||||
|
|
213
bl2/bl2_main.c
213
bl2/bl2_main.c
|
@ -38,40 +38,63 @@
|
|||
#include <stdio.h>
|
||||
#include "bl2_private.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Load the BL3-0 image if there's one.
|
||||
* If a platform does not want to attempt to load BL3-0 image it must leave
|
||||
* BL30_BASE undefined.
|
||||
* Return 0 on success or if there's no BL3-0 image to load, a negative error
|
||||
* code otherwise.
|
||||
******************************************************************************/
|
||||
static int load_bl30(void)
|
||||
{
|
||||
int e = 0;
|
||||
#ifdef BL30_BASE
|
||||
meminfo_t bl30_mem_info;
|
||||
image_info_t bl30_image_info;
|
||||
|
||||
/*
|
||||
* It is up to the platform to specify where BL3-0 should be loaded if
|
||||
* it exists. It could create space in the secure sram or point to a
|
||||
* completely different memory.
|
||||
*
|
||||
* The entry point information is not relevant in this case as the AP
|
||||
* won't execute the BL3-0 image.
|
||||
*/
|
||||
bl2_plat_get_bl30_meminfo(&bl30_mem_info);
|
||||
e = load_image(&bl30_mem_info,
|
||||
BL30_IMAGE_NAME,
|
||||
BL30_BASE,
|
||||
&bl30_image_info,
|
||||
NULL);
|
||||
|
||||
if (e == 0) {
|
||||
/* The subsequent handling of BL3-0 is platform specific */
|
||||
bl2_plat_handle_bl30(&bl30_image_info);
|
||||
}
|
||||
#endif /* BL30_BASE */
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* The only thing to do in BL2 is to load further images and pass control to
|
||||
* BL3-1. The memory occupied by BL2 will be reclaimed by BL3-x stages. BL2 runs
|
||||
* entirely in S-EL1.
|
||||
* Load the BL3-1 image.
|
||||
* The bl2_to_bl31_params and bl31_ep_info params will be updated with the
|
||||
* relevant BL3-1 information.
|
||||
* Return 0 on success, a negative error code otherwise.
|
||||
******************************************************************************/
|
||||
void bl2_main(void)
|
||||
static int load_bl31(bl31_params_t *bl2_to_bl31_params,
|
||||
entry_point_info_t *bl31_ep_info)
|
||||
{
|
||||
meminfo_t *bl2_tzram_layout;
|
||||
bl31_params_t *bl2_to_bl31_params;
|
||||
entry_point_info_t *bl31_ep_info;
|
||||
meminfo_t bl32_mem_info;
|
||||
meminfo_t bl33_mem_info;
|
||||
int e;
|
||||
|
||||
/* Perform remaining generic architectural setup in S-El1 */
|
||||
bl2_arch_setup();
|
||||
|
||||
/* Perform platform setup in BL1 */
|
||||
bl2_platform_setup();
|
||||
|
||||
printf("BL2 %s\n\r", build_message);
|
||||
assert(bl2_to_bl31_params != NULL);
|
||||
assert(bl31_ep_info != NULL);
|
||||
|
||||
/* Find out how much free trusted ram remains after BL2 load */
|
||||
bl2_tzram_layout = bl2_plat_sec_mem_layout();
|
||||
|
||||
/*
|
||||
* Get a pointer to the memory the platform has set aside to pass
|
||||
* information to BL31.
|
||||
*/
|
||||
bl2_to_bl31_params = bl2_plat_get_bl31_params();
|
||||
bl31_ep_info = bl2_plat_get_bl31_ep_info();
|
||||
|
||||
/* Set the X0 parameter to bl31 */
|
||||
/* Set the X0 parameter to BL3-1 */
|
||||
bl31_ep_info->args.arg0 = (unsigned long)bl2_to_bl31_params;
|
||||
|
||||
/* Load the BL3-1 image */
|
||||
|
@ -81,42 +104,34 @@ void bl2_main(void)
|
|||
bl2_to_bl31_params->bl31_image_info,
|
||||
bl31_ep_info);
|
||||
|
||||
/* Assert if it has not been possible to load BL31 */
|
||||
if (e) {
|
||||
ERROR("Failed to load BL3-1.\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
if (e == 0)
|
||||
bl2_plat_set_bl31_ep_info(bl2_to_bl31_params->bl31_image_info,
|
||||
bl31_ep_info);
|
||||
|
||||
bl2_plat_get_bl33_meminfo(&bl33_mem_info);
|
||||
|
||||
/* Load the BL33 image in non-secure memory provided by the platform */
|
||||
e = load_image(&bl33_mem_info,
|
||||
BL33_IMAGE_NAME,
|
||||
plat_get_ns_image_entrypoint(),
|
||||
bl2_to_bl31_params->bl33_image_info,
|
||||
bl2_to_bl31_params->bl33_ep_info);
|
||||
|
||||
/* Halt if failed to load normal world firmware. */
|
||||
if (e) {
|
||||
ERROR("Failed to load BL3-3.\n");
|
||||
panic();
|
||||
}
|
||||
bl2_plat_set_bl33_ep_info(bl2_to_bl31_params->bl33_image_info,
|
||||
bl2_to_bl31_params->bl33_ep_info);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Load the BL3-2 image if there's one.
|
||||
* The bl2_to_bl31_params param will be updated with the relevant BL3-2
|
||||
* information.
|
||||
* If a platform does not want to attempt to load BL3-2 image it must leave
|
||||
* BL32_BASE undefined.
|
||||
* Return 0 on success or if there's no BL3-2 image to load, a negative error
|
||||
* code otherwise.
|
||||
******************************************************************************/
|
||||
static int load_bl32(bl31_params_t *bl2_to_bl31_params)
|
||||
{
|
||||
int e = 0;
|
||||
#ifdef BL32_BASE
|
||||
meminfo_t bl32_mem_info;
|
||||
|
||||
assert(bl2_to_bl31_params != NULL);
|
||||
|
||||
/*
|
||||
* Load the BL32 image if there's one. It is upto to platform
|
||||
* to specify where BL32 should be loaded if it exists. It
|
||||
* could create space in the secure sram or point to a
|
||||
* It is up to the platform to specify where BL3-2 should be loaded if
|
||||
* it exists. It could create space in the secure sram or point to a
|
||||
* completely different memory.
|
||||
*
|
||||
* If a platform does not want to attempt to load BL3-2 image
|
||||
* it must leave BL32_BASE undefined
|
||||
*/
|
||||
bl2_plat_get_bl32_meminfo(&bl32_mem_info);
|
||||
e = load_image(&bl32_mem_info,
|
||||
|
@ -125,23 +140,103 @@ void bl2_main(void)
|
|||
bl2_to_bl31_params->bl32_image_info,
|
||||
bl2_to_bl31_params->bl32_ep_info);
|
||||
|
||||
/* Issue a diagnostic if no Secure Payload could be loaded */
|
||||
if (e) {
|
||||
WARN("Failed to load BL3-2.\n");
|
||||
} else {
|
||||
if (e == 0) {
|
||||
bl2_plat_set_bl32_ep_info(
|
||||
bl2_to_bl31_params->bl32_image_info,
|
||||
bl2_to_bl31_params->bl32_ep_info);
|
||||
}
|
||||
#endif /* BL32_BASE */
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Load the BL3-3 image.
|
||||
* The bl2_to_bl31_params param will be updated with the relevant BL3-3
|
||||
* information.
|
||||
* Return 0 on success, a negative error code otherwise.
|
||||
******************************************************************************/
|
||||
static int load_bl33(bl31_params_t *bl2_to_bl31_params)
|
||||
{
|
||||
meminfo_t bl33_mem_info;
|
||||
int e;
|
||||
|
||||
assert(bl2_to_bl31_params != NULL);
|
||||
|
||||
bl2_plat_get_bl33_meminfo(&bl33_mem_info);
|
||||
|
||||
/* Load the BL3-3 image in non-secure memory provided by the platform */
|
||||
e = load_image(&bl33_mem_info,
|
||||
BL33_IMAGE_NAME,
|
||||
plat_get_ns_image_entrypoint(),
|
||||
bl2_to_bl31_params->bl33_image_info,
|
||||
bl2_to_bl31_params->bl33_ep_info);
|
||||
|
||||
if (e == 0)
|
||||
bl2_plat_set_bl33_ep_info(bl2_to_bl31_params->bl33_image_info,
|
||||
bl2_to_bl31_params->bl33_ep_info);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* The only thing to do in BL2 is to load further images and pass control to
|
||||
* BL3-1. The memory occupied by BL2 will be reclaimed by BL3-x stages. BL2 runs
|
||||
* entirely in S-EL1.
|
||||
******************************************************************************/
|
||||
void bl2_main(void)
|
||||
{
|
||||
bl31_params_t *bl2_to_bl31_params;
|
||||
entry_point_info_t *bl31_ep_info;
|
||||
int e;
|
||||
|
||||
/* Perform remaining generic architectural setup in S-EL1 */
|
||||
bl2_arch_setup();
|
||||
|
||||
/* Perform platform setup in BL2 */
|
||||
bl2_platform_setup();
|
||||
|
||||
printf("BL2 %s\n\r", build_message);
|
||||
|
||||
/*
|
||||
* Load the subsequent bootloader images
|
||||
*/
|
||||
e = load_bl30();
|
||||
if (e) {
|
||||
ERROR("Failed to load BL3-0 (%i)\n", e);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a pointer to the memory the platform has set aside to pass
|
||||
* information to BL3-1.
|
||||
*/
|
||||
bl2_to_bl31_params = bl2_plat_get_bl31_params();
|
||||
bl31_ep_info = bl2_plat_get_bl31_ep_info();
|
||||
|
||||
e = load_bl31(bl2_to_bl31_params, bl31_ep_info);
|
||||
if (e) {
|
||||
ERROR("Failed to load BL3-1 (%i)\n", e);
|
||||
panic();
|
||||
}
|
||||
|
||||
e = load_bl32(bl2_to_bl31_params);
|
||||
if (e)
|
||||
WARN("Failed to load BL3-2 (%i)\n", e);
|
||||
|
||||
e = load_bl33(bl2_to_bl31_params);
|
||||
if (e) {
|
||||
ERROR("Failed to load BL3-3 (%i)\n", e);
|
||||
panic();
|
||||
}
|
||||
|
||||
/* Flush the params to be passed to memory */
|
||||
bl2_plat_flush_bl31_params();
|
||||
|
||||
/*
|
||||
* Run BL31 via an SMC to BL1. Information on how to pass control to
|
||||
* the BL32 (if present) and BL33 software images will be passed to
|
||||
* BL31 as an argument.
|
||||
* Run BL3-1 via an SMC to BL1. Information on how to pass control to
|
||||
* the BL3-2 (if present) and BL3-3 software images will be passed to
|
||||
* BL3-1 as an argument.
|
||||
*/
|
||||
smc(RUN_IMAGE, (unsigned long)bl31_ep_info, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
|
|
@ -609,23 +609,24 @@ The BL2 stage is executed only by the primary CPU, which is determined in BL1
|
|||
using the `platform_is_primary_cpu()` function. BL1 passed control to BL2 at
|
||||
`BL2_BASE`. BL2 executes in Secure EL1 and is responsible for:
|
||||
|
||||
1. Loading the BL3-1 binary image into secure RAM from non-volatile storage. To
|
||||
1. (Optional) Loading the BL3-0 binary image (if present) from platform
|
||||
provided non-volatile storage. To load the BL3-0 image, BL2 makes use of
|
||||
the `meminfo` returned by the `bl2_plat_get_bl30_meminfo()` function.
|
||||
The platform also defines the address in memory where BL3-0 is loaded
|
||||
through the optional constant `BL30_BASE`. BL2 uses this information
|
||||
to determine if there is enough memory to load the BL3-0 image.
|
||||
Subsequent handling of the BL3-0 image is platform-specific and is
|
||||
implemented in the `bl2_plat_handle_bl30()` function.
|
||||
If `BL30_BASE` is not defined then this step is not performed.
|
||||
|
||||
2. Loading the BL3-1 binary image into secure RAM from non-volatile storage. To
|
||||
load the BL3-1 image, BL2 makes use of the `meminfo` structure passed to it
|
||||
by BL1. This structure allows BL2 to calculate how much secure RAM is
|
||||
available for its use. The platform also defines the address in secure RAM
|
||||
where BL3-1 is loaded through the constant `BL31_BASE`. BL2 uses this
|
||||
information to determine if there is enough memory to load the BL3-1 image.
|
||||
|
||||
2. Loading the normal world BL3-3 binary image into non-secure DRAM from
|
||||
platform storage and arranging for BL3-1 to pass control to this image. This
|
||||
address is determined using the `plat_get_ns_image_entrypoint()` function
|
||||
described below.
|
||||
|
||||
3. BL2 populates an `entry_point_info` structure in memory provided by the
|
||||
platform with information about how BL3-1 should pass control to the
|
||||
other BL images.
|
||||
|
||||
4. (Optional) Loading the BL3-2 binary image (if present) from platform
|
||||
3. (Optional) Loading the BL3-2 binary image (if present) from platform
|
||||
provided non-volatile storage. To load the BL3-2 image, BL2 makes use of
|
||||
the `meminfo` returned by the `bl2_plat_get_bl32_meminfo()` function.
|
||||
The platform also defines the address in memory where BL3-2 is loaded
|
||||
|
@ -633,11 +634,20 @@ using the `platform_is_primary_cpu()` function. BL1 passed control to BL2 at
|
|||
to determine if there is enough memory to load the BL3-2 image.
|
||||
If `BL32_BASE` is not defined then this and the next step is not performed.
|
||||
|
||||
5. (Optional) Arranging to pass control to the BL3-2 image (if present) that
|
||||
4. (Optional) Arranging to pass control to the BL3-2 image (if present) that
|
||||
has been pre-loaded at `BL32_BASE`. BL2 populates an `entry_point_info`
|
||||
structure in memory provided by the platform with information about how
|
||||
BL3-1 should pass control to the BL3-2 image.
|
||||
|
||||
5. Loading the normal world BL3-3 binary image into non-secure DRAM from
|
||||
platform storage and arranging for BL3-1 to pass control to this image. This
|
||||
address is determined using the `plat_get_ns_image_entrypoint()` function
|
||||
described below.
|
||||
|
||||
6. BL2 populates an `entry_point_info` structure in memory provided by the
|
||||
platform with information about how BL3-1 should pass control to the
|
||||
other BL images.
|
||||
|
||||
The following functions must be implemented by the platform port to enable BL2
|
||||
to perform the above tasks.
|
||||
|
||||
|
@ -704,6 +714,31 @@ populated with the extents of secure RAM available for BL2 to use. See
|
|||
`bl2_early_platform_setup()` above.
|
||||
|
||||
|
||||
### Function : bl2_plat_get_bl30_meminfo() [mandatory]
|
||||
|
||||
Argument : meminfo *
|
||||
Return : void
|
||||
|
||||
This function is used to get the memory limits where BL2 can load the
|
||||
BL3-0 image. The meminfo provided by this is used by load_image() to
|
||||
validate whether the BL3-0 image can be loaded within the given
|
||||
memory from the given base.
|
||||
|
||||
|
||||
### Function : bl2_plat_handle_bl30() [mandatory]
|
||||
|
||||
Argument : image_info *
|
||||
Return : int
|
||||
|
||||
This function is called after loading BL3-0 image and it is used to perform any
|
||||
platform-specific actions required to handle the SCP firmware. Typically it
|
||||
transfers the image into SCP memory using a platform-specific protocol and waits
|
||||
until SCP executes it and signals to the Application Processor (AP) for BL2
|
||||
execution to continue.
|
||||
|
||||
This function returns 0 on success, a negative error code otherwise.
|
||||
|
||||
|
||||
### Function : bl2_plat_get_bl31_params() [mandatory]
|
||||
|
||||
Argument : void
|
||||
|
|
|
@ -133,6 +133,10 @@ the build system doesn't track dependency for build options. Therefore, if any
|
|||
of the build options are changed from a previous build, a clean build must be
|
||||
performed.
|
||||
|
||||
* `BL30`: Path to BL3-0 image in the host file system. This image is optional.
|
||||
If a BL3-0 image is present then this option must be passed for the `fip`
|
||||
target
|
||||
|
||||
* `BL33`: Path to BL33 image in the host file system. This is mandatory for
|
||||
`fip` target
|
||||
|
||||
|
|
|
@ -66,6 +66,10 @@ typedef struct {
|
|||
|
||||
static const plat_fip_name_uuid_t name_uuid[] = {
|
||||
{BL2_IMAGE_NAME, UUID_TRUSTED_BOOT_FIRMWARE_BL2},
|
||||
#ifdef BL30_IMAGE_NAME
|
||||
/* BL3-0 is optional in the platform */
|
||||
{BL30_IMAGE_NAME, UUID_SCP_FIRMWARE_BL30},
|
||||
#endif /* BL30_IMAGE_NAME */
|
||||
{BL31_IMAGE_NAME, UUID_EL3_RUNTIME_FIRMWARE_BL31},
|
||||
#ifdef BL32_IMAGE_NAME
|
||||
/* BL3-2 is optional in the platform */
|
||||
|
|
|
@ -120,25 +120,42 @@ struct entry_point_info *bl2_plat_get_bl31_ep_info(void);
|
|||
void bl2_plat_flush_bl31_params(void);
|
||||
|
||||
/*
|
||||
* The next 3 functions allow the platform to change the entrypoint
|
||||
* information for the 3rd level BL images, after BL2 has loaded the 3rd
|
||||
* level BL images into memory but before BL3-1 is executed.
|
||||
* The next 2 functions allow the platform to change the entrypoint information
|
||||
* for the mandatory 3rd level BL images, BL3-1 and BL3-3. This is done after
|
||||
* BL2 has loaded those images into memory but before BL3-1 is executed.
|
||||
*/
|
||||
void bl2_plat_set_bl31_ep_info(struct image_info *image,
|
||||
struct entry_point_info *ep);
|
||||
|
||||
void bl2_plat_set_bl32_ep_info(struct image_info *image,
|
||||
struct entry_point_info *ep);
|
||||
|
||||
void bl2_plat_set_bl33_ep_info(struct image_info *image,
|
||||
struct entry_point_info *ep);
|
||||
|
||||
/* Gets the memory layout for BL32 */
|
||||
void bl2_plat_get_bl32_meminfo(struct meminfo *mem_info);
|
||||
|
||||
/* Gets the memory layout for BL33 */
|
||||
/* Gets the memory layout for BL3-3 */
|
||||
void bl2_plat_get_bl33_meminfo(struct meminfo *mem_info);
|
||||
|
||||
/*******************************************************************************
|
||||
* Conditionally mandatory BL2 functions: must be implemented if BL3-0 image
|
||||
* is supported
|
||||
******************************************************************************/
|
||||
/* Gets the memory layout for BL3-0 */
|
||||
void bl2_plat_get_bl30_meminfo(struct meminfo *mem_info);
|
||||
|
||||
/*
|
||||
* This function is called after loading BL3-0 image and it is used to perform
|
||||
* any platform-specific actions required to handle the SCP firmware.
|
||||
*/
|
||||
int bl2_plat_handle_bl30(struct image_info *bl30_image_info);
|
||||
|
||||
/*******************************************************************************
|
||||
* Conditionally mandatory BL2 functions: must be implemented if BL3-2 image
|
||||
* is supported
|
||||
******************************************************************************/
|
||||
void bl2_plat_set_bl32_ep_info(struct image_info *image,
|
||||
struct entry_point_info *ep);
|
||||
|
||||
/* Gets the memory layout for BL3-2 */
|
||||
void bl2_plat_get_bl32_meminfo(struct meminfo *mem_info);
|
||||
|
||||
/*******************************************************************************
|
||||
* Optional BL2 functions (may be overridden)
|
||||
******************************************************************************/
|
||||
|
|
Loading…
Add table
Reference in a new issue