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