1/*
2 * Copyright (c) 2013-2014 Wind River Systems, Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7/**
8 * @file
9 * @brief Linker command/script file
10 *
11 * Linker script for the Cortex-A and Cortex-R platforms.
12 */
13
14#include <zephyr/linker/sections.h>
15#include <zephyr/devicetree.h>
16
17#include <zephyr/linker/devicetree_regions.h>
18#include <zephyr/linker/linker-defs.h>
19#include <zephyr/linker/linker-tool.h>
20
21/* physical address of RAM */
22#ifdef CONFIG_XIP
23  #define ROMABLE_REGION FLASH
24#else
25  #define ROMABLE_REGION RAM
26#endif
27#define RAMABLE_REGION RAM
28
29/* Region of the irq vectors and boot-vector SP/PC */
30#if defined(CONFIG_ROMSTART_RELOCATION_ROM)
31 #define ROMSTART_ADDR CONFIG_ROMSTART_REGION_ADDRESS
32 #define ROMSTART_SIZE (CONFIG_ROMSTART_REGION_SIZE * 1K)
33#else
34 #define ROMSTART_REGION ROMABLE_REGION
35#endif
36
37#if !defined(CONFIG_XIP) && (CONFIG_FLASH_SIZE == 0)
38  #define ROM_ADDR RAM_ADDR
39#else
40  #define ROM_ADDR (CONFIG_FLASH_BASE_ADDRESS + CONFIG_FLASH_LOAD_OFFSET)
41#endif
42
43#if defined(CONFIG_ROM_END_OFFSET)
44#define ROM_END_OFFSET CONFIG_ROM_END_OFFSET
45#else
46#define ROM_END_OFFSET 0
47#endif
48
49#if CONFIG_FLASH_LOAD_SIZE > 0
50  #define ROM_SIZE (CONFIG_FLASH_LOAD_SIZE - ROM_END_OFFSET)
51#else
52  #define ROM_SIZE (CONFIG_FLASH_SIZE*1K - CONFIG_FLASH_LOAD_OFFSET - ROM_END_OFFSET)
53#endif
54
55#define RAM_SIZE (CONFIG_SRAM_SIZE * 1K)
56#define RAM_ADDR CONFIG_SRAM_BASE_ADDRESS
57
58/* Set alignment to CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE
59 * to make linker section alignment comply with MPU granularity.
60 */
61#if defined(CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE)
62_region_min_align = CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE;
63#elif defined(CONFIG_ARM_AARCH32_MMU)
64_region_min_align = CONFIG_MMU_PAGE_SIZE;
65#else
66/* If building without MPU/MMU support, use default 4-byte alignment. */
67_region_min_align = 4;
68#endif
69
70#if defined(CONFIG_MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT)
71  #define MPU_ALIGN(region_size) \
72    . = ALIGN(_region_min_align); \
73    . = ALIGN(1 << LOG2CEIL(region_size))
74#else
75  #define MPU_ALIGN(region_size) \
76    . = ALIGN(_region_min_align)
77#endif
78
79#define BSS_ALIGN ALIGN(_region_min_align)
80
81#define MMU_ALIGN    . = ALIGN(_region_min_align)
82
83MEMORY
84{
85#if defined(CONFIG_ROMSTART_RELOCATION_ROM)
86    ROMSTART_REGION (rx) : ORIGIN = ROMSTART_ADDR, LENGTH = ROMSTART_SIZE
87#endif
88    FLASH    (rx) : ORIGIN = ROM_ADDR, LENGTH = ROM_SIZE
89    RAM      (wx) : ORIGIN = RAM_ADDR, LENGTH = RAM_SIZE
90    LINKER_DT_REGIONS()
91    /* Used by and documented in include/linker/intlist.ld */
92    IDT_LIST (wx) : ORIGIN = 0xFFFF8000, LENGTH = 32K
93}
94
95ENTRY(CONFIG_KERNEL_ENTRY)
96
97SECTIONS
98{
99#include <zephyr/linker/rel-sections.ld>
100
101#ifdef CONFIG_LLEXT
102#include <zephyr/linker/llext-sections.ld>
103#endif
104
105    /*
106     * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose',
107     * before text section.
108     */
109    SECTION_PROLOGUE(.plt,,)
110    {
111        *(.plt)
112    }
113
114    SECTION_PROLOGUE(.iplt,,)
115    {
116        *(.iplt)
117    }
118
119    GROUP_START(ROMABLE_REGION)
120
121#if defined(CONFIG_XIP)
122    __rom_region_start = ROM_ADDR;
123#else
124    __rom_region_start = RAM_ADDR;
125#endif
126
127    SECTION_PROLOGUE(rom_start,,)
128    {
129
130/* Located in generated directory. This file is populated by calling
131 * zephyr_linker_sources(ROM_START ...). This typically contains the vector
132 * table and debug information.
133 */
134#include <snippets-rom-start.ld>
135
136    } GROUP_LINK_IN(ROMSTART_REGION)
137
138#ifdef CONFIG_CODE_DATA_RELOCATION
139
140#include <linker_relocate.ld>
141
142#endif /* CONFIG_CODE_DATA_RELOCATION */
143
144    SECTION_PROLOGUE(_TEXT_SECTION_NAME,,)
145    {
146        . = ALIGN(_region_min_align);
147        __text_region_start = .;
148#ifndef CONFIG_XIP
149        z_mapped_start = .;
150#endif
151
152#include <zephyr/linker/kobject-text.ld>
153
154        *(.text)
155        *(".text.*")
156        *(.gnu.linkonce.t.*)
157
158        /*
159         * These are here according to 'arm-zephyr-elf-ld --verbose',
160         * after .gnu.linkonce.t.*
161         */
162        *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx)
163
164        __text_region_end = .;
165        . = ALIGN(_region_min_align);
166    } GROUP_LINK_IN(ROMABLE_REGION)
167
168#if defined (CONFIG_CPP)
169    SECTION_PROLOGUE(.ARM.extab,,)
170    {
171        /*
172         * .ARM.extab section containing exception unwinding information.
173         */
174        *(.ARM.extab* .gnu.linkonce.armextab.*)
175    } GROUP_LINK_IN(ROMABLE_REGION)
176#endif
177
178    SECTION_PROLOGUE(.ARM.exidx,,)
179    {
180        /*
181         * This section, related to stack and exception unwinding, is placed
182         * explicitly to prevent it from being shared between multiple regions.
183         * It  must be defined for gcc to support 64-bit math and avoid
184         * section overlap.
185         */
186        __exidx_start = .;
187#if defined (__GCC_LINKER_CMD__)
188        *(.ARM.exidx* gnu.linkonce.armexidx.*)
189#endif
190        __exidx_end = .;
191    } GROUP_LINK_IN(ROMABLE_REGION)
192
193    SECTION_PROLOGUE(rodata_start,,)
194    {
195        . = ALIGN(_region_min_align);
196        __rodata_region_start = .;
197    } GROUP_LINK_IN(ROMABLE_REGION)
198
199#include <zephyr/linker/common-rom.ld>
200/* Located in generated directory. This file is populated by calling
201 * zephyr_linker_sources(ROM_SECTIONS ...). Useful for grouping iterable RO structs.
202 */
203#include <snippets-rom-sections.ld>
204#include <zephyr/linker/thread-local-storage.ld>
205#include <zephyr/linker/cplusplus-rom.ld>
206
207    SECTION_PROLOGUE(_RODATA_SECTION_NAME,,)
208    {
209        *(.rodata)
210        *(".rodata.*")
211        *(.gnu.linkonce.r.*)
212
213/* Located in generated directory. This file is populated by the
214 * zephyr_linker_sources() Cmake function.
215 */
216#include <snippets-rodata.ld>
217
218#include <zephyr/linker/kobject-rom.ld>
219
220        /*
221         * For XIP images, in order to avoid the situation when __data_rom_start
222         * is 32-bit aligned, but the actual data is placed right after rodata
223         * section, which may not end exactly at 32-bit border, pad rodata
224         * section, so __data_rom_start points at data and it is 32-bit aligned.
225         *
226         * On non-XIP images this may enlarge image size up to 3 bytes. This
227         * generally is not an issue, since modern ROM and FLASH memory is
228         * usually 4k aligned.
229         */
230        . = ALIGN(4);
231
232        /*
233         * RODATA must be the last section so that the size of the entire read
234         * only area will be filled to a power of 2.
235         */
236        MPU_ALIGN(ABSOLUTE(.) - __rom_region_start);
237    } GROUP_LINK_IN(ROMABLE_REGION)
238
239    __rodata_region_end = .;
240    __rom_region_end = .;
241    MPU_ALIGN(__rodata_region_end - __rom_region_start);
242    _image_rom_end_order = (LOG2CEIL(__rom_region_end) - 1) << 1;
243
244    GROUP_END(ROMABLE_REGION)
245
246    /*
247     * These are here according to 'arm-zephyr-elf-ld --verbose',
248     * before data section.
249     */
250    SECTION_PROLOGUE(.got,,)
251    {
252        *(.got.plt)
253        *(.igot.plt)
254        *(.got)
255        *(.igot)
256    }
257
258    GROUP_START(RAMABLE_REGION)
259
260    . = RAM_ADDR;
261    /* Align the start of image RAM with the
262     * minimum granularity required by MPU.
263     */
264    . = ALIGN(_region_min_align);
265    _image_ram_start = .;
266#ifdef CONFIG_XIP
267    z_mapped_start = .;
268#endif
269
270/* Located in generated directory. This file is populated by the
271 * zephyr_linker_sources() Cmake function.
272 */
273#include <snippets-ram-sections.ld>
274
275#if defined(CONFIG_USERSPACE)
276#define APP_SHARED_ALIGN . = ALIGN(_region_min_align);
277#define SMEM_PARTITION_ALIGN MPU_ALIGN
278
279#include <app_smem.ld>
280
281    _app_smem_size = _app_smem_end - _app_smem_start;
282    _app_smem_rom_start = LOADADDR(_APP_SMEM_SECTION_NAME);
283#endif  /* CONFIG_USERSPACE */
284
285    SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD), BSS_ALIGN)
286    {
287        /*
288         * For performance, BSS section is assumed to be 4 byte aligned and
289         * a multiple of 4 bytes
290         */
291        . = ALIGN(4);
292        __bss_start = .;
293        __kernel_ram_start = .;
294
295        *(.bss)
296        *(".bss.*")
297        *(COMMON)
298        *(".kernel_bss.*")
299
300#ifdef CONFIG_CODE_DATA_RELOCATION
301#include <linker_sram_bss_relocate.ld>
302#endif
303
304        /*
305         * As memory is cleared in words only, it is simpler to ensure the BSS
306         * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes.
307         */
308        __bss_end = ALIGN(4);
309    } GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
310
311#include <zephyr/linker/common-noinit.ld>
312
313    SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,)
314    {
315        __data_region_start = .;
316        __data_start = .;
317        *(.data)
318        *(".data.*")
319        *(".kernel.*")
320
321/* Located in generated directory. This file is populated by the
322 * zephyr_linker_sources() Cmake function.
323 */
324#include <snippets-rwdata.ld>
325
326#ifdef CONFIG_CODE_DATA_RELOCATION
327#include <linker_sram_data_relocate.ld>
328#endif
329        __data_end = .;
330
331    } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
332    __data_size = __data_end - __data_start;
333    __data_load_start = LOADADDR(_DATA_SECTION_NAME);
334
335    __data_region_load_start = LOADADDR(_DATA_SECTION_NAME);
336
337#include <zephyr/linker/common-ram.ld>
338#include <zephyr/linker/kobject-data.ld>
339#include <zephyr/linker/cplusplus-ram.ld>
340
341/* Located in generated directory. This file is populated by the
342 * zephyr_linker_sources() Cmake function.
343 */
344#include <snippets-data-sections.ld>
345
346    __data_region_end = .;
347
348
349    /* Define linker symbols */
350
351    __kernel_ram_end = RAM_ADDR + RAM_SIZE;
352    __kernel_ram_size = __kernel_ram_end - __kernel_ram_start;
353
354#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ocm), okay)
355GROUP_START(OCM)
356
357	SECTION_PROLOGUE(_OCM_BSS_SECTION_NAME, (NOLOAD),SUBALIGN(4))
358	{
359		__ocm_start = .;
360		__ocm_bss_start = .;
361		*(.ocm_bss)
362		*(".ocm_bss.*")
363		__ocm_bss_end = .;
364	} GROUP_LINK_IN(LINKER_DT_NODE_REGION_NAME(DT_CHOSEN(zephyr_ocm)))
365
366	SECTION_PROLOGUE(_OCM_DATA_SECTION_NAME,,SUBALIGN(4))
367	{
368		__ocm_data_start = .;
369		*(.ocm_data)
370		*(".ocm_data.*")
371		__ocm_data_end = .;
372	} GROUP_LINK_IN(LINKER_DT_NODE_REGION_NAME(DT_CHOSEN(zephyr_ocm)))
373
374  __ocm_end = .;
375  __ocm_size = __ocm_end - __ocm_start;
376
377GROUP_END(OCM)
378#endif
379
380/* Located in generated directory. This file is populated by the
381 * zephyr_linker_sources() Cmake function.
382 */
383#include <snippets-sections.ld>
384
385#define LAST_RAM_ALIGN . = ALIGN(_region_min_align);
386
387#include <zephyr/linker/ram-end.ld>
388
389    GROUP_END(RAMABLE_REGION)
390
391#include <zephyr/linker/debug-sections.ld>
392
393    SECTION_PROLOGUE(.ARM.attributes, 0,)
394    {
395        KEEP(*(.ARM.attributes))
396        KEEP(*(.gnu.attributes))
397    }
398
399    /* Sections generated from 'zephyr,memory-region' nodes */
400    LINKER_DT_SECTIONS()
401
402    /* Must be last in romable region */
403    SECTION_PROLOGUE(.last_section,,)
404    {
405#ifdef CONFIG_LINKER_LAST_SECTION_ID
406      /* Fill last section with a word to ensure location counter and actual rom
407       * region data usage match. */
408      LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN)
409#endif
410    } GROUP_LINK_IN(ROMABLE_REGION)
411
412    /* To provide the image size as a const expression,
413     * calculate this value here. */
414    _flash_used = LOADADDR(.last_section) + SIZEOF(.last_section) - __rom_region_start;
415
416}
417