Add support for BL2 in XIP memory

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 patch enable this
use-case with a new build option, BL2_IN_XIP_MEM. For now, this option
is only supported when BL2_AT_EL3 is 1.

Signed-off-by: Jiafei Pan <Jiafei.Pan@nxp.com>
This commit is contained in:
Jiafei Pan 2018-03-21 07:20:09 +00:00
parent 93883a2931
commit 7d173fc594
8 changed files with 125 additions and 5 deletions

View File

@ -373,6 +373,11 @@ ifneq ($(MULTI_CONSOLE_API), 0)
endif endif
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 # 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,USE_TBBR_DEFS))
$(eval $(call assert_boolean,WARMBOOT_ENABLE_DCACHE_EARLY)) $(eval $(call assert_boolean,WARMBOOT_ENABLE_DCACHE_EARLY))
$(eval $(call assert_boolean,BL2_AT_EL3)) $(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_MAJOR))
$(eval $(call assert_numeric,ARM_ARCH_MINOR)) $(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,USE_TBBR_DEFS))
$(eval $(call add_define,WARMBOOT_ENABLE_DCACHE_EARLY)) $(eval $(call add_define,WARMBOOT_ENABLE_DCACHE_EARLY))
$(eval $(call add_define,BL2_AT_EL3)) $(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. # Define the EL3_PAYLOAD_BASE flag only if it is provided.
ifdef EL3_PAYLOAD_BASE ifdef EL3_PAYLOAD_BASE

View File

@ -12,15 +12,26 @@ OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
ENTRY(bl2_entrypoint) ENTRY(bl2_entrypoint)
MEMORY { 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 RAM (rwx): ORIGIN = BL2_BASE, LENGTH = BL2_LIMIT - BL2_BASE
#endif
} }
SECTIONS 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; . = BL2_BASE;
ASSERT(. == ALIGN(PAGE_SIZE), ASSERT(. == ALIGN(PAGE_SIZE),
"BL2_BASE address is not aligned on a page boundary.") "BL2_BASE address is not aligned on a page boundary.")
#endif
#if SEPARATE_CODE_AND_RODATA #if SEPARATE_CODE_AND_RODATA
.text . : { .text . : {
@ -33,7 +44,11 @@ SECTIONS
*(.vectors) *(.vectors)
. = NEXT(PAGE_SIZE); . = NEXT(PAGE_SIZE);
__TEXT_END__ = .; __TEXT_END__ = .;
#if BL2_IN_XIP_MEM
} >ROM
#else
} >RAM } >RAM
#endif
.rodata . : { .rodata . : {
__RODATA_START__ = .; __RODATA_START__ = .;
@ -56,7 +71,11 @@ SECTIONS
. = NEXT(PAGE_SIZE); . = NEXT(PAGE_SIZE);
__RODATA_END__ = .; __RODATA_END__ = .;
#if BL2_IN_XIP_MEM
} >ROM
#else
} >RAM } >RAM
#endif
ASSERT(__TEXT_RESIDENT_END__ - __TEXT_RESIDENT_START__ <= PAGE_SIZE, ASSERT(__TEXT_RESIDENT_END__ - __TEXT_RESIDENT_START__ <= PAGE_SIZE,
"Resident part of BL2 has exceeded its limit.") "Resident part of BL2 has exceeded its limit.")
@ -95,12 +114,22 @@ SECTIONS
. = NEXT(PAGE_SIZE); . = NEXT(PAGE_SIZE);
__RO_END__ = .; __RO_END__ = .;
#if BL2_IN_XIP_MEM
} >ROM
#else
} >RAM } >RAM
#endif
#endif #endif
ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__,
"cpu_ops not defined for this platform.") "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 * Define a linker symbol to mark start of the RW memory area for this
* image. * image.
@ -113,10 +142,14 @@ SECTIONS
* section can be placed independently of the main .data section. * section can be placed independently of the main .data section.
*/ */
.data . : { .data . : {
__DATA_START__ = .; __DATA_RAM_START__ = .;
*(.data*) *(.data*)
__DATA_END__ = .; __DATA_RAM_END__ = .;
#if BL2_IN_XIP_MEM
} >RAM AT>ROM
#else
} >RAM } >RAM
#endif
stacks (NOLOAD) : { stacks (NOLOAD) : {
__STACKS_START__ = .; __STACKS_START__ = .;
@ -174,12 +207,32 @@ SECTIONS
__RW_END__ = .; __RW_END__ = .;
__BL2_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); __BSS_SIZE__ = SIZEOF(.bss);
#if USE_COHERENT_MEM #if USE_COHERENT_MEM
__COHERENT_RAM_UNALIGNED_SIZE__ = __COHERENT_RAM_UNALIGNED_SIZE__ =
__COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__;
#endif #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.") ASSERT(. <= BL2_LIMIT, "BL2 image has exceeded its limit.")
#endif
} }

View File

@ -7,6 +7,20 @@
#ifndef __BL2_PRIVATE_H__ #ifndef __BL2_PRIVATE_H__
#define __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 * Forward declarations
*****************************************/ *****************************************/

View File

@ -217,11 +217,37 @@ platform port to define additional platform porting constants in
- **#define : BL2\_BASE** - **#define : BL2\_BASE**
Defines the base address in secure RAM where BL1 loads the BL2 binary image. 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** - **#define : BL2\_LIMIT**
Defines the maximum address in secure RAM that the BL2 image can occupy. 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** - **#define : BL31\_BASE**

View File

@ -246,6 +246,12 @@ Common build options
- ``BL2_AT_EL3``: This is an optional build option that enables the use of - ``BL2_AT_EL3``: This is an optional build option that enables the use of
BL2 at EL3 execution level. 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``: 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 BL31 image for the ``fip`` target. In this case, the BL31 in TF-A will not
be built. be built.

View File

@ -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 * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -294,7 +294,7 @@
bl zeromem bl zeromem
#endif #endif
#ifdef IMAGE_BL1 #if defined(IMAGE_BL1) || (defined(IMAGE_BL2) && BL2_IN_XIP_MEM)
ldr x0, =__DATA_RAM_START__ ldr x0, =__DATA_RAM_START__
ldr x1, =__DATA_ROM_START__ ldr x1, =__DATA_ROM_START__
ldr x2, =__DATA_SIZE__ ldr x2, =__DATA_SIZE__

View File

@ -78,9 +78,19 @@
#define BL1_CODE_END BL_CODE_END #define BL1_CODE_END BL_CODE_END
#define BL1_RO_DATA_BASE BL_RO_DATA_BASE #define BL1_RO_DATA_BASE BL_RO_DATA_BASE
#define BL1_RO_DATA_END round_up(BL1_ROM_END, PAGE_SIZE) #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 #else
#define BL_RO_DATA_BASE 0 #define BL_RO_DATA_BASE 0
#define BL_RO_DATA_END 0 #define BL_RO_DATA_END 0
#define BL1_CODE_END round_up(BL1_ROM_END, PAGE_SIZE) #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 /* SEPARATE_CODE_AND_RODATA */
#endif /* __COMMON_DEF_H__ */ #endif /* __COMMON_DEF_H__ */

View File

@ -30,6 +30,10 @@ BASE_COMMIT := origin/master
# Execute BL2 at EL3 # Execute BL2 at EL3
BL2_AT_EL3 := 0 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. # By default, consider that the platform may release several CPUs out of reset.
# The platform Makefile is free to override this value. # The platform Makefile is free to override this value.
COLD_BOOT_SINGLE_CPU := 0 COLD_BOOT_SINGLE_CPU := 0