diff --git a/Makefile b/Makefile index ef4e5c681..a8378462b 100644 --- a/Makefile +++ b/Makefile @@ -373,6 +373,11 @@ ifneq ($(MULTI_CONSOLE_API), 0) endif endif +#For now, BL2_IN_XIP_MEM is only supported when BL2_AT_EL3 is 1. +ifeq ($(BL2_AT_EL3)-$(BL2_IN_XIP_MEM),0-1) +$(error "BL2_IN_XIP_MEM is only supported when BL2_AT_EL3 is enabled") +endif + ################################################################################ # Process platform overrideable behaviour ################################################################################ @@ -518,6 +523,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_boolean,BL2_IN_XIP_MEM)) $(eval $(call assert_numeric,ARM_ARCH_MAJOR)) $(eval $(call assert_numeric,ARM_ARCH_MINOR)) @@ -564,6 +570,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)) +$(eval $(call add_define,BL2_IN_XIP_MEM)) # Define the EL3_PAYLOAD_BASE flag only if it is provided. ifdef EL3_PAYLOAD_BASE diff --git a/bl2/bl2_el3.ld.S b/bl2/bl2_el3.ld.S index 3728643ca..0f91edc95 100644 --- a/bl2/bl2_el3.ld.S +++ b/bl2/bl2_el3.ld.S @@ -12,15 +12,26 @@ OUTPUT_ARCH(PLATFORM_LINKER_ARCH) ENTRY(bl2_entrypoint) MEMORY { +#if BL2_IN_XIP_MEM + ROM (rx): ORIGIN = BL2_RO_BASE, LENGTH = BL2_RO_LIMIT - BL2_RO_BASE + RAM (rwx): ORIGIN = BL2_RW_BASE, LENGTH = BL2_RW_LIMIT - BL2_RW_BASE +#else RAM (rwx): ORIGIN = BL2_BASE, LENGTH = BL2_LIMIT - BL2_BASE +#endif } SECTIONS { +#if BL2_IN_XIP_MEM + . = BL2_RO_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL2_RO_BASE address is not aligned on a page boundary.") +#else . = BL2_BASE; ASSERT(. == ALIGN(PAGE_SIZE), "BL2_BASE address is not aligned on a page boundary.") +#endif #if SEPARATE_CODE_AND_RODATA .text . : { @@ -33,7 +44,11 @@ SECTIONS *(.vectors) . = NEXT(PAGE_SIZE); __TEXT_END__ = .; +#if BL2_IN_XIP_MEM + } >ROM +#else } >RAM +#endif .rodata . : { __RODATA_START__ = .; @@ -56,7 +71,11 @@ SECTIONS . = NEXT(PAGE_SIZE); __RODATA_END__ = .; +#if BL2_IN_XIP_MEM + } >ROM +#else } >RAM +#endif ASSERT(__TEXT_RESIDENT_END__ - __TEXT_RESIDENT_START__ <= PAGE_SIZE, "Resident part of BL2 has exceeded its limit.") @@ -95,12 +114,22 @@ SECTIONS . = NEXT(PAGE_SIZE); __RO_END__ = .; +#if BL2_IN_XIP_MEM + } >ROM +#else } >RAM +#endif #endif ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, "cpu_ops not defined for this platform.") +#if BL2_IN_XIP_MEM + . = BL2_RW_BASE; + ASSERT(BL2_RW_BASE == ALIGN(PAGE_SIZE), + "BL2_RW_BASE address is not aligned on a page boundary.") +#endif + /* * Define a linker symbol to mark start of the RW memory area for this * image. @@ -113,10 +142,14 @@ SECTIONS * section can be placed independently of the main .data section. */ .data . : { - __DATA_START__ = .; + __DATA_RAM_START__ = .; *(.data*) - __DATA_END__ = .; + __DATA_RAM_END__ = .; +#if BL2_IN_XIP_MEM + } >RAM AT>ROM +#else } >RAM +#endif stacks (NOLOAD) : { __STACKS_START__ = .; @@ -174,12 +207,32 @@ SECTIONS __RW_END__ = .; __BL2_END__ = .; +#if BL2_IN_XIP_MEM + __BL2_RAM_START__ = ADDR(.data); + __BL2_RAM_END__ = .; + + __DATA_ROM_START__ = LOADADDR(.data); + __DATA_SIZE__ = SIZEOF(.data); + + /* + * The .data section is the last PROGBITS section so its end marks the end + * of BL2's RO content in XIP memory.. + */ + __BL2_ROM_END__ = __DATA_ROM_START__ + __DATA_SIZE__; + ASSERT(__BL2_ROM_END__ <= BL2_RO_LIMIT, + "BL2's RO content has exceeded its limit.") +#endif __BSS_SIZE__ = SIZEOF(.bss); + #if USE_COHERENT_MEM __COHERENT_RAM_UNALIGNED_SIZE__ = __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; #endif +#if BL2_IN_XIP_MEM + ASSERT(. <= BL2_RW_LIMIT, "BL2's RW content has exceeded its limit.") +#else ASSERT(. <= BL2_LIMIT, "BL2 image has exceeded its limit.") +#endif } diff --git a/bl2/bl2_private.h b/bl2/bl2_private.h index 50295d674..f93a179d1 100644 --- a/bl2/bl2_private.h +++ b/bl2/bl2_private.h @@ -7,6 +7,20 @@ #ifndef __BL2_PRIVATE_H__ #define __BL2_PRIVATE_H__ +#if BL2_IN_XIP_MEM +/******************************************************************************* + * Declarations of linker defined symbols which will tell us where BL2 lives + * in Trusted ROM and RAM + ******************************************************************************/ +extern uintptr_t __BL2_ROM_END__; +#define BL2_ROM_END (uintptr_t)(&__BL2_ROM_END__) + +extern uintptr_t __BL2_RAM_START__; +extern uintptr_t __BL2_RAM_END__; +#define BL2_RAM_BASE (uintptr_t)(&__BL2_RAM_START__) +#define BL2_RAM_LIMIT (uintptr_t)(&__BL2_RAM_END__) +#endif + /****************************************** * Forward declarations *****************************************/ diff --git a/docs/porting-guide.rst b/docs/porting-guide.rst index ff5bb1225..12e135f71 100644 --- a/docs/porting-guide.rst +++ b/docs/porting-guide.rst @@ -217,11 +217,37 @@ platform port to define additional platform porting constants in - **#define : BL2\_BASE** Defines the base address in secure RAM where BL1 loads the BL2 binary image. - Must be aligned on a page-size boundary. + Must be aligned on a page-size boundary. This constant is not applicable + when BL2_IN_XIP_MEM is set to '1'. - **#define : BL2\_LIMIT** Defines the maximum address in secure RAM that the BL2 image can occupy. + This constant is not applicable when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2\_RO\_BASE** + + Defines the base address in secure XIP memory where BL2 RO section originally + lives. Must be aligned on a page-size boundary. This constant is only needed + when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2\_RO\_LIMIT** + + Defines the maximum address in secure XIP memory that BL2's actual content + (i.e. excluding any data section allocated at runtime) can occupy. This + constant is only needed when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2\_RW\_BASE** + + Defines the base address in secure RAM where BL2's read-write data will live + at runtime. Must be aligned on a page-size boundary. This constant is only + needed when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2\_RW\_LIMIT** + + Defines the maximum address in secure RAM that BL2's read-write data can + occupy at runtime. This constant is only needed when BL2_IN_XIP_MEM is set + to '1'. - **#define : BL31\_BASE** diff --git a/docs/user-guide.rst b/docs/user-guide.rst index 579485546..fdf1568e1 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -246,6 +246,12 @@ Common build options - ``BL2_AT_EL3``: This is an optional build option that enables the use of BL2 at EL3 execution level. +- ``BL2_IN_XIP_MEM``: In some use-cases BL2 will be stored in eXecute In Place + (XIP) memory, like BL1. In these use-cases, it is necessary to initialize + the RW sections in RAM, while leaving the RO sections in place. This option + enable this use-case. For now, this option is only supported when BL2_AT_EL3 + is set to '1'. + - ``BL31``: This is an optional build option which specifies the path to BL31 image for the ``fip`` target. In this case, the BL31 in TF-A will not be built. diff --git a/include/common/aarch64/el3_common_macros.S b/include/common/aarch64/el3_common_macros.S index 4ebf77bbf..e85249c41 100644 --- a/include/common/aarch64/el3_common_macros.S +++ b/include/common/aarch64/el3_common_macros.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -294,7 +294,7 @@ bl zeromem #endif -#ifdef IMAGE_BL1 +#if defined(IMAGE_BL1) || (defined(IMAGE_BL2) && BL2_IN_XIP_MEM) ldr x0, =__DATA_RAM_START__ ldr x1, =__DATA_ROM_START__ ldr x2, =__DATA_SIZE__ diff --git a/include/plat/common/common_def.h b/include/plat/common/common_def.h index 84923b9a7..827d416f3 100644 --- a/include/plat/common/common_def.h +++ b/include/plat/common/common_def.h @@ -78,9 +78,19 @@ #define BL1_CODE_END BL_CODE_END #define BL1_RO_DATA_BASE BL_RO_DATA_BASE #define BL1_RO_DATA_END round_up(BL1_ROM_END, PAGE_SIZE) +#if BL2_IN_XIP_MEM +#define BL2_CODE_END BL_CODE_END +#define BL2_RO_DATA_BASE BL_RO_DATA_BASE +#define BL2_RO_DATA_END round_up(BL2_ROM_END, PAGE_SIZE) +#endif /* BL2_IN_XIP_MEM */ #else #define BL_RO_DATA_BASE 0 #define BL_RO_DATA_END 0 #define BL1_CODE_END round_up(BL1_ROM_END, PAGE_SIZE) +#if BL2_IN_XIP_MEM +#define BL2_RO_DATA_BASE 0 +#define BL2_RO_DATA_END 0 +#define BL2_CODE_END round_up(BL2_ROM_END, PAGE_SIZE) +#endif /* BL2_IN_XIP_MEM */ #endif /* SEPARATE_CODE_AND_RODATA */ #endif /* __COMMON_DEF_H__ */ diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 751f8343c..77eb157c6 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -30,6 +30,10 @@ BASE_COMMIT := origin/master # Execute BL2 at EL3 BL2_AT_EL3 := 0 +# BL2 image is stored in XIP memory, for now, this option is only supported +# when BL2_AT_EL3 is 1. +BL2_IN_XIP_MEM := 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