diff --git a/Makefile b/Makefile index 1058b39..1cd6b62 100644 --- a/Makefile +++ b/Makefile @@ -500,6 +500,7 @@ $(eval $(call assert_boolean,USE_COHERENT_MEM)) $(eval $(call assert_boolean,USE_TBBR_DEFS)) $(eval $(call assert_boolean,WARMBOOT_ENABLE_DCACHE_EARLY)) +$(eval $(call assert_boolean,BL2_AT_EL3)) $(eval $(call assert_numeric,ARM_ARCH_MAJOR)) $(eval $(call assert_numeric,ARM_ARCH_MINOR)) @@ -543,6 +544,7 @@ $(eval $(call add_define,USE_COHERENT_MEM)) $(eval $(call add_define,USE_TBBR_DEFS)) $(eval $(call add_define,WARMBOOT_ENABLE_DCACHE_EARLY)) +$(eval $(call add_define,BL2_AT_EL3)) # Define the EL3_PAYLOAD_BASE flag only if it is provided. ifdef EL3_PAYLOAD_BASE @@ -584,8 +586,12 @@ endif ifeq (${NEED_BL2},yes) -$(if ${BL2}, $(eval $(call MAKE_TOOL_ARGS,2,${BL2},tb-fw)),\ - $(eval $(call MAKE_BL,2,tb-fw))) +ifeq (${BL2_AT_EL3}, 0) +FIP_BL2_ARGS := tb-fw +endif + +$(if ${BL2}, $(eval $(call MAKE_TOOL_ARGS,2,${BL2},${FIP_BL2_ARGS})),\ + $(eval $(call MAKE_BL,2,${FIP_BL2_ARGS}))) endif ifeq (${NEED_SCP_BL2},yes) diff --git a/bl1/bl1.mk b/bl1/bl1.mk index a026499..41ee1a7 100644 --- a/bl1/bl1.mk +++ b/bl1/bl1.mk @@ -13,7 +13,10 @@ lib/cpus/errata_report.c \ lib/el3_runtime/${ARCH}/context_mgmt.c \ plat/common/plat_bl1_common.c \ - plat/common/${ARCH}/platform_up_stack.S + plat/common/${ARCH}/platform_up_stack.S \ + ${MBEDTLS_COMMON_SOURCES} \ + ${MBEDTLS_CRYPTO_SOURCES} \ + ${MBEDTLS_X509_SOURCES} ifeq (${ARCH},aarch64) BL1_SOURCES += lib/el3_runtime/aarch64/context.S diff --git a/bl2/aarch32/bl2_el3_entrypoint.S b/bl2/aarch32/bl2_el3_entrypoint.S new file mode 100644 index 0000000..997b069 --- /dev/null +++ b/bl2/aarch32/bl2_el3_entrypoint.S @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + + .globl bl2_entrypoint + .globl bl2_run_next_image + + +func bl2_entrypoint + /* Save arguments x0-x3 from previous Boot loader */ + mov r9, r0 + mov r10, r1 + mov r11, r2 + mov r12, r3 + + el3_entrypoint_common \ + _init_sctlr=1 \ + _warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \ + _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \ + _init_memory=1 \ + _init_c_runtime=1 \ + _exception_vectors=bl2_vector_table + + /* + * Restore parameters of boot rom + */ + mov r0, r9 + mov r1, r10 + mov r2, r11 + mov r3, r12 + + bl bl2_el3_early_platform_setup + bl bl2_el3_plat_arch_setup + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl bl2_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler + +endfunc bl2_entrypoint + +func bl2_run_next_image + mov r8,r0 + + /* + * MMU needs to be disabled because both BL2 and BL32 execute + * in PL1, and therefore share the same address space. + * BL32 will initialize the address space according to its + * own requirement. + */ + bl disable_mmu_icache_secure + stcopr r0, TLBIALL + dsb sy + isb + mov r0, r8 + bl bl2_el3_plat_prepare_exit + + /* + * Extract PC and SPSR based on struct `entry_point_info_t` + * and load it in LR and SPSR registers respectively. + */ + ldr lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET] + ldr r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)] + msr spsr, r1 + + add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET + ldm r8, {r0, r1, r2, r3} + eret +endfunc bl2_run_next_image diff --git a/bl2/aarch32/bl2_el3_exceptions.S b/bl2/aarch32/bl2_el3_exceptions.S new file mode 100644 index 0000000..11ddf37 --- /dev/null +++ b/bl2/aarch32/bl2_el3_exceptions.S @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl bl2_vector_table + +vector_base bl2_vector_table + b bl2_entrypoint + b report_exception /* Undef */ + b report_exception /* SVC call */ + b report_exception /* Prefetch abort */ + b report_exception /* Data abort */ + b report_exception /* Reserved */ + b report_exception /* IRQ */ + b report_exception /* FIQ */ diff --git a/bl2/aarch64/bl2_el3_entrypoint.S b/bl2/aarch64/bl2_el3_entrypoint.S new file mode 100644 index 0000000..2d3efd1 --- /dev/null +++ b/bl2/aarch64/bl2_el3_entrypoint.S @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl bl2_entrypoint + .globl bl2_vector_table + .globl bl2_el3_run_image + .globl bl2_run_next_image + +func bl2_entrypoint + /* Save arguments x0-x3 from previous Boot loader */ + mov x20, x0 + mov x21, x1 + mov x22, x2 + mov x23, x3 + + el3_entrypoint_common \ + _init_sctlr=1 \ + _warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \ + _secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \ + _init_memory=1 \ + _init_c_runtime=1 \ + _exception_vectors=bl2_el3_exceptions + + /* + * Restore parameters of boot rom + */ + mov x0, x20 + mov x1, x21 + mov x2, x22 + mov x3, x23 + + bl bl2_el3_early_platform_setup + bl bl2_el3_plat_arch_setup + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl bl2_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler +endfunc bl2_entrypoint + +func bl2_run_next_image + mov x20,x0 + /* + * MMU needs to be disabled because both BL2 and BL31 execute + * in EL3, and therefore share the same address space. + * BL31 will initialize the address space according to its + * own requirement. + */ + bl disable_mmu_icache_el3 + tlbi alle3 + bl bl2_el3_plat_prepare_exit + + ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET] + msr elr_el3, x0 + msr spsr_el3, x1 + + ldp x6, x7, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x30)] + ldp x4, x5, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x20)] + ldp x2, x3, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x10)] + ldp x0, x1, [x20, #(ENTRY_POINT_INFO_ARGS_OFFSET + 0x0)] + eret +endfunc bl2_run_next_image diff --git a/bl2/aarch64/bl2_el3_exceptions.S b/bl2/aarch64/bl2_el3_exceptions.S new file mode 100644 index 0000000..987f6e3 --- /dev/null +++ b/bl2/aarch64/bl2_el3_exceptions.S @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* ----------------------------------------------------------------------------- + * Very simple stackless exception handlers used by BL2. + * ----------------------------------------------------------------------------- + */ + .globl bl2_el3_exceptions + +vector_base bl2_el3_exceptions + + /* ----------------------------------------------------- + * Current EL with SP0 : 0x0 - 0x200 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionSP0 + mov x0, #SYNC_EXCEPTION_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size SynchronousExceptionSP0 + +vector_entry IrqSP0 + mov x0, #IRQ_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size IrqSP0 + +vector_entry FiqSP0 + mov x0, #FIQ_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size FiqSP0 + +vector_entry SErrorSP0 + mov x0, #SERROR_SP_EL0 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size SErrorSP0 + + /* ----------------------------------------------------- + * Current EL with SPx: 0x200 - 0x400 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionSPx + mov x0, #SYNC_EXCEPTION_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size SynchronousExceptionSPx + +vector_entry IrqSPx + mov x0, #IRQ_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size IrqSPx + +vector_entry FiqSPx + mov x0, #FIQ_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size FiqSPx + +vector_entry SErrorSPx + mov x0, #SERROR_SP_ELX + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size SErrorSPx + + /* ----------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA64 + mov x0, #SYNC_EXCEPTION_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size SynchronousExceptionA64 + +vector_entry IrqA64 + mov x0, #IRQ_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size IrqA64 + +vector_entry FiqA64 + mov x0, #FIQ_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size FiqA64 + +vector_entry SErrorA64 + mov x0, #SERROR_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size SErrorA64 + + /* ----------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA32 + mov x0, #SYNC_EXCEPTION_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size SynchronousExceptionA32 + +vector_entry IrqA32 + mov x0, #IRQ_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size IrqA32 + +vector_entry FiqA32 + mov x0, #FIQ_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size FiqA32 + +vector_entry SErrorA32 + mov x0, #SERROR_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler + check_vector_size SErrorA32 diff --git a/bl2/bl2.mk b/bl2/bl2.mk index 32e3284..9d75286 100644 --- a/bl2/bl2.mk +++ b/bl2/bl2.mk @@ -5,10 +5,12 @@ # BL2_SOURCES += bl2/bl2_main.c \ - bl2/${ARCH}/bl2_entrypoint.S \ bl2/${ARCH}/bl2_arch_setup.c \ lib/locks/exclusive/${ARCH}/spinlock.S \ - plat/common/${ARCH}/platform_up_stack.S + plat/common/${ARCH}/platform_up_stack.S \ + ${MBEDTLS_COMMON_SOURCES} \ + ${MBEDTLS_CRYPTO_SOURCES} \ + ${MBEDTLS_X509_SOURCES} ifeq (${ARCH},aarch64) BL2_SOURCES += common/aarch64/early_exceptions.S @@ -20,4 +22,15 @@ BL2_SOURCES += bl2/bl2_image_load.c endif +ifeq (${BL2_AT_EL3},0) +BL2_SOURCES += bl2/${ARCH}/bl2_entrypoint.S BL2_LINKERFILE := bl2/bl2.ld.S + +else +BL2_SOURCES += bl2/${ARCH}/bl2_el3_entrypoint.S \ + bl2/${ARCH}/bl2_el3_exceptions.S \ + plat/common/plat_bl2_el3_common.c \ + lib/cpus/${ARCH}/cpu_helpers.S \ + lib/cpus/errata_report.c +BL2_LINKERFILE := bl2/bl2_el3.ld.S +endif diff --git a/bl2/bl2_el3.ld.S b/bl2/bl2_el3.ld.S new file mode 100644 index 0000000..57709e3 --- /dev/null +++ b/bl2/bl2_el3.ld.S @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) +ENTRY(bl2_entrypoint) + +MEMORY { + RAM (rwx): ORIGIN = BL2_BASE, LENGTH = BL2_LIMIT - BL2_BASE +} + + +SECTIONS +{ + . = BL2_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL2_BASE address is not aligned on a page boundary.") + +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + __TEXT_RESIDENT_START__ = .; + *bl2_el3_entrypoint.o(.text*) + *(.text.asm.*) + __TEXT_RESIDENT_END__ = .; + *(.text*) + *(.vectors) + . = NEXT(PAGE_SIZE); + __TEXT_END__ = .; + } >RAM + + .rodata . : { + __RODATA_START__ = .; + *(.rodata*) + + /* Ensure 8-byte alignment for descriptors and ensure inclusion */ + . = ALIGN(8); + __PARSER_LIB_DESCS_START__ = .; + KEEP(*(.img_parser_lib_descs)) + __PARSER_LIB_DESCS_END__ = .; + + /* + * Ensure 8-byte alignment for cpu_ops so that its fields are also + * aligned. Also ensure cpu_ops inclusion. + */ + . = ALIGN(8); + __CPU_OPS_START__ = .; + KEEP(*(cpu_ops)) + __CPU_OPS_END__ = .; + + . = NEXT(PAGE_SIZE); + __RODATA_END__ = .; + } >RAM + + ASSERT(__TEXT_RESIDENT_END__ - __TEXT_RESIDENT_START__ <= PAGE_SIZE, + "Resident part of BL2 has exceeded its limit.") +#else + ro . : { + __RO_START__ = .; + __TEXT_RESIDENT_START__ = .; + *bl2_el3_entrypoint.o(.text*) + *(.text.asm.*) + __TEXT_RESIDENT_END__ = .; + *(.text*) + *(.rodata*) + + /* + * Ensure 8-byte alignment for cpu_ops so that its fields are also + * aligned. Also ensure cpu_ops inclusion. + */ + . = ALIGN(8); + __CPU_OPS_START__ = .; + KEEP(*(cpu_ops)) + __CPU_OPS_END__ = .; + + /* Ensure 8-byte alignment for descriptors and ensure inclusion */ + . = ALIGN(8); + __PARSER_LIB_DESCS_START__ = .; + KEEP(*(.img_parser_lib_descs)) + __PARSER_LIB_DESCS_END__ = .; + + *(.vectors) + __RO_END_UNALIGNED__ = .; + /* + * Memory page(s) mapped to this section will be marked as + * read-only, executable. No RW data from the next section must + * creep in. Ensure the rest of the current memory page is unused. + */ + . = NEXT(PAGE_SIZE); + + __RO_END__ = .; + } >RAM +#endif + + ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, + "cpu_ops not defined for this platform.") + + /* + * Define a linker symbol to mark start of the RW memory area for this + * image. + */ + __RW_START__ = . ; + + /* + * .data must be placed at a lower address than the stacks if the stack + * protector is enabled. Alternatively, the .data.stack_protector_canary + * section can be placed independently of the main .data section. + */ + .data . : { + __DATA_START__ = .; + *(.data*) + __DATA_END__ = .; + } >RAM + + stacks (NOLOAD) : { + __STACKS_START__ = .; + *(tzfw_normal_stacks) + __STACKS_END__ = .; + } >RAM + + /* + * The .bss section gets initialised to 0 at runtime. + * Its base address should be 16-byte aligned for better performance of the + * zero-initialization code. + */ + .bss : ALIGN(16) { + __BSS_START__ = .; + *(SORT_BY_ALIGNMENT(.bss*)) + *(COMMON) + __BSS_END__ = .; + } >RAM + + /* + * The xlat_table section is for full, aligned page tables (4K). + * Removing them from .bss avoids forcing 4K alignment on + * the .bss section and eliminates the unnecessary zero init + */ + xlat_table (NOLOAD) : { + *(xlat_table) + } >RAM + +#if USE_COHERENT_MEM + /* + * The base address of the coherent memory section must be page-aligned (4K) + * to guarantee that the coherent data are stored on their own pages and + * are not mixed with normal data. This is required to set up the correct + * memory attributes for the coherent data page tables. + */ + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { + __COHERENT_RAM_START__ = .; + *(tzfw_coherent_mem) + __COHERENT_RAM_END_UNALIGNED__ = .; + /* + * Memory page(s) mapped to this section will be marked + * as device memory. No other unexpected data must creep in. + * Ensure the rest of the current memory page is unused. + */ + . = NEXT(PAGE_SIZE); + __COHERENT_RAM_END__ = .; + } >RAM +#endif + + /* + * Define a linker symbol to mark end of the RW memory area for this + * image. + */ + __RW_END__ = .; + __BL2_END__ = .; + + __BSS_SIZE__ = SIZEOF(.bss); + +#if USE_COHERENT_MEM + __COHERENT_RAM_UNALIGNED_SIZE__ = + __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; +#endif + + ASSERT(. <= BL2_LIMIT, "BL2 image has exceeded its limit.") +} diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c index 018deb3..c85db2d 100644 --- a/bl2/bl2_main.c +++ b/bl2/bl2_main.c @@ -13,6 +13,11 @@ #include #include "bl2_private.h" +#ifdef AARCH32 +#define NEXT_IMAGE "BL32" +#else +#define NEXT_IMAGE "BL31" +#endif /******************************************************************************* * The only thing to do in BL2 is to load further images and pass control to @@ -49,6 +54,8 @@ disable_mmu_icache_secure(); #endif /* AARCH32 */ + +#if !BL2_AT_EL3 console_flush(); /* @@ -57,4 +64,11 @@ * be passed to next BL image as an argument. */ smc(BL1_SMC_RUN_IMAGE, (unsigned long)next_bl_ep_info, 0, 0, 0, 0, 0, 0); +#else + NOTICE("BL2: Booting " NEXT_IMAGE "\n"); + print_entry_point_info(next_bl_ep_info); + console_flush(); + + bl2_run_next_image(next_bl_ep_info); +#endif } diff --git a/bl2/bl2_private.h b/bl2/bl2_private.h index 83b8047..ea2f33a 100644 --- a/bl2/bl2_private.h +++ b/bl2/bl2_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -17,5 +17,6 @@ *****************************************/ void bl2_arch_setup(void); struct entry_point_info *bl2_load_images(void); +void bl2_run_next_image(const entry_point_info_t *bl_ep_info); #endif /* __BL2_PRIVATE_H__ */ diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst index 3cb004a..1f8fcc8 100644 --- a/docs/firmware-design.rst +++ b/docs/firmware-design.rst @@ -418,6 +418,63 @@ #. BL1 passes control to BL31 at the specified entrypoint at EL3. +Running BL2 at EL3 execution level +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Some platforms have a non-TF Boot ROM that expects the next boot stage +to execute at EL3. On these platforms, TF BL1 is a waste of memory +as its only purpose is to ensure TF BL2 is entered at S-EL1. To avoid +this waste, a special mode enables BL2 to execute at EL3, which allows +a non-TF Boot ROM to load and jump directly to BL2. This mode is selected +when the build flag BL2_AT_EL3 is enabled. The main differences in this +mode are: + +#. BL2 includes the reset code and the mailbox mechanism to differentiate + cold boot and warm boot. It runs at EL3 doing the arch + initialization required for EL3. + +#. BL2 does not receive the meminfo information from BL1 anymore. This + information can be passed by the Boot ROM or be internal to the + BL2 image. + +#. Since BL2 executes at EL3, BL2 jumps directly to the next image, + instead of invoking the RUN_IMAGE SMC call. + + +We assume 3 different types of BootROM support on the platform: + +#. The Boot ROM always jumps to the same address, for both cold + and warm boot. In this case, we will need to keep a resident part + of BL2 whose memory cannot be reclaimed by any other image. The + linker script defines the symbols __TEXT_RESIDENT_START__ and + __TEXT_RESIDENT_END__ that allows the platform to configure + correctly the memory map. +#. The platform has some mechanism to indicate the jump address to the + Boot ROM. Platform code can then program the jump address with + psci_warmboot_entrypoint during cold boot. +#. The platform has some mechanism to program the reset address using + the PROGRAMMABLE_RESET_ADDRESS feature. Platform code can then + program the reset address with psci_warmboot_entrypoint during + cold boot, bypassing the boot ROM for warm boot. + +In the last 2 cases, no part of BL2 needs to remain resident at +runtime. In the first 2 cases, we expect the Boot ROM to be able to +differentiate between warm and cold boot, to avoid loading BL2 again +during warm boot. + +This functionality can be tested with FVP loading the image directly +in memory and changing the address where the system jumps at reset. +For example: + + -C cluster0.cpu0.RVBAR=0x4014000 + --data cluster0.cpu0=bl2.bin@0x4014000 + +With this configuration, FVP is like a platform of the first case, +where the Boot ROM jumps always to the same address. For simplification, +BL32 is loaded in DRAM in this case, to avoid other images reclaiming +BL2 memory. + + AArch64 BL31 ~~~~~~~~~~~~ diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst index 2e2cc4f..84bd2cd 100644 --- a/docs/porting-guide.rst +++ b/docs/porting-guide.rst @@ -1643,6 +1643,70 @@ must return 0, otherwise it must return 1. The default implementation of this always returns 0. +Boot Loader Stage 2 (BL2) at EL3 +-------------------------------- + +When the platform has a non-TF Boot ROM it is desirable to jump +directly to BL2 instead of TF BL1. In this case BL2 is expected to +execute at EL3 instead of executing at EL1. Refer to the `Firmware +Design`_ for more information. + +All mandatory functions of BL2 must be implemented, except the functions +bl2\_early\_platform\_setup and bl2\_el3\_plat\_arch\_setup, because +their work is done now by bl2\_el3\_early\_platform\_setup and +bl2\_el3\_plat\_arch\_setup. These functions should generally implement +the bl1\_plat\_xxx() and bl2\_plat\_xxx() functionality combined. + + +Function : bl2\_el3\_early\_platform\_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + Argument : u_register_t, u_register_t, u_register_t, u_register_t + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. This function receives four parameters which can be used +by the platform to pass any needed information from the Boot ROM to BL2. + +On ARM standard platforms, this function does the following: + +- Initializes a UART (PL011 console), which enables access to the ``printf`` + family of functions in BL2. + +- Initializes the storage abstraction layer used to load further bootloader + images. It is necessary to do this early on platforms with a SCP\_BL2 image, + since the later ``bl2_platform_setup`` must be done after SCP\_BL2 is loaded. + +- Initializes the private variables that define the memory layout used. + +Function : bl2\_el3\_plat\_arch\_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. + +The purpose of this function is to perform any architectural initialization +that varies across platforms. + +On ARM standard platforms, this function enables the MMU. + +Function : bl2\_el3\_plat\_prepare\_exit() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + Argument : void + Return : void + +This function is called prior to exiting BL2 and run the next image. +It should be used to perform platform specific clean up or bookkeeping +operations before transferring control to the next image. This function +runs with MMU disabled. + FWU Boot Loader Stage 2 (BL2U) ------------------------------ diff --git a/docs/user-guide.rst b/docs/user-guide.rst index 0647e70..ed5ba18 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -245,6 +245,9 @@ BL2U image. In this case, the BL2U in the ARM Trusted Firmware will not be built. +- ``BL2_AT_EL3``: This is an optional build option that enables the use of + BL2 at EL3 execution level. + - ``BL31``: This is an optional build option which specifies the path to BL31 image for the ``fip`` target. In this case, the BL31 in the ARM Trusted Firmware will not be built. diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk index f2b6f6e..8c4123d 100644 --- a/drivers/auth/mbedtls/mbedtls_common.mk +++ b/drivers/auth/mbedtls/mbedtls_common.mk @@ -29,7 +29,4 @@ platform.c \ ) -BL1_SOURCES += ${MBEDTLS_COMMON_SOURCES} -BL2_SOURCES += ${MBEDTLS_COMMON_SOURCES} - endif diff --git a/drivers/auth/mbedtls/mbedtls_crypto.mk b/drivers/auth/mbedtls/mbedtls_crypto.mk index 8eb4873..6b15e71 100644 --- a/drivers/auth/mbedtls/mbedtls_crypto.mk +++ b/drivers/auth/mbedtls/mbedtls_crypto.mk @@ -89,6 +89,3 @@ # Needs to be set to drive mbed TLS configuration correctly $(eval $(call add_define,TF_MBEDTLS_KEY_ALG_ID)) $(eval $(call add_define,TF_MBEDTLS_HASH_ALG_ID)) - -BL1_SOURCES += ${MBEDTLS_CRYPTO_SOURCES} -BL2_SOURCES += ${MBEDTLS_CRYPTO_SOURCES} diff --git a/drivers/auth/mbedtls/mbedtls_x509.mk b/drivers/auth/mbedtls/mbedtls_x509.mk index 0f28b65..a6f72e6 100644 --- a/drivers/auth/mbedtls/mbedtls_x509.mk +++ b/drivers/auth/mbedtls/mbedtls_x509.mk @@ -11,6 +11,3 @@ x509.c \ x509_crt.c \ ) - -BL1_SOURCES += ${MBEDTLS_X509_SOURCES} -BL2_SOURCES += ${MBEDTLS_X509_SOURCES} diff --git a/include/common/aarch32/el3_common_macros.S b/include/common/aarch32/el3_common_macros.S index 59e99f8..d654b65 100644 --- a/include/common/aarch32/el3_common_macros.S +++ b/include/common/aarch32/el3_common_macros.S @@ -260,9 +260,9 @@ * --------------------------------------------------------------------- */ .if \_init_c_runtime -#ifdef IMAGE_BL32 +#if defined(IMAGE_BL32) || (defined(IMAGE_BL2) && BL2_AT_EL3) /* ----------------------------------------------------------------- - * Invalidate the RW memory used by the BL32 (SP_MIN) image. This + * Invalidate the RW memory used by the image. This * includes the data and NOBITS sections. This is done to * safeguard against possible corruption of this memory by * dirty cache lines in a system cache as a result of use by @@ -273,7 +273,7 @@ ldr r1, =__RW_END__ sub r1, r1, r0 bl inv_dcache_range -#endif /* IMAGE_BL32 */ +#endif ldr r0, =__BSS_START__ ldr r1, =__BSS_SIZE__ diff --git a/include/common/aarch64/el3_common_macros.S b/include/common/aarch64/el3_common_macros.S index defd4a2..4ebf77b 100644 --- a/include/common/aarch64/el3_common_macros.S +++ b/include/common/aarch64/el3_common_macros.S @@ -269,7 +269,7 @@ * --------------------------------------------------------------------- */ .if \_init_c_runtime -#ifdef IMAGE_BL31 +#if defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3) /* ------------------------------------------------------------- * Invalidate the RW memory used by the BL31 image. This * includes the data and NOBITS sections. This is done to @@ -282,7 +282,7 @@ adr x1, __RW_END__ sub x1, x1, x0 bl inv_dcache_range -#endif /* IMAGE_BL31 */ +#endif ldr x0, =__BSS_START__ ldr x1, =__BSS_SIZE__ diff --git a/include/common/asm_macros_common.S b/include/common/asm_macros_common.S index 6a02e18..ca8c1ad 100644 --- a/include/common/asm_macros_common.S +++ b/include/common/asm_macros_common.S @@ -29,7 +29,7 @@ * debugging experience. */ .cfi_sections .debug_frame - .section .text.\_name, "ax" + .section .text.asm.\_name, "ax" .type \_name, %function .func \_name /* diff --git a/include/lib/cpus/aarch32/cpu_macros.S b/include/lib/cpus/aarch32/cpu_macros.S index e2e4316..0f3a572 100644 --- a/include/lib/cpus/aarch32/cpu_macros.S +++ b/include/lib/cpus/aarch32/cpu_macros.S @@ -9,6 +9,10 @@ #include #include +#if defined(IMAGE_BL1) || defined(IMAGE_BL32) || (defined(IMAGE_BL2) && BL2_AT_EL3) +#define IMAGE_AT_EL3 +#endif + #define CPU_IMPL_PN_MASK (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) | \ (MIDR_PN_MASK << MIDR_PN_SHIFT) @@ -38,7 +42,7 @@ CPU_MIDR: /* cpu_ops midr */ .space 4 /* Reset fn is needed during reset */ -#if defined(IMAGE_BL1) || defined(IMAGE_BL32) +#if defined(IMAGE_AT_EL3) CPU_RESET_FUNC: /* cpu_ops reset_func */ .space 4 #endif @@ -54,7 +58,7 @@ #if REPORT_ERRATA CPU_ERRATA_FUNC: /* CPU errata status printing function */ .space 4 -#ifdef IMAGE_BL32 +#if defined(IMAGE_BL32) CPU_ERRATA_LOCK: .space 4 CPU_ERRATA_PRINTED: @@ -120,7 +124,7 @@ .align 2 .type cpu_ops_\_name, %object .word \_midr -#if defined(IMAGE_BL1) || defined(IMAGE_BL32) +#if defined(IMAGE_AT_EL3) .word \_resetfunc #endif #ifdef IMAGE_BL32 diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S index a8c23e5..ccf5306 100644 --- a/include/lib/cpus/aarch64/cpu_macros.S +++ b/include/lib/cpus/aarch64/cpu_macros.S @@ -21,6 +21,10 @@ /* Word size for 64-bit CPUs */ #define CPU_WORD_SIZE 8 +#if defined(IMAGE_BL1) || defined(IMAGE_BL31) ||(defined(IMAGE_BL2) && BL2_AT_EL3) +#define IMAGE_AT_EL3 +#endif + /* * Whether errata status needs reporting. Errata status is printed in debug * builds for both BL1 and BL31 images. @@ -38,7 +42,7 @@ CPU_MIDR: /* cpu_ops midr */ .space 8 /* Reset fn is needed in BL at reset vector */ -#if defined(IMAGE_BL1) || defined(IMAGE_BL31) +#if defined(IMAGE_AT_EL3) CPU_RESET_FUNC: /* cpu_ops reset_func */ .space 8 #endif @@ -54,7 +58,7 @@ #if REPORT_ERRATA CPU_ERRATA_FUNC: .space 8 -#ifdef IMAGE_BL31 +#if defined(IMAGE_BL31) CPU_ERRATA_LOCK: .space 8 CPU_ERRATA_PRINTED: @@ -124,7 +128,7 @@ .align 3 .type cpu_ops_\_name, %object .quad \_midr -#if defined(IMAGE_BL1) || defined(IMAGE_BL31) +#if defined(IMAGE_AT_EL3) .quad \_resetfunc #endif #ifdef IMAGE_BL31 diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h index 1be99b7..de1c2d4 100644 --- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h +++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h @@ -168,7 +168,7 @@ * This IMAGE_EL macro must not to be used outside the library, and it is only * used in AArch64. */ -#if defined(IMAGE_BL1) || defined(IMAGE_BL31) +#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3) # define IMAGE_EL 3 # define IMAGE_XLAT_DEFAULT_REGIME EL3_REGIME #else diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h index f38c357..697a0b0 100644 --- a/include/plat/arm/common/arm_def.h +++ b/include/plat/arm/common/arm_def.h @@ -334,6 +334,11 @@ #define BL2_BASE (BL1_RW_BASE - PLAT_ARM_MAX_BL2_SIZE) #define BL2_LIMIT BL1_RW_BASE +#elif BL2_AT_EL3 + +#define BL2_BASE ARM_BL_RAM_BASE +#define BL2_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) + #elif defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME /* * Put BL2 just below BL32. diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index abd7395..dfd7a20 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -145,6 +145,10 @@ uint32_t arm_get_spsr_for_bl33_entry(void); int arm_bl2_handle_post_image_load(unsigned int image_id); +/* BL2 at EL3 functions */ +void arm_bl2_el3_early_platform_setup(void); +void arm_bl2_el3_plat_arch_setup(void); + /* BL2U utility functions */ void arm_bl2u_early_platform_setup(struct meminfo *mem_layout, void *plat_info); diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index f11bee9..0960105 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -235,6 +235,21 @@ * Optional BL2 functions (may be overridden) ******************************************************************************/ + +/******************************************************************************* + * Mandatory BL2 at EL3 functions: Must be implemented if BL2_AT_EL3 image is + * supported + ******************************************************************************/ +void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3); +void bl2_el3_plat_arch_setup(void); + + +/******************************************************************************* + * Optional BL2 at EL3 functions (may be overridden) + ******************************************************************************/ +void bl2_el3_plat_prepare_exit(void); + /******************************************************************************* * Mandatory BL2U functions. ******************************************************************************/ diff --git a/lib/cpus/aarch32/cpu_helpers.S b/lib/cpus/aarch32/cpu_helpers.S index bfdc1e4..72e42c6 100644 --- a/lib/cpus/aarch32/cpu_helpers.S +++ b/lib/cpus/aarch32/cpu_helpers.S @@ -10,7 +10,7 @@ #include #include -#if defined(IMAGE_BL1) || defined(IMAGE_BL32) +#if defined(IMAGE_BL1) || defined(IMAGE_BL32) || (defined(IMAGE_BL2) && BL2_AT_EL3) /* * The reset handler common to all platforms. After a matching * cpu_ops structure entry is found, the correponding reset_handler @@ -42,7 +42,7 @@ bx lr endfunc reset_handler -#endif /* IMAGE_BL1 || IMAGE_BL32 */ +#endif #ifdef IMAGE_BL32 /* The power down core and cluster is needed only in BL32 */ /* diff --git a/lib/cpus/aarch64/cpu_helpers.S b/lib/cpus/aarch64/cpu_helpers.S index 2384553..ae1c3c2 100644 --- a/lib/cpus/aarch64/cpu_helpers.S +++ b/lib/cpus/aarch64/cpu_helpers.S @@ -7,7 +7,7 @@ #include #include #include -#ifdef IMAGE_BL31 +#if defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3) #include #endif #include @@ -15,7 +15,7 @@ #include /* Reset fn is needed in BL at reset vector */ -#if defined(IMAGE_BL1) || defined(IMAGE_BL31) +#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3) /* * The reset handler common to all platforms. After a matching * cpu_ops structure entry is found, the correponding reset_handler @@ -47,7 +47,7 @@ ret endfunc reset_handler -#endif /* IMAGE_BL1 || IMAGE_BL31 */ +#endif #ifdef IMAGE_BL31 /* The power down core and cluster is needed only in BL31 */ /* diff --git a/lib/cpus/errata_report.c b/lib/cpus/errata_report.c index 8d9f704..182679d 100644 --- a/lib/cpus/errata_report.c +++ b/lib/cpus/errata_report.c @@ -20,6 +20,8 @@ # define BL_STRING "BL31" #elif defined(AARCH32) && defined(IMAGE_BL32) # define BL_STRING "BL32" +#elif defined(IMAGE_BL2) && BL2_AT_EL3 +# define BL_STRING "BL2" #else # error This image should not be printing errata status #endif diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index fa0d17d..643890f 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -27,6 +27,9 @@ # Base commit to perform code check on BASE_COMMIT := origin/master +# Execute BL2 at EL3 +BL2_AT_EL3 := 0 + # By default, consider that the platform may release several CPUs out of reset. # The platform Makefile is free to override this value. COLD_BOOT_SINGLE_CPU := 0 diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk index 6e6e273..cda8d72 100644 --- a/make_helpers/tbbr/tbbr_tools.mk +++ b/make_helpers/tbbr/tbbr_tools.mk @@ -64,7 +64,9 @@ $(if ${BL2},$(eval $(call CERT_ADD_CMD_OPT,${BL2},--tb-fw,true)),\ $(eval $(call CERT_ADD_CMD_OPT,$(call IMG_BIN,2),--tb-fw,true))) $(eval $(call CERT_ADD_CMD_OPT,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert)) +ifeq (${BL2_AT_EL3}, 0) $(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert)) +endif # Add the SCP_BL2 CoT (key cert + img cert + image) ifneq (${SCP_BL2},) diff --git a/plat/arm/board/fvp/fvp_bl2_el3_setup.c b/plat/arm/board/fvp/fvp_bl2_el3_setup.c new file mode 100644 index 0000000..69f2f7a --- /dev/null +++ b/plat/arm/board/fvp/fvp_bl2_el3_setup.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "fvp_private.h" + +void bl2_el3_early_platform_setup(u_register_t arg0 __unused, + u_register_t arg1 __unused, + u_register_t arg2 __unused, + u_register_t arg3 __unused) +{ + arm_bl2_el3_early_platform_setup(); + + /* Initialize the platform config for future decision making */ + fvp_config_setup(); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + fvp_interconnect_init(); + /* + * Enable coherency in Interconnect for the primary CPU's cluster. + */ + fvp_interconnect_enable(); +} diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 9d3c5f6..a257784 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -126,6 +126,13 @@ plat/arm/board/fvp/fvp_trusted_boot.c \ ${FVP_SECURITY_SOURCES} +ifeq (${BL2_AT_EL3},1) +BL2_SOURCES += plat/arm/board/fvp/${ARCH}/fvp_helpers.S \ + plat/arm/board/fvp/fvp_bl2_el3_setup.c \ + ${FVP_CPU_LIBS} \ + ${FVP_INTERCONNECT_SOURCES} +endif + ifeq (${FVP_USE_SP804_TIMER},1) BL2_SOURCES += drivers/arm/sp804/sp804_delay_timer.c endif @@ -165,5 +172,9 @@ # Add support for platform supplied linker script for BL31 build $(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) +ifneq (${BL2_AT_EL3}, 0) + override BL1_SOURCES = +endif + include plat/arm/board/common/board_common.mk include plat/arm/common/arm_common.mk diff --git a/plat/arm/common/arm_bl2_el3_setup.c b/plat/arm/common/arm_bl2_el3_setup.c new file mode 100644 index 0000000..e70d115 --- /dev/null +++ b/plat/arm/common/arm_bl2_el3_setup.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include + +#pragma weak bl2_el3_early_platform_setup +#pragma weak bl2_el3_plat_arch_setup +#pragma weak bl2_el3_plat_prepare_exit + +static meminfo_t bl2_el3_tzram_layout; + +/* + * Perform arm specific early platform setup. At this moment we only initialize + * the console and the memory layout. + */ +void arm_bl2_el3_early_platform_setup(void) +{ + /* Initialize the console to provide early debug support */ + console_init(PLAT_ARM_BOOT_UART_BASE, PLAT_ARM_BOOT_UART_CLK_IN_HZ, + ARM_CONSOLE_BAUDRATE); + + /* + * Allow BL2 to see the whole Trusted RAM. This is determined + * statically since we cannot rely on BL1 passing this information + * in the BL2_AT_EL3 case. + */ + bl2_el3_tzram_layout.total_base = ARM_BL_RAM_BASE; + bl2_el3_tzram_layout.total_size = ARM_BL_RAM_SIZE; + + /* Initialise the IO layer and register platform IO devices */ + plat_arm_io_setup(); +} + +void bl2_el3_early_platform_setup(u_register_t arg0 __unused, + u_register_t arg1 __unused, + u_register_t arg2 __unused, + u_register_t arg3 __unused) +{ + arm_bl2_el3_early_platform_setup(); + + /* + * Initialize Interconnect for this cluster during cold boot. + * No need for locks as no other CPU is active. + */ + plat_arm_interconnect_init(); + /* + * Enable Interconnect coherency for the primary CPU's cluster. + */ + plat_arm_interconnect_enter_coherency(); + + generic_delay_timer_init(); +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only initializes the mmu in a quick and dirty way. + ******************************************************************************/ +void arm_bl2_el3_plat_arch_setup(void) +{ + arm_setup_page_tables(bl2_el3_tzram_layout.total_base, + bl2_el3_tzram_layout.total_size, + BL_CODE_BASE, + BL_CODE_END, + BL_RO_DATA_BASE, + BL_RO_DATA_END +#if USE_COHERENT_MEM + , BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END +#endif + ); + +#ifdef AARCH32 + enable_mmu_secure(0); +#else + enable_mmu_el3(0); +#endif +} + +void bl2_el3_plat_arch_setup(void) +{ + arm_bl2_el3_plat_arch_setup(); +} + +void bl2_el3_plat_prepare_exit(void) +{ +} diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk index fab57f1..e6ce18a 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -150,6 +150,11 @@ drivers/io/io_storage.c \ plat/arm/common/arm_bl2_setup.c \ plat/arm/common/arm_io_storage.c + +ifeq (${BL2_AT_EL3},1) +BL2_SOURCES += plat/arm/common/arm_bl2_el3_setup.c +endif + ifeq (${LOAD_IMAGE_V2},1) # Because BL1/BL2 execute in AArch64 mode but BL32 in AArch32 we need to use # the AArch32 descriptors. diff --git a/plat/common/plat_bl2_el3_common.c b/plat/common/plat_bl2_el3_common.c new file mode 100644 index 0000000..358a02d --- /dev/null +++ b/plat/common/plat_bl2_el3_common.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* + * The following platform functions are weakly defined. They + * are default implementations that allow BL2 to compile in + * absence of real definitions. The Platforms may override + * with more complex definitions. + */ +#pragma weak bl2_el3_plat_prepare_exit + +void bl2_el3_plat_prepare_exit(void) +{ +}