diff --git a/Makefile b/Makefile index b505d62..f4a7185 100644 --- a/Makefile +++ b/Makefile @@ -407,7 +407,23 @@ $(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 7efd9f6..d96e199 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(); - } + if (e == 0) + bl2_plat_set_bl31_ep_info(bl2_to_bl31_params->bl31_image_info, + bl31_ep_info); - bl2_plat_set_bl31_ep_info(bl2_to_bl31_params->bl31_image_info, - bl31_ep_info); + return e; +} - 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); - - +/******************************************************************************* + * 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 @@ 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 b39a62b..2a98d0e 100644 --- a/docs/porting-guide.md +++ b/docs/porting-guide.md @@ -609,23 +609,24 @@ 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 @@ 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 @@ `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 0105531..34e5ba1 100644 --- a/docs/user-guide.md +++ b/docs/user-guide.md @@ -133,6 +133,10 @@ 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 36788a2..7df229d 100644 --- a/drivers/io/io_fip.c +++ b/drivers/io/io_fip.c @@ -66,6 +66,10 @@ 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 c130ae7..1eeaac2 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -120,26 +120,43 @@ 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) ******************************************************************************/