From 93d81d64d3947aa7712fab602a16b781a12c78bb Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Tue, 24 Jun 2014 14:19:36 +0100 Subject: [PATCH] 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 --- Makefile | 18 ++- bl2/bl2_main.c | 225 +++++++++++++++++++++++---------- docs/porting-guide.md | 59 +++++++-- docs/user-guide.md | 4 + drivers/io/io_fip.c | 4 + include/plat/common/platform.h | 37 ++++-- 6 files changed, 259 insertions(+), 88 deletions(-) diff --git a/Makefile b/Makefile index b505d62a4..f4a7185bf 100644 --- a/Makefile +++ b/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} \ diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c index 7efd9f6da..d96e199c2 100644 --- a/bl2/bl2_main.c +++ b/bl2/bl2_main.c @@ -38,85 +38,100 @@ #include #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); } diff --git a/docs/porting-guide.md b/docs/porting-guide.md index b39a62b09..2a98d0e93 100644 --- a/docs/porting-guide.md +++ b/docs/porting-guide.md @@ -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 diff --git a/docs/user-guide.md b/docs/user-guide.md index 010553165..34e5ba1dd 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -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 diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c index 36788a248..7df229d3d 100644 --- a/drivers/io/io_fip.c +++ b/drivers/io/io_fip.c @@ -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 */ diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index c130ae78d..1eeaac278 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -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) ******************************************************************************/