diff --git a/bl1/aarch64/bl1_entrypoint.S b/bl1/aarch64/bl1_entrypoint.S index 83594f2..ce27752 100644 --- a/bl1/aarch64/bl1_entrypoint.S +++ b/bl1/aarch64/bl1_entrypoint.S @@ -69,10 +69,14 @@ /* -------------------------------------------------- * Initialize platform and jump to our c-entry point - * for this type of reset. Panic if it returns + * for this type of reset. * -------------------------------------------------- */ bl bl1_main -panic: - b panic + + /* -------------------------------------------------- + * Do the transition to next boot image. + * -------------------------------------------------- + */ + b el3_exit endfunc bl1_entrypoint diff --git a/bl1/aarch64/bl1_exceptions.S b/bl1/aarch64/bl1_exceptions.S index de3086d..8802301 100644 --- a/bl1/aarch64/bl1_exceptions.S +++ b/bl1/aarch64/bl1_exceptions.S @@ -31,6 +31,7 @@ #include #include #include +#include .globl bl1_exceptions @@ -114,10 +115,12 @@ /* Enable the SError interrupt */ msr daifclr, #DAIF_ABT_BIT + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + /* Expect only SMC exceptions */ - mrs x19, esr_el3 - ubfx x20, x19, #ESR_EC_SHIFT, #ESR_EC_LENGTH - cmp x20, #EC_AARCH64_SMC + mrs x30, esr_el3 + ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH + cmp x30, #EC_AARCH64_SMC b.ne unexpected_sync_exception b smc_handler64 @@ -178,6 +181,14 @@ func smc_handler64 + /* ---------------------------------------------- + * Switch back to SP_EL0 for the C runtime stack. + * ---------------------------------------------- + */ + ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] + msr spsel, #0 + mov sp, x30 + /* --------------------------------------------------------------------- * Only a single SMC exception from BL2 to ask BL1 to pass EL3 control * to BL31 is expected here. It expects: diff --git a/bl1/bl1.mk b/bl1/bl1.mk index 8e73bef..a19a330 100644 --- a/bl1/bl1.mk +++ b/bl1/bl1.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -32,6 +32,11 @@ bl1/aarch64/bl1_arch_setup.c \ bl1/aarch64/bl1_entrypoint.S \ bl1/aarch64/bl1_exceptions.S \ - lib/cpus/aarch64/cpu_helpers.S + bl1/bl1_context_mgmt.c \ + common/aarch64/context.S \ + common/context_mgmt.c \ + lib/cpus/aarch64/cpu_helpers.S \ + plat/common/plat_bl1_common.c + BL1_LINKERFILE := bl1/bl1.ld.S diff --git a/bl1/bl1_context_mgmt.c b/bl1/bl1_context_mgmt.c new file mode 100644 index 0000000..e9264cb --- /dev/null +++ b/bl1/bl1_context_mgmt.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +/* + * Following array will be used for context management. + * There are 2 instances, for the Secure and Non-Secure contexts. + */ +static cpu_context_t bl1_cpu_context[2]; + +/* Following contains the cpu context pointers. */ +static void *bl1_cpu_context_ptr[2]; + + +void *cm_get_context(uint32_t security_state) +{ + assert(sec_state_is_valid(security_state)); + return bl1_cpu_context_ptr[security_state]; +} + +void cm_set_context(void *context, uint32_t security_state) +{ + assert(sec_state_is_valid(security_state)); + bl1_cpu_context_ptr[security_state] = context; +} + +/******************************************************************************* + * This function prepares the context for Secure/Normal world images. + * Normal world images are transitioned to EL2(if supported) else EL1. + ******************************************************************************/ +void bl1_prepare_next_image(unsigned int image_id) +{ + unsigned int security_state; + image_desc_t *image_desc; + entry_point_info_t *next_bl_ep; + + /* Get the image descriptor. */ + image_desc = bl1_plat_get_image_desc(image_id); + assert(image_desc); + + /* Get the entry point info. */ + next_bl_ep = &image_desc->ep_info; + + /* Get the image security state. */ + security_state = GET_SEC_STATE(next_bl_ep->h.attr); + + /* Setup the Secure/Non-Secure context if not done already. */ + if (!cm_get_context(security_state)) + cm_set_context(&bl1_cpu_context[security_state], security_state); + + /* Prepare the SPSR for the next BL image. */ + if (security_state == SECURE) { + next_bl_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + } else { + /* Use EL2 if supported else use EL1. */ + if (read_id_aa64pfr0_el1() & + (ID_AA64PFR0_ELX_MASK << ID_AA64PFR0_EL2_SHIFT)) { + next_bl_ep->spsr = SPSR_64(MODE_EL2, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + } else { + next_bl_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + } + } + + /* Allow platform to make change */ + bl1_plat_set_ep_info(image_id, next_bl_ep); + + /* Prepare the context for the next BL image. */ + cm_init_my_context(next_bl_ep); + cm_prepare_el3_exit(security_state); + + /* Indicate that image is in execution state. */ + image_desc->state = IMAGE_STATE_EXECUTED; + + print_entry_point_info(next_bl_ep); +} diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c index 9c0927f..54da735 100644 --- a/bl1/bl1_main.c +++ b/bl1/bl1_main.c @@ -38,34 +38,8 @@ #include #include "bl1_private.h" -/******************************************************************************* - * Runs BL2 from the given entry point. It results in dropping the - * exception level - ******************************************************************************/ -static void __dead2 bl1_run_bl2(entry_point_info_t *bl2_ep) -{ - /* Check bl2 security state is expected as secure */ - assert(GET_SECURITY_STATE(bl2_ep->h.attr) == SECURE); - /* Check NS Bit is also set as secure */ - assert(!(read_scr_el3() & SCR_NS_BIT)); - bl1_arch_next_el_setup(); - - write_spsr_el3(bl2_ep->spsr); - write_elr_el3(bl2_ep->pc); - - NOTICE("BL1: Booting BL2\n"); - print_entry_point_info(bl2_ep); - - eret(bl2_ep->args.arg0, - bl2_ep->args.arg1, - bl2_ep->args.arg2, - bl2_ep->args.arg3, - bl2_ep->args.arg4, - bl2_ep->args.arg5, - bl2_ep->args.arg6, - bl2_ep->args.arg7); -} +static void bl1_load_bl2(void); /******************************************************************************* * The next function has a weak definition. Platform specific code can override @@ -88,7 +62,8 @@ /* Check that BL1's memory is lying outside of the free memory */ assert((BL1_RAM_LIMIT <= bl1_mem_layout->free_base) || - (BL1_RAM_BASE >= bl1_mem_layout->free_base + bl1_mem_layout->free_size)); + (BL1_RAM_BASE >= bl1_mem_layout->free_base + + bl1_mem_layout->free_size)); /* Remove BL1 RW data from the scope of memory visible to BL2 */ *bl2_mem_layout = *bl1_mem_layout; @@ -102,13 +77,13 @@ /******************************************************************************* * Function to perform late architectural and platform specific initialization. - * It also locates and loads the BL2 raw binary image in the trusted DRAM. Only - * called by the primary cpu after a cold boot. - * TODO: Add support for alternative image load mechanism e.g using virtio/elf - * loader etc. - ******************************************************************************/ + * It also queries the platform to load and run next BL image. Only called + * by the primary cpu after a cold boot. + ******************************************************************************/ void bl1_main(void) { + unsigned int image_id; + /* Announce our arrival */ NOTICE(FIRMWARE_WELCOME_STR); NOTICE("BL1: %s\n", version_string); @@ -116,11 +91,6 @@ INFO("BL1: RAM 0x%lx - 0x%lx\n", BL1_RAM_BASE, BL1_RAM_LIMIT); - image_info_t bl2_image_info = { {0} }; - entry_point_info_t bl2_ep = { {0} }; - meminfo_t *bl1_tzram_layout; - meminfo_t *bl2_tzram_layout = 0x0; - int err; #if DEBUG unsigned long val; @@ -150,28 +120,59 @@ /* Perform remaining generic architectural setup from EL3 */ bl1_arch_setup(); +#if TRUSTED_BOARD_BOOT + /* Initialize authentication module */ + auth_mod_init(); +#endif /* TRUSTED_BOARD_BOOT */ + /* Perform platform setup in BL1. */ bl1_platform_setup(); - SET_PARAM_HEAD(&bl2_image_info, PARAM_IMAGE_BINARY, VERSION_1, 0); - SET_PARAM_HEAD(&bl2_ep, PARAM_EP, VERSION_1, 0); + /* Get the image id of next image to load and run. */ + image_id = bl1_plat_get_next_image_id(); + + if (image_id == BL2_IMAGE_ID) + bl1_load_bl2(); + + bl1_prepare_next_image(image_id); +} + +/******************************************************************************* + * This function locates and loads the BL2 raw binary image in the trusted SRAM. + * Called by the primary cpu after a cold boot. + * TODO: Add support for alternative image load mechanism e.g using virtio/elf + * loader etc. + ******************************************************************************/ +void bl1_load_bl2(void) +{ + image_desc_t *image_desc; + image_info_t *image_info; + entry_point_info_t *ep_info; + meminfo_t *bl1_tzram_layout; + meminfo_t *bl2_tzram_layout; + int err; + + /* Get the image descriptor */ + image_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID); + assert(image_desc); + + /* Get the image info */ + image_info = &image_desc->image_info; + + /* Get the entry point info */ + ep_info = &image_desc->ep_info; /* Find out how much free trusted ram remains after BL1 load */ bl1_tzram_layout = bl1_plat_sec_mem_layout(); INFO("BL1: Loading BL2\n"); -#if TRUSTED_BOARD_BOOT - /* Initialize authentication module */ - auth_mod_init(); -#endif /* TRUSTED_BOARD_BOOT */ - /* Load the BL2 image */ err = load_auth_image(bl1_tzram_layout, BL2_IMAGE_ID, - BL2_BASE, - &bl2_image_info, - &bl2_ep); + image_info->image_base, + image_info, + ep_info); if (err) { ERROR("Failed to load BL2 firmware.\n"); @@ -188,11 +189,10 @@ bl2_tzram_layout = (meminfo_t *) bl1_tzram_layout->free_base; bl1_init_bl2_mem_layout(bl1_tzram_layout, bl2_tzram_layout); - bl1_plat_set_bl2_ep_info(&bl2_image_info, &bl2_ep); - bl2_ep.args.arg1 = (unsigned long)bl2_tzram_layout; - bl1_run_bl2(&bl2_ep); - - return; + ep_info->args.arg1 = (unsigned long)bl2_tzram_layout; + NOTICE("BL1: Booting BL2\n"); + VERBOSE("BL1: BL2 memory layout address = 0x%llx\n", + (unsigned long long) bl2_tzram_layout); } /******************************************************************************* diff --git a/bl1/bl1_private.h b/bl1/bl1_private.h index 0a8fc45..7d796f1 100644 --- a/bl1/bl1_private.h +++ b/bl1/bl1_private.h @@ -46,4 +46,5 @@ void bl1_arch_setup(void); void bl1_arch_next_el_setup(void); +void bl1_prepare_next_image(unsigned int image_id); #endif /* __BL1_PRIVATE_H__ */ diff --git a/include/common/bl_common.h b/include/common/bl_common.h index d8741c9..bedd496 100644 --- a/include/common/bl_common.h +++ b/include/common/bl_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -59,11 +59,41 @@ #define ENTRY_POINT_INFO_PC_OFFSET 0x08 #define ENTRY_POINT_INFO_ARGS_OFFSET 0x18 -#define PARAM_EP_SECURITY_MASK 0x1 +/* The following are used to set/get image attributes. */ +#define EXECUTABLE (0x1) +#define NON_EXECUTABLE (0x0) +#define PARAM_EP_EXECUTE_MASK (0x1) +#define PARAM_EP_EXECUTE_SHIFT (0x1) +#define PARAM_EP_SECURITY_MASK (0x1) +#define PARAM_EP_SECURITY_SHIFT (0x0) + #define GET_SECURITY_STATE(x) (x & PARAM_EP_SECURITY_MASK) #define SET_SECURITY_STATE(x, security) \ ((x) = ((x) & ~PARAM_EP_SECURITY_MASK) | (security)) +#define GET_EXEC_STATE(x) \ + (((x) >> PARAM_EP_EXECUTE_SHIFT) & PARAM_EP_EXECUTE_MASK) + +#define SET_EXEC_STATE(x) \ + (((x) & PARAM_EP_EXECUTE_MASK) << PARAM_EP_EXECUTE_SHIFT) + +#define GET_SEC_STATE(x) \ + (((x) >> PARAM_EP_SECURITY_SHIFT) & PARAM_EP_SECURITY_MASK) + +#define SET_SEC_STATE(x) \ + (((x) & PARAM_EP_SECURITY_MASK) << PARAM_EP_SECURITY_SHIFT) + +/* + * The following are used for image state attributes. + * Image can only be in one of the following state. + */ +#define IMAGE_STATE_RESET 0 +#define IMAGE_STATE_COPIED 1 +#define IMAGE_STATE_COPYING 2 +#define IMAGE_STATE_AUTHENTICATED 3 +#define IMAGE_STATE_EXECUTED 4 +#define IMAGE_STATE_INTERRUPTED 5 + #define EP_EE_MASK 0x2 #define EP_EE_LITTLE 0x0 #define EP_EE_BIG 0x2 @@ -82,6 +112,8 @@ #define VERSION_1 0x01 +#define INVALID_IMAGE_ID (0xFFFFFFFF) + #define SET_PARAM_HEAD(_p, _type, _ver, _attr) do { \ (_p)->h.type = (uint8_t)(_type); \ (_p)->h.version = (uint8_t)(_ver); \ @@ -196,8 +228,24 @@ param_header_t h; uintptr_t image_base; /* physical address of base of image */ uint32_t image_size; /* bytes read from image file */ + uint32_t copied_size; /* image size copied in blocks */ } image_info_t; +/***************************************************************************** + * The image descriptor struct definition. + *****************************************************************************/ +typedef struct image_desc { + /* Contains unique image id for the image. */ + unsigned int image_id; + image_info_t image_info; + entry_point_info_t ep_info; + /* + * This member contains Image state information. + * Refer IMAGE_STATE_XXX defined above. + */ + unsigned int state; +} image_desc_t; + /******************************************************************************* * This structure represents the superset of information that can be passed to * BL31 e.g. while passing control to it from BL2. The BL32 parameters will be diff --git a/include/common/el3_common_macros.S b/include/common/el3_common_macros.S index 87e172e..0514e2a 100644 --- a/include/common/el3_common_macros.S +++ b/include/common/el3_common_macros.S @@ -247,13 +247,11 @@ #endif .endif /* _init_c_runtime */ -#if IMAGE_BL31 /* --------------------------------------------------------------------- * Use SP_EL0 for the C runtime stack. * --------------------------------------------------------------------- */ msr spsel, #0 -#endif /* IMAGE_BL31 */ /* --------------------------------------------------------------------- * Allocate a stack whose memory will be marked as Normal-IS-WBWA when diff --git a/include/plat/common/common_def.h b/include/plat/common/common_def.h index 43c69cc..4175b14 100644 --- a/include/plat/common/common_def.h +++ b/include/plat/common/common_def.h @@ -30,6 +30,9 @@ #ifndef __COMMON_DEF_H__ #define __COMMON_DEF_H__ +#include +#include + /****************************************************************************** * Required platform porting definitions that are expected to be common to * all platforms @@ -74,5 +77,14 @@ */ #define __warn_deprecated __attribute__ ((deprecated)) +#define BL2_IMAGE_DESC { \ + .image_id = BL2_IMAGE_ID, \ + .image_info.h.version = VERSION_1, \ + .image_info.h.attr = SET_EXEC_STATE(EXECUTABLE),\ + .image_info.image_base = BL2_BASE, \ + .ep_info.h.attr = SET_SEC_STATE(SECURE), \ + .ep_info.pc = BL2_BASE \ +} + #endif /* __COMMON_DEF_H__ */ diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index de9848b..6d75770 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -43,6 +43,7 @@ struct image_info; struct entry_point_info; struct bl31_params; +struct image_desc; /******************************************************************************* * plat_get_rotpk_info() flags @@ -91,18 +92,18 @@ void bl1_platform_setup(void); struct meminfo *bl1_plat_sec_mem_layout(void); -/* - * This function allows the platform to change the entrypoint information for - * BL2, after BL1 has loaded BL2 into memory but before BL2 is executed. - */ -void bl1_plat_set_bl2_ep_info(struct image_info *image, - struct entry_point_info *ep); - /******************************************************************************* * Optional BL1 functions (may be overridden) ******************************************************************************/ void bl1_init_bl2_mem_layout(const struct meminfo *bl1_mem_layout, struct meminfo *bl2_mem_layout); +/* + * The following functions are used for image loading process in BL1. + */ +void bl1_plat_set_ep_info(unsigned int image_id, + struct entry_point_info *ep_info); +unsigned int bl1_plat_get_next_image_id(void); +struct image_desc *bl1_plat_get_image_desc(unsigned int image_id); /******************************************************************************* * Mandatory BL2 functions diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c index 79c7d94..d0a4c0b 100644 --- a/plat/arm/common/arm_bl1_setup.c +++ b/plat/arm/common/arm_bl1_setup.c @@ -57,7 +57,6 @@ #pragma weak bl1_plat_arch_setup #pragma weak bl1_platform_setup #pragma weak bl1_plat_sec_mem_layout -#pragma weak bl1_plat_set_bl2_ep_info /* Data structure which holds the extents of the trusted SRAM for BL1*/ @@ -169,16 +168,3 @@ sev(); #endif } - -/******************************************************************************* - * Before calling this function BL2 is loaded in memory and its entrypoint - * is set by load_image. This is a placeholder for the platform to change - * the entrypoint of BL2 and set SPSR and security state. - * On ARM standard platforms we only set the security state of the entrypoint - ******************************************************************************/ -void bl1_plat_set_bl2_ep_info(image_info_t *bl2_image, - entry_point_info_t *bl2_ep) -{ - SET_SECURITY_STATE(bl2_ep->h.attr, SECURE); - bl2_ep->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); -} diff --git a/plat/common/plat_bl1_common.c b/plat/common/plat_bl1_common.c new file mode 100644 index 0000000..73362a1 --- /dev/null +++ b/plat/common/plat_bl1_common.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include + +/* + * The following platform functions are weakly defined. They + * are default implementations that allow BL1 compile in + * absence of real definitions. The Platforms may override + * with more complex definitions. + */ +#pragma weak bl1_plat_get_next_image_id +#pragma weak bl1_plat_set_ep_info +#pragma weak bl1_plat_get_image_desc + + +unsigned int bl1_plat_get_next_image_id(void) +{ + /* BL2 load will be done by default. */ + return BL2_IMAGE_ID; +} + +void bl1_plat_set_ep_info(unsigned int image_id, + entry_point_info_t *ep_info) +{ + +} + +/* + * Following is the default definition that always + * returns BL2 image details. + */ +image_desc_t *bl1_plat_get_image_desc(unsigned int image_id) +{ + static image_desc_t bl2_img_desc = BL2_IMAGE_DESC; + return &bl2_img_desc; +}