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:
Sandrine Bailleux 2014-06-24 14:19:36 +01:00
parent a1b6db6c62
commit 93d81d64d3
6 changed files with 259 additions and 88 deletions

View File

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

View File

@ -38,85 +38,100 @@
#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 */
e = load_image(bl2_tzram_layout,
BL31_IMAGE_NAME,
BL31_BASE,
bl2_to_bl31_params->bl31_image_info,
bl31_ep_info);
BL31_IMAGE_NAME,
BL31_BASE,
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();
}
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);
if (e == 0)
bl2_plat_set_bl31_ep_info(bl2_to_bl31_params->bl31_image_info,
bl31_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);
}

View File

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

View File

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

View File

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

View File

@ -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)
******************************************************************************/