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