1/*
2 * Copyright (c) 2016 Intel Corporation
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 Nios II platform
12 */
13
14#include <zephyr/linker/sections.h>
15
16#include <zephyr/linker/linker-defs.h>
17#include <zephyr/linker/linker-tool.h>
18
19/* These sections are specific to this CPU */
20#define _EXCEPTION_SECTION_NAME exceptions
21#define _RESET_SECTION_NAME reset
22
23/* This linker script requires the following macros to be defined in the
24 * SOC-specific linker script. All of these values can be found defined
25 * in system.h for CPU configurations that can generate a HAL.
26 *
27 * _RESET_VECTOR     CPU entry point at boot
28 * _EXC_VECTOR       General exception vector
29 * _ROM_ADDR         Beginning of flash memory
30 * _ROM_SIZE         Size in bytes of flash memory
31 * _RAM_ADDR         Beginning of RAM
32 * _RAM_SIZE         Size of RAM in bytes
33 *
34 * For now we support two scenarios:
35 *
36 * 1. Non-XIP systems where the reset vector is at the beginning of RAM
37 * with the exception vector 0x20 bytes after it.
38 * 2. XIP systems where the reset vector is at the beginning of ROM and
39 * the exception vector is in RAM
40 */
41
42#if defined(CONFIG_ROM_END_OFFSET)
43#define ROM_END_OFFSET CONFIG_ROM_END_OFFSET
44#else
45#define ROM_END_OFFSET 0
46#endif
47
48#ifdef CONFIG_XIP
49	#define ROMABLE_REGION FLASH
50#else
51	#define ROMABLE_REGION RAM
52#endif
53#define RAMABLE_REGION RAM
54
55#ifdef CONFIG_XIP
56
57ASSERT(_RESET_VECTOR == _ROM_ADDR, "Reset vector not at beginning of ROM!")
58
59MEMORY
60    {
61    RESET (rx) : ORIGIN = _RESET_VECTOR, LENGTH = 0x20
62    FLASH (rx) : ORIGIN = _RESET_VECTOR + 0x20 , LENGTH = (_ROM_SIZE - 0x20 - ROM_END_OFFSET)
63    RAM   (wx) : ORIGIN = _EXC_VECTOR, LENGTH = _RAM_SIZE - (_EXC_VECTOR - _RAM_ADDR)
64    /* Used by and documented in include/linker/intlist.ld */
65    IDT_LIST  (wx)      : ORIGIN = 0xFFFFF7FF, LENGTH = 2K
66
67    }
68
69#else
70
71MEMORY
72    {
73    RESET (wx) : ORIGIN = _RESET_VECTOR, LENGTH = 0x20
74    RAM   (wx) : ORIGIN = _EXC_VECTOR, LENGTH = _RAM_SIZE - (_EXC_VECTOR - _RAM_ADDR)
75
76    /* Used by and documented in include/linker/intlist.ld */
77    IDT_LIST  (wx)      : ORIGIN = 0xFFFFF7FF, LENGTH = 2K
78}
79#endif
80
81ENTRY(CONFIG_KERNEL_ENTRY)
82
83SECTIONS
84    {
85
86#include <zephyr/linker/rel-sections.ld>
87
88#ifdef CONFIG_LLEXT
89#include <zephyr/linker/llext-sections.ld>
90#endif
91
92    /*
93     * .plt and .iplt are here according to
94     * 'nios2-zephyr-elf-ld --verbose', before text section.
95     */
96    SECTION_PROLOGUE(.plt,,)
97        {
98        *(.plt)
99        }
100
101    SECTION_PROLOGUE(.iplt,,)
102        {
103        *(.iplt)
104        }
105
106    GROUP_START(ROMABLE_REGION)
107    __rom_region_start = _ROM_ADDR;
108
109    SECTION_PROLOGUE(_RESET_SECTION_NAME,,)
110    {
111        KEEP(*(.reset.*))
112    } GROUP_LINK_IN(RESET)
113
114#ifndef CONFIG_XIP
115    SECTION_PROLOGUE(_EXCEPTION_SECTION_NAME,,)
116        {
117            KEEP(*(".exception.entry.*"))
118            *(".exception.other.*")
119
120        } GROUP_LINK_IN(ROMABLE_REGION)
121#endif
122
123    SECTION_PROLOGUE(_TEXT_SECTION_NAME,,)
124        {
125        /* XXX If ALT_CPU_RESET_ADDR is not the same as _ROM_ADDR
126         * we are going to waste flash space? */
127        . = ALT_CPU_RESET_ADDR;
128
129        __text_region_start = .;
130
131        *(.text)
132        *(".text.*")
133        *(.gnu.linkonce.t.*)
134        } GROUP_LINK_IN(ROMABLE_REGION)
135
136    __text_region_end = .;
137
138#if defined(CONFIG_GP_ALL_DATA)
139        _gp = ABSOLUTE(. + 0x8000);
140        PROVIDE(gp = _gp);
141#endif
142
143    __rodata_region_start = .;
144
145#include <zephyr/linker/common-rom.ld>
146/* Located in generated directory. This file is populated by calling
147 * zephyr_linker_sources(ROM_SECTIONS ...). Useful for grouping iterable RO structs.
148 */
149#include <snippets-rom-sections.ld>
150
151    SECTION_PROLOGUE(_RODATA_SECTION_NAME,,)
152        {
153        . = ALIGN(4);
154
155        *(.rodata)
156        *(".rodata.*")
157        *(.gnu.linkonce.r.*)
158
159/* Located in generated directory. This file is populated by the
160 * zephyr_linker_sources() Cmake function.
161 */
162#include <snippets-rodata.ld>
163
164        . = ALIGN(4);
165        } GROUP_LINK_IN(ROMABLE_REGION)
166
167#include <zephyr/linker/cplusplus-rom.ld>
168
169    __rodata_region_end = .;
170    __rodata_region_size = __rodata_region_end - __rodata_region_start;
171
172    __rom_region_end = .;
173    __data_region_load_start = ALIGN(4);    /* XIP imaged DATA ROM start addr */
174
175    GROUP_END(ROMABLE_REGION)
176
177    GROUP_START(RAMABLE_REGION)
178
179#ifdef CONFIG_XIP
180    /* Altera strongly recommends keeping exception entry code in RAM
181     * even on XIP systems
182     *
183     * This is code not data, but we need this copied just like XIP data
184     */
185
186    SECTION_DATA_PROLOGUE(_EXCEPTION_SECTION_NAME,,)
187        {
188            _image_ram_start = .;
189            __data_region_start = .;
190
191            KEEP(*(".exception.entry.*"))
192            *(".exception.other.*")
193
194        } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
195#endif
196
197#ifndef CONFIG_XIP
198        _image_ram_start = .;
199#endif
200
201#include <zephyr/linker/common-ram.ld>
202
203    SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,)
204        {
205	__data_start = .;
206        *(.data)
207        *(".data.*")
208
209/* Located in generated directory. This file is populated by the
210 * zephyr_linker_sources() Cmake function.
211 */
212#include <snippets-rwdata.ld>
213
214        /* the Nios2 architecture only has 16-bit signed immediate offsets in
215         * the instructions, so accessing a general address requires typically
216         * three instructions - basically, two for the two halves of the 32-bit
217         * address, and one to merge them - but if we can put the most commonly
218         * accessed globals in a special 64K span of memory addressed by the GP
219         * register, then we can access those values in a single instruction,
220         * saving both codespace and runtime.
221         *
222         * Since these immediate offsets are signed, place gp 0x8000 past the
223         * beginning of .sdata so that we can use both positive and negative
224         * offsets.
225         */
226#if defined(CONFIG_GP_LOCAL) || defined(CONFIG_GP_GLOBAL)
227        _gp = ABSOLUTE(. + 0x8000);
228        PROVIDE(gp = _gp);
229#endif
230
231        *(.sdata .sdata.* .gnu.linkonce.s.*)
232        *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
233
234/* Located in generated directory. This file is populated by the
235 * zephyr_linker_sources() Cmake function.
236 */
237#include <snippets-ram-sections.ld>
238	__data_end = .;
239
240        } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
241    __data_size = __data_end - __data_start;
242    __data_load_start = LOADADDR(_DATA_SECTION_NAME);
243
244#include <zephyr/linker/cplusplus-ram.ld>
245
246/* Located in generated directory. This file is populated by the
247 * zephyr_linker_sources() Cmake function.
248 */
249#include <snippets-data-sections.ld>
250
251    __data_region_end = .;
252
253	SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),)
254        {
255        /*
256         * For performance, BSS section is assumed to be 4 byte aligned and
257         * a multiple of 4 bytes
258         */
259        . = ALIGN(4);
260        __bss_start = .;
261        *(.sbss)
262        *(".sbss.*")
263        *(.bss)
264        *(".bss.*")
265        COMMON_SYMBOLS
266        /*
267         * As memory is cleared in words only, it is simpler to ensure the BSS
268         * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes.
269                 */
270        __bss_end = ALIGN(4);
271        } GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)
272
273#include <zephyr/linker/common-noinit.ld>
274
275/* Located in generated directory. This file is populated by the
276 * zephyr_linker_sources() Cmake function.
277 */
278#include <snippets-sections.ld>
279
280#include <zephyr/linker/ram-end.ld>
281
282    GROUP_END(RAMABLE_REGION)
283
284#include <zephyr/linker/debug-sections.ld>
285
286    }
287