1/*
2 * Copyright 2023 NXP
3 * Copyright (c) 2013-2014 Wind River Systems, Inc.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8
9/* This is mostly a copy of arch/arm64/scripts/linker.ld with
10 * a few SOF-related changes. This is needed in order to avoid
11 * introducing sections based on CONFIG_SOF in the main ARM64
12 * linker script.
13 */
14#include <zephyr/linker/sections.h>
15#include <zephyr/devicetree.h>
16
17#include <zephyr/linker/linker-defs.h>
18#include <zephyr/linker/linker-tool.h>
19
20/* physical address of RAM */
21#ifdef CONFIG_XIP
22  #define ROMABLE_REGION FLASH
23#else
24  #define ROMABLE_REGION RAM
25#endif
26#define RAMABLE_REGION RAM
27
28#if !defined(CONFIG_XIP) && (CONFIG_FLASH_SIZE == 0)
29  #define ROM_ADDR RAM_ADDR
30#else
31  #define ROM_ADDR (CONFIG_FLASH_BASE_ADDRESS + CONFIG_FLASH_LOAD_OFFSET)
32#endif
33
34#if CONFIG_FLASH_LOAD_SIZE > 0
35  #define ROM_SIZE CONFIG_FLASH_LOAD_SIZE
36#else
37  #define ROM_SIZE (CONFIG_FLASH_SIZE * 1K - CONFIG_FLASH_LOAD_OFFSET)
38#endif
39
40#define RAM_SIZE (CONFIG_SRAM_SIZE * 1K)
41#define RAM_ADDR CONFIG_SRAM_BASE_ADDRESS
42
43#if defined(CONFIG_ARM_MMU)
44  _region_min_align = CONFIG_MMU_PAGE_SIZE;
45#elif defined(CONFIG_ARM_MPU)
46  _region_min_align = CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE;
47  #define BSS_ALIGN ALIGN(_region_min_align)
48#else
49  /* If building without MMU support, use default 4-byte alignment. */
50  _region_min_align = 4;
51#endif
52
53#ifndef BSS_ALIGN
54#define BSS_ALIGN
55#endif
56
57#define MMU_ALIGN    . = ALIGN(_region_min_align)
58
59MEMORY
60{
61    FLASH     (rx) : ORIGIN = ROM_ADDR, LENGTH = ROM_SIZE
62    RAM       (wx) : ORIGIN = RAM_ADDR, LENGTH = RAM_SIZE
63    /* Used by and documented in include/linker/intlist.ld */
64    IDT_LIST  (wx) : ORIGIN = 0xFFFFF7FF, LENGTH = 2K
65}
66
67ENTRY(CONFIG_KERNEL_ENTRY)
68
69SECTIONS
70{
71
72#include <zephyr/linker/rel-sections.ld>
73
74    /*
75     * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose',
76     * before text section.
77     */
78    /DISCARD/ :
79    {
80        *(.plt)
81    }
82
83    /DISCARD/ :
84    {
85        *(.iplt)
86    }
87
88    GROUP_START(ROMABLE_REGION)
89
90    __rom_region_start = ROM_ADDR;
91
92    SECTION_PROLOGUE(_TEXT_SECTION_NAME,,)
93    {
94        __text_region_start = .;
95#ifndef CONFIG_XIP
96        z_mapped_start = .;
97#endif
98
99#ifdef CONFIG_AARCH64_IMAGE_HEADER
100        KEEP(*(.image_header))
101        KEEP(*(".image_header.*"))
102#endif
103
104        _vector_start = .;
105        KEEP(*(.exc_vector_table))
106        KEEP(*(".exc_vector_table.*"))
107
108        KEEP(*(.vectors))
109
110        _vector_end = .;
111
112        *(.text)
113        *(".text.*")
114        *(.gnu.linkonce.t.*)
115
116        /*
117         * These are here according to 'arm-zephyr-elf-ld --verbose',
118         * after .gnu.linkonce.t.*
119         */
120        *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx)
121
122#include <zephyr/linker/kobject-text.ld>
123
124        MMU_ALIGN;
125    } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
126
127    __text_region_end = .;
128    __text_region_size = __text_region_end - __text_region_start;
129
130#if defined (CONFIG_CPP)
131    SECTION_PROLOGUE(.ARM.extab,,)
132    {
133        /*
134         * .ARM.extab section containing exception unwinding information.
135         */
136        *(.ARM.extab* .gnu.linkonce.armextab.*)
137    } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
138#endif
139
140    SECTION_PROLOGUE(.ARM.exidx,,)
141    {
142        /*
143         * This section, related to stack and exception unwinding, is placed
144         * explicitly to prevent it from being shared between multiple regions.
145         * It  must be defined for gcc to support 64-bit math and avoid
146         * section overlap.
147         */
148        __exidx_start = .;
149#if defined (__GCC_LINKER_CMD__)
150        *(.ARM.exidx* gnu.linkonce.armexidx.*)
151#endif
152        __exidx_end = .;
153    } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
154
155        __rodata_region_start = .;
156
157#include <zephyr/linker/common-rom.ld>
158#include <zephyr/linker/thread-local-storage.ld>
159
160    SECTION_PROLOGUE(_RODATA_SECTION_NAME,,)
161    {
162        *(.rodata)
163        *(".rodata.*")
164        *(.gnu.linkonce.r.*)
165
166        /*
167         * The following is a workaround to allow compiling with GCC 12 and
168         * above, which may emit "GOT indirections" for the weak symbol
169         * references (see the GitHub issue zephyrproject-rtos/sdk-ng#547).
170         */
171        *(.got)
172        *(.got.plt)
173
174/* Located in generated directory. This file is populated by the
175 * zephyr_linker_sources() Cmake function.
176 */
177#include <snippets-rodata.ld>
178
179#include <zephyr/linker/kobject-rom.ld>
180
181    } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
182
183#include <zephyr/linker/cplusplus-rom.ld>
184    MMU_ALIGN;
185
186    __rodata_region_end = .;
187    __rodata_region_size = __rodata_region_end - __rodata_region_start;
188    __rom_region_end = .;
189
190    /*
191     * These are here according to 'arm-zephyr-elf-ld --verbose',
192     * before data section.
193     */
194    /DISCARD/ :
195    {
196        *(.igot.plt)
197        *(.igot)
198    }
199
200    GROUP_END(ROMABLE_REGION)
201
202    GROUP_START(RAMABLE_REGION)
203
204    . = RAM_ADDR;
205    /* Align the start of image RAM with the
206     * minimum granularity required by MMU.
207     */
208    . = ALIGN(_region_min_align);
209    _image_ram_start = .;
210#ifdef CONFIG_XIP
211    z_mapped_start = .;
212#endif
213
214/* Located in generated directory. This file is populated by the
215 * zephyr_linker_sources() Cmake function.
216 */
217#include <snippets-ram-sections.ld>
218
219#if defined(CONFIG_USERSPACE)
220#define APP_SHARED_ALIGN . = ALIGN(_region_min_align);
221#define SMEM_PARTITION_ALIGN(size) MMU_ALIGN
222
223#if defined(CONFIG_ARM_MPU)
224/*
225 * When _app_smem region is empty, alignment is also needed. If there
226 * is no alignment, the _app_smem_start used by arm mpu can be lower
227 * than __rodata_region_end, and this two regions can overlap.
228 * The Armv8-R aarch64 MPU does not allow overlapped regions.
229 */
230#define EMPTY_APP_SHARED_ALIGN APP_SHARED_ALIGN
231#endif
232
233#include <app_smem.ld>
234
235    _app_smem_size = _app_smem_end - _app_smem_start;
236    _app_smem_rom_start = LOADADDR(_APP_SMEM_SECTION_NAME);
237#endif  /* CONFIG_USERSPACE */
238
239    SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD), BSS_ALIGN)
240    {
241        /*
242         * For performance, BSS section is assumed to be 4 byte aligned and
243         * a multiple of 4 bytes
244         */
245        . = ALIGN(4);
246        __bss_start = .;
247        __kernel_ram_start = .;
248
249        *(.bss)
250        *(".bss.*")
251        *(COMMON)
252        *(".kernel_bss.*")
253
254        /*
255         * As memory is cleared in words only, it is simpler to ensure the BSS
256         * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes.
257                 */
258        __bss_end = ALIGN(4);
259    } GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
260
261#if CONFIG_SOF
262    SECTION_PROLOGUE(.static_uuid_entries,,)
263    {
264        *(*.static_uuids)
265    } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
266
267    SECTION_PROLOGUE(.static_log_entries,,)
268    {
269        *(*.static_log*)
270    } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
271#endif /* CONFIG_SOF */
272
273#include <zephyr/linker/common-noinit.ld>
274
275    SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,)
276    {
277	__data_region_start = .;
278	__data_start = .;
279        *(.data)
280        *(".data.*")
281        *(".kernel.*")
282#if CONFIG_SOF
283	_trace_ctx_start = ABSOLUTE(.);
284	*(.trace_ctx)
285	_trace_ctx_end = ABSOLUTE(.);
286#endif /* CONFIG_SOF */
287
288/* Located in generated directory. This file is populated by the
289 * zephyr_linker_sources() Cmake function.
290 */
291#include <snippets-rwdata.ld>
292
293        __data_end = .;
294
295    } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
296    __data_size = __data_end - __data_start;
297    __data_load_start = LOADADDR(_DATA_SECTION_NAME);
298
299    __data_region_load_start = LOADADDR(_DATA_SECTION_NAME);
300
301#include <zephyr/linker/common-ram.ld>
302#include <zephyr/linker/kobject-data.ld>
303#include <zephyr/linker/cplusplus-ram.ld>
304
305/* Located in generated directory. This file is populated by the
306 * zephyr_linker_sources() Cmake function.
307 */
308#include <snippets-data-sections.ld>
309
310    __data_region_end = .;
311
312
313    /* Define linker symbols */
314
315/* Located in generated directory. This file is populated by the
316 * zephyr_linker_sources() Cmake function.
317 */
318#include <snippets-sections.ld>
319
320#define LAST_RAM_ALIGN MMU_ALIGN;
321
322#include <zephyr/linker/ram-end.ld>
323
324    GROUP_END(RAMABLE_REGION)
325
326    __kernel_ram_end = RAM_ADDR + RAM_SIZE;
327    __kernel_ram_size = __kernel_ram_end - __kernel_ram_start;
328
329#include <zephyr/linker/debug-sections.ld>
330
331    SECTION_PROLOGUE(.ARM.attributes, 0,)
332    {
333        KEEP(*(.ARM.attributes))
334        KEEP(*(.gnu.attributes))
335    }
336
337    /DISCARD/ : { *(.note.GNU-stack) }
338
339
340    /* Must be last in romable region */
341    SECTION_PROLOGUE(.last_section,,)
342    {
343#ifdef CONFIG_LINKER_LAST_SECTION_ID
344      /* Fill last section with a word to ensure location counter and actual rom
345       * region data usage match. */
346      LONG(CONFIG_LINKER_LAST_SECTION_ID_PATTERN)
347#endif
348    } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
349
350    /* To provide the image size as a const expression,
351     * calculate this value here. */
352    _flash_used = LOADADDR(.last_section) + SIZEOF(.last_section) - __rom_region_start;
353
354}
355