mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-07 21:33:54 +00:00

Update linker file and init codes to allow using separated memory region for RW DATA. Init codes will copy the RW DATA from the image to the linked address. On some NXP platforms, after the BL31 image has been verified, the bl31 image space will be locked/protected as RO only, so need to move the RW DATA and NOBITS out of the bl31 image. Signed-off-by: Ye Li <ye.li@nxp.com> Reviewed-by: Peng Fan <peng.fan@nxp.com> Signed-off-by: Jacky Bai <ping.bai@nxp.com> Change-Id: I361d9a715890961bf30790a3325f8085a40c0c39
256 lines
6.7 KiB
ArmAsm
256 lines
6.7 KiB
ArmAsm
/*
|
|
* Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <common/bl_common.ld.h>
|
|
#include <lib/xlat_tables/xlat_tables_defs.h>
|
|
|
|
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
|
|
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
|
|
ENTRY(bl31_entrypoint)
|
|
|
|
MEMORY {
|
|
RAM (rwx): ORIGIN = BL31_BASE, LENGTH = BL31_LIMIT - BL31_BASE
|
|
|
|
#if SEPARATE_NOBITS_REGION
|
|
NOBITS (rw!a): ORIGIN = BL31_NOBITS_BASE, LENGTH = BL31_NOBITS_LIMIT - BL31_NOBITS_BASE
|
|
#else /* SEPARATE_NOBITS_REGION */
|
|
# define NOBITS RAM
|
|
#endif /* SEPARATE_NOBITS_REGION */
|
|
|
|
#if SEPARATE_RWDATA_REGION
|
|
RAM_RW (rw): ORIGIN = BL31_RWDATA_BASE, LENGTH = BL31_RWDATA_LIMIT - BL31_RWDATA_BASE
|
|
#else /* SEPARATE_RWDATA_REGION */
|
|
#define RAM_RW RAM
|
|
#endif /* SEPARATE_RWDATA_REGION */
|
|
}
|
|
|
|
#ifdef PLAT_EXTRA_LD_SCRIPT
|
|
# include <plat.ld.S>
|
|
#endif /* PLAT_EXTRA_LD_SCRIPT */
|
|
|
|
SECTIONS {
|
|
RAM_REGION_START = ORIGIN(RAM);
|
|
RAM_REGION_LENGTH = LENGTH(RAM);
|
|
. = BL31_BASE;
|
|
|
|
ASSERT(. == ALIGN(PAGE_SIZE),
|
|
"BL31_BASE address is not aligned on a page boundary.")
|
|
|
|
__BL31_START__ = .;
|
|
|
|
#if SEPARATE_CODE_AND_RODATA
|
|
.text . : {
|
|
ASSERT(. == ALIGN(PAGE_SIZE),
|
|
".text is not aligned on a page boundary.");
|
|
|
|
__TEXT_START__ = .;
|
|
|
|
*bl31_entrypoint.o(.text*)
|
|
*(SORT_BY_ALIGNMENT(SORT(.text*)))
|
|
*(.vectors)
|
|
__TEXT_END_UNALIGNED__ = .;
|
|
|
|
. = ALIGN(PAGE_SIZE);
|
|
|
|
__TEXT_END__ = .;
|
|
} >RAM
|
|
|
|
.rodata . : {
|
|
__RODATA_START__ = .;
|
|
|
|
*(SORT_BY_ALIGNMENT(.rodata*))
|
|
|
|
# if PLAT_EXTRA_RODATA_INCLUDES
|
|
# include <plat.ld.rodata.inc>
|
|
# endif /* PLAT_EXTRA_RODATA_INCLUDES */
|
|
|
|
RODATA_COMMON
|
|
|
|
. = ALIGN(8);
|
|
|
|
# include <lib/el3_runtime/pubsub_events.h>
|
|
__RODATA_END_UNALIGNED__ = .;
|
|
|
|
. = ALIGN(PAGE_SIZE);
|
|
|
|
__RODATA_END__ = .;
|
|
} >RAM
|
|
#else /* SEPARATE_CODE_AND_RODATA */
|
|
.ro . : {
|
|
ASSERT(. == ALIGN(PAGE_SIZE),
|
|
".ro is not aligned on a page boundary.");
|
|
|
|
__RO_START__ = .;
|
|
|
|
*bl31_entrypoint.o(.text*)
|
|
*(SORT_BY_ALIGNMENT(.text*))
|
|
*(SORT_BY_ALIGNMENT(.rodata*))
|
|
|
|
RODATA_COMMON
|
|
|
|
. = ALIGN(8);
|
|
|
|
# include <lib/el3_runtime/pubsub_events.h>
|
|
|
|
*(.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
|
|
* that the rest of the current memory page is unused.
|
|
*/
|
|
. = ALIGN(PAGE_SIZE);
|
|
|
|
__RO_END__ = .;
|
|
} >RAM
|
|
#endif /* SEPARATE_CODE_AND_RODATA */
|
|
|
|
ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__,
|
|
"cpu_ops not defined for this platform.")
|
|
|
|
#if SPM_MM || (SPMC_AT_EL3 && SPMC_AT_EL3_SEL0_SP)
|
|
# ifndef SPM_SHIM_EXCEPTIONS_VMA
|
|
# define SPM_SHIM_EXCEPTIONS_VMA RAM
|
|
# endif /* SPM_SHIM_EXCEPTIONS_VMA */
|
|
|
|
/*
|
|
* Exception vectors of the SPM shim layer. They must be aligned to a 2K
|
|
* address but we need to place them in a separate page so that we can set
|
|
* individual permissions on them, so the actual alignment needed is the
|
|
* page size.
|
|
*
|
|
* There's no need to include this into the RO section of BL31 because it
|
|
* doesn't need to be accessed by BL31.
|
|
*/
|
|
.spm_shim_exceptions : ALIGN(PAGE_SIZE) {
|
|
__SPM_SHIM_EXCEPTIONS_START__ = .;
|
|
|
|
*(.spm_shim_exceptions)
|
|
|
|
. = ALIGN(PAGE_SIZE);
|
|
|
|
__SPM_SHIM_EXCEPTIONS_END__ = .;
|
|
} >SPM_SHIM_EXCEPTIONS_VMA AT>RAM
|
|
|
|
PROVIDE(__SPM_SHIM_EXCEPTIONS_LMA__ = LOADADDR(.spm_shim_exceptions));
|
|
|
|
. = LOADADDR(.spm_shim_exceptions) + SIZEOF(.spm_shim_exceptions);
|
|
#endif /* SPM_MM || (SPMC_AT_EL3 && SPMC_AT_EL3_SEL0_SP) */
|
|
|
|
#if SEPARATE_RWDATA_REGION
|
|
. = BL31_RWDATA_BASE;
|
|
ASSERT(BL31_RWDATA_BASE == ALIGN(PAGE_SIZE),
|
|
"BL31_RWDATA_BASE address is not aligned on a page boundary.")
|
|
|
|
/*
|
|
* Define a linker symbol to mark the start of the RW memory area for this
|
|
* image.
|
|
*/
|
|
__RW_START__ = . ;
|
|
|
|
DATA_SECTION >RAM_RW AT>RAM
|
|
__DATA_RAM_START__ = __DATA_START__;
|
|
__DATA_RAM_END__ = __DATA_END__;
|
|
__DATA_ROM_START__ = LOADADDR(.data);
|
|
|
|
. = ALIGN(PAGE_SIZE);
|
|
__RW_END__ = .;
|
|
|
|
RELA_SECTION >RAM
|
|
#else /* SEPARATE_RWDATA_REGION */
|
|
/*
|
|
* Define a linker symbol to mark the start of the RW memory area for this
|
|
* image.
|
|
*/
|
|
__RW_START__ = . ;
|
|
|
|
DATA_SECTION >RAM
|
|
RELA_SECTION >RAM
|
|
#endif /* SEPARATE_RWDATA_REGION */
|
|
|
|
#ifdef BL31_PROGBITS_LIMIT
|
|
ASSERT(
|
|
. <= BL31_PROGBITS_LIMIT,
|
|
"BL31 progbits has exceeded its limit. Consider disabling some features."
|
|
)
|
|
#endif /* BL31_PROGBITS_LIMIT */
|
|
|
|
#if SEPARATE_NOBITS_REGION
|
|
. = ALIGN(PAGE_SIZE);
|
|
|
|
#if !SEPARATE_RWDATA_REGION
|
|
__RW_END__ = .;
|
|
#endif /* SEPARATE_RWDATA_REGION */
|
|
__BL31_END__ = .;
|
|
|
|
ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.")
|
|
|
|
. = BL31_NOBITS_BASE;
|
|
|
|
ASSERT(. == ALIGN(PAGE_SIZE),
|
|
"BL31 NOBITS base address is not aligned on a page boundary.")
|
|
|
|
__NOBITS_START__ = .;
|
|
#endif /* SEPARATE_NOBITS_REGION */
|
|
|
|
STACK_SECTION >NOBITS
|
|
BSS_SECTION >NOBITS
|
|
XLAT_TABLE_SECTION >NOBITS
|
|
|
|
#if USE_COHERENT_MEM
|
|
/*
|
|
* The base address of the coherent memory section must be page-aligned 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__ = .;
|
|
|
|
/*
|
|
* Bakery locks are stored in coherent memory. Each lock's data is
|
|
* contiguous and fully allocated by the compiler.
|
|
*/
|
|
*(.bakery_lock)
|
|
*(.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.
|
|
*/
|
|
. = ALIGN(PAGE_SIZE);
|
|
|
|
__COHERENT_RAM_END__ = .;
|
|
} >NOBITS
|
|
#endif /* USE_COHERENT_MEM */
|
|
|
|
#if SEPARATE_NOBITS_REGION
|
|
__NOBITS_END__ = .;
|
|
|
|
ASSERT(. <= BL31_NOBITS_LIMIT, "BL31 NOBITS region has exceeded its limit.")
|
|
#else /* SEPARATE_NOBITS_REGION */
|
|
/*
|
|
* Define a linker symbol to mark the end of the RW memory area for this
|
|
* image.
|
|
*/
|
|
#if !SEPARATE_RWDATA_REGION
|
|
__RW_END__ = .;
|
|
#endif /* SEPARATE_RWDATA_REGION */
|
|
__BL31_END__ = .;
|
|
|
|
ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.")
|
|
#endif /* SEPARATE_NOBITS_REGION */
|
|
RAM_REGION_END = .;
|
|
|
|
/DISCARD/ : {
|
|
*(.dynsym .dynstr .hash .gnu.hash)
|
|
}
|
|
}
|