1/* 2 * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7#include <common/bl_common.ld.h> 8#include <lib/per_cpu/per_cpu_defs.h> 9#include <lib/xlat_tables/xlat_tables_defs.h> 10 11OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) 12OUTPUT_ARCH(PLATFORM_LINKER_ARCH) 13ENTRY(bl31_entrypoint) 14 15MEMORY { 16 RAM (rwx): ORIGIN = BL31_BASE, LENGTH = BL31_LIMIT - BL31_BASE 17 18#if SEPARATE_NOBITS_REGION 19 NOBITS (rw!a): ORIGIN = BL31_NOBITS_BASE, LENGTH = BL31_NOBITS_LIMIT - BL31_NOBITS_BASE 20#else /* SEPARATE_NOBITS_REGION */ 21# define NOBITS RAM 22#endif /* SEPARATE_NOBITS_REGION */ 23 24#if SEPARATE_RWDATA_REGION 25 RAM_RW (rw): ORIGIN = BL31_RWDATA_BASE, LENGTH = BL31_RWDATA_LIMIT - BL31_RWDATA_BASE 26#else /* SEPARATE_RWDATA_REGION */ 27#define RAM_RW RAM 28#endif /* SEPARATE_RWDATA_REGION */ 29} 30 31#if PLAT_EXTRA_LD_SCRIPT 32# include <plat.ld.S> 33#endif /* PLAT_EXTRA_LD_SCRIPT */ 34 35SECTIONS { 36 RAM_REGION_START = ORIGIN(RAM); 37 RAM_REGION_LENGTH = LENGTH(RAM); 38 . = BL31_BASE; 39 40 ASSERT(. == ALIGN(PAGE_SIZE), 41 "BL31_BASE address is not aligned on a page boundary.") 42 43 __BL31_START__ = .; 44 45#if SEPARATE_CODE_AND_RODATA 46 .text . : { 47 ASSERT(. == ALIGN(PAGE_SIZE), 48 ".text is not aligned on a page boundary."); 49 50 __TEXT_START__ = .; 51 52 *bl31_entrypoint.o(.text*) 53 *(SORT_BY_ALIGNMENT(SORT(.text*))) 54 *(.vectors) 55 __TEXT_END_UNALIGNED__ = .; 56 57 . = ALIGN(PAGE_SIZE); 58 59 __TEXT_END__ = .; 60 } >RAM 61 62 .rodata . : { 63 __RODATA_START__ = .; 64 65 *(SORT_BY_ALIGNMENT(.rodata*)) 66 67# if PLAT_EXTRA_RODATA_INCLUDES 68# include <plat.ld.rodata.inc> 69# endif /* PLAT_EXTRA_RODATA_INCLUDES */ 70 71 RODATA_COMMON 72 73 . = ALIGN(8); 74 75# include <lib/el3_runtime/pubsub_events.h> 76 __RODATA_END_UNALIGNED__ = .; 77 78 . = ALIGN(PAGE_SIZE); 79 80 __RODATA_END__ = .; 81 } >RAM 82#else /* SEPARATE_CODE_AND_RODATA */ 83 .ro . : { 84 ASSERT(. == ALIGN(PAGE_SIZE), 85 ".ro is not aligned on a page boundary."); 86 87 __RO_START__ = .; 88 89 *bl31_entrypoint.o(.text*) 90 *(SORT_BY_ALIGNMENT(.text*)) 91 *(SORT_BY_ALIGNMENT(.rodata*)) 92 93 RODATA_COMMON 94 95 . = ALIGN(8); 96 97# include <lib/el3_runtime/pubsub_events.h> 98 99 *(.vectors) 100 101 __RO_END_UNALIGNED__ = .; 102 103 /* 104 * Memory page(s) mapped to this section will be marked as read-only, 105 * executable. No RW data from the next section must creep in. Ensure 106 * that the rest of the current memory page is unused. 107 */ 108 . = ALIGN(PAGE_SIZE); 109 110 __RO_END__ = .; 111 } >RAM 112#endif /* SEPARATE_CODE_AND_RODATA */ 113 114 ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, 115 "cpu_ops not defined for this platform.") 116 117#if SPM_MM || (SPMC_AT_EL3 && SPMC_AT_EL3_SEL0_SP) 118# ifndef SPM_SHIM_EXCEPTIONS_VMA 119# define SPM_SHIM_EXCEPTIONS_VMA RAM 120# endif /* SPM_SHIM_EXCEPTIONS_VMA */ 121 122 /* 123 * Exception vectors of the SPM shim layer. They must be aligned to a 2K 124 * address but we need to place them in a separate page so that we can set 125 * individual permissions on them, so the actual alignment needed is the 126 * page size. 127 * 128 * There's no need to include this into the RO section of BL31 because it 129 * doesn't need to be accessed by BL31. 130 */ 131 .spm_shim_exceptions : ALIGN(PAGE_SIZE) { 132 __SPM_SHIM_EXCEPTIONS_START__ = .; 133 134 *(.spm_shim_exceptions) 135 136 . = ALIGN(PAGE_SIZE); 137 138 __SPM_SHIM_EXCEPTIONS_END__ = .; 139 } >SPM_SHIM_EXCEPTIONS_VMA AT>RAM 140 141 PROVIDE(__SPM_SHIM_EXCEPTIONS_LMA__ = LOADADDR(.spm_shim_exceptions)); 142 143 . = LOADADDR(.spm_shim_exceptions) + SIZEOF(.spm_shim_exceptions); 144#endif /* SPM_MM || (SPMC_AT_EL3 && SPMC_AT_EL3_SEL0_SP) */ 145 146#if SEPARATE_RWDATA_REGION 147 . = BL31_RWDATA_BASE; 148 ASSERT(BL31_RWDATA_BASE == ALIGN(PAGE_SIZE), 149 "BL31_RWDATA_BASE address is not aligned on a page boundary.") 150 151 /* 152 * Define a linker symbol to mark the start of the RW memory area for this 153 * image. 154 */ 155 __RW_START__ = . ; 156 157 DATA_SECTION >RAM_RW AT>RAM 158 __DATA_RAM_START__ = __DATA_START__; 159 __DATA_RAM_END__ = __DATA_END__; 160 __DATA_ROM_START__ = LOADADDR(.data); 161 162 . = ALIGN(PAGE_SIZE); 163 __RW_END__ = .; 164 165 RELA_SECTION >RAM 166#else /* SEPARATE_RWDATA_REGION */ 167 /* 168 * Define a linker symbol to mark the start of the RW memory area for this 169 * image. 170 */ 171 __RW_START__ = . ; 172 173 DATA_SECTION >RAM 174 RELA_SECTION >RAM 175#endif /* SEPARATE_RWDATA_REGION */ 176 177#ifdef BL31_PROGBITS_LIMIT 178 ASSERT( 179 . <= BL31_PROGBITS_LIMIT, 180 "BL31 progbits has exceeded its limit. Consider disabling some features." 181 ) 182#endif /* BL31_PROGBITS_LIMIT */ 183 184#if SEPARATE_NOBITS_REGION 185 . = ALIGN(PAGE_SIZE); 186 187#if !SEPARATE_RWDATA_REGION 188 __RW_END__ = .; 189#endif /* SEPARATE_RWDATA_REGION */ 190 __BL31_END__ = .; 191 192 ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.") 193 194 . = BL31_NOBITS_BASE; 195 196 ASSERT(. == ALIGN(PAGE_SIZE), 197 "BL31 NOBITS base address is not aligned on a page boundary.") 198 199 __NOBITS_START__ = .; 200#endif /* SEPARATE_NOBITS_REGION */ 201 202 STACK_SECTION >NOBITS 203 BSS_SECTION >NOBITS 204 PER_CPU >NOBITS 205 XLAT_TABLE_SECTION >NOBITS 206 207#if USE_COHERENT_MEM 208 /* 209 * The base address of the coherent memory section must be page-aligned to 210 * guarantee that the coherent data are stored on their own pages and are 211 * not mixed with normal data. This is required to set up the correct 212 * memory attributes for the coherent data page tables. 213 */ 214 .coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { 215 __COHERENT_RAM_START__ = .; 216 217 /* 218 * Bakery locks are stored in coherent memory. Each lock's data is 219 * contiguous and fully allocated by the compiler. 220 */ 221 *(.bakery_lock) 222 *(.tzfw_coherent_mem) 223 224 __COHERENT_RAM_END_UNALIGNED__ = .; 225 226 /* 227 * Memory page(s) mapped to this section will be marked as device 228 * memory. No other unexpected data must creep in. Ensure the rest of 229 * the current memory page is unused. 230 */ 231 . = ALIGN(PAGE_SIZE); 232 233 __COHERENT_RAM_END__ = .; 234 } >NOBITS 235#endif /* USE_COHERENT_MEM */ 236 237#if SEPARATE_NOBITS_REGION 238 __NOBITS_END__ = .; 239 240 ASSERT(. <= BL31_NOBITS_LIMIT, "BL31 NOBITS region has exceeded its limit.") 241#else /* SEPARATE_NOBITS_REGION */ 242 /* 243 * Define a linker symbol to mark the end of the RW memory area for this 244 * image. 245 */ 246#if !SEPARATE_RWDATA_REGION 247 __RW_END__ = .; 248#endif /* SEPARATE_RWDATA_REGION */ 249 __BL31_END__ = .; 250 251 ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.") 252#endif /* SEPARATE_NOBITS_REGION */ 253 RAM_REGION_END = .; 254 255 /DISCARD/ : { 256 *(.dynsym .dynstr .hash .gnu.hash) 257 } 258} 259