1/*
2 * Copyright (c) 2016 Cadence Design Systems, Inc.
3 * Copyright (c) 2017 Intel Corporation
4 * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd.
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8#include <zephyr/devicetree.h>
9#include <zephyr/linker/sections.h>
10#include <zephyr/linker/linker-defs.h>
11#include <zephyr/linker/linker-tool.h>
12
13#if !defined(CONFIG_BOOTLOADER_MCUBOOT)
14#error "APPCPU image must use MCUboot image format."
15#endif /* CONFIG_BOOTLOADER_MCUBOOT */
16
17#include "memory.h"
18
19/* User available SRAM memory segments */
20appcpu_iram_end = USER_IRAM_END - APPCPU_DRAM_SIZE;
21appcpu_iram_org = appcpu_iram_end - APPCPU_IRAM_SIZE;
22appcpu_iram_len = APPCPU_IRAM_SIZE;
23
24appcpu_dram_org = SRAM1_DRAM_USER_START;
25appcpu_dram_len = APPCPU_DRAM_SIZE;
26
27/* Aliases */
28#define ROMABLE_REGION   FLASH
29#define RODATA_REGION    dram0_1_seg
30#define RAMABLE_REGION   dram0_1_seg
31#define IRAM_REGION      iram0_1_seg
32
33/* Zephyr macro re-definitions */
34#undef GROUP_DATA_LINK_IN
35#define GROUP_DATA_LINK_IN(vregion, lregion) > vregion AT > lregion
36
37#undef GROUP_NOLOAD_LINK_IN
38#define GROUP_NOLOAD_LINK_IN(vregion, lregion) > vregion
39
40/* Flash segments (rodata and text) should be mapped in the virtual address spaces.
41 * Executing directly from LMA is not possible. */
42#undef GROUP_ROM_LINK_IN
43#define GROUP_ROM_LINK_IN(vregion, lregion) > RODATA_REGION AT > lregion
44
45/* Make sure new sections have consistent alignment between input and output sections */
46#undef SECTION_DATA_PROLOGUE
47#define SECTION_DATA_PROLOGUE(name, options, align) name options : ALIGN_WITH_INPUT
48
49#undef SECTION_PROLOGUE
50#define SECTION_PROLOGUE SECTION_DATA_PROLOGUE
51
52MEMORY
53{
54  mcuboot_hdr (R):  org = 0x0,  len = 0x20
55  metadata (R):     org = 0x20, len = 0x20
56  FLASH (R):        org = 0x40, len = FLASH_SIZE - 0x40
57
58  iram0_1_seg(RX): org = appcpu_iram_org, len = appcpu_iram_len
59  dram0_1_seg(RW): org = appcpu_dram_org, len = appcpu_dram_len
60
61#ifdef CONFIG_GEN_ISR_TABLES
62  IDT_LIST(RW): org = 0x3ebfe010, len = 0x2000
63#endif
64}
65
66/*  Default entry point:  */
67PROVIDE ( _ResetVector = 0x40000400 );
68ENTRY(__appcpu_start)
69
70_rom_store_table = 0;
71
72PROVIDE(_memmap_vecbase_reset = 0x40000450);
73PROVIDE(_memmap_reset_vector = 0x40000400);
74
75_heap_sentry = BOOTLOADER_DRAM_SEG_START + APPCPU_DRAM_SIZE;
76
77SECTIONS
78{
79  /* Reserve space for MCUboot header in the binary */
80  .mcuboot_header :
81  {
82    QUAD(0x0)
83    QUAD(0x0)
84    QUAD(0x0)
85    QUAD(0x0)
86  } > mcuboot_hdr
87  /* Image load table */
88  .metadata :
89  {
90    /* 0. Magic byte for load header */
91    LONG(0xace637d3)
92
93    /* 1. Application entry point address */
94    KEEP(*(.entry_addr))
95
96    /* IRAM metadata:
97     * 2. Destination address (VMA) for IRAM region
98     * 3. Flash offset (LMA) for start of IRAM region
99     * 4. Size of IRAM region
100     */
101    LONG(ADDR(.iram0.vectors))
102    LONG(LOADADDR(.iram0.vectors))
103    LONG(_iram_end - _init_start);
104
105    /* DRAM metadata:
106     * 5. Destination address (VMA) for DRAM region
107     * 6. Flash offset (LMA) for start of DRAM region
108     * 7. Size of DRAM region
109     */
110    LONG(ADDR(.dram0.data))
111    LONG(LOADADDR(.dram0.data))
112    LONG(_data_end - _data_start)
113  } > metadata
114
115  #include <zephyr/linker/rel-sections.ld>
116
117#ifdef CONFIG_LLEXT
118  #include <zephyr/linker/llext-sections.ld>
119#endif
120
121  /* --- START OF IRAM --- */
122
123  /* Send .iram0 code to iram */
124  .iram0.vectors : ALIGN(4)
125  {
126    /* Vectors go to IRAM */
127    _init_start = ABSOLUTE(.);
128    /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */
129    . = 0x0;
130    KEEP(*(.WindowVectors.text));
131    . = 0x180;
132    KEEP(*(.Level2InterruptVector.text));
133    . = 0x1c0;
134    KEEP(*(.Level3InterruptVector.text));
135    . = 0x200;
136    KEEP(*(.Level4InterruptVector.text));
137    . = 0x240;
138    KEEP(*(.Level5InterruptVector.text));
139    . = 0x280;
140    KEEP(*(.DebugExceptionVector.text));
141    . = 0x2c0;
142    KEEP(*(.NMIExceptionVector.text));
143    . = 0x300;
144    KEEP(*(.KernelExceptionVector.text));
145    . = 0x340;
146    KEEP(*(.UserExceptionVector.text));
147    . = 0x3C0;
148    KEEP(*(.DoubleExceptionVector.text));
149    . = 0x400;
150    *(.*Vector.literal)
151
152    *(.UserEnter.literal);
153    *(.UserEnter.text);
154    . = ALIGN (16);
155    *(.entry.text)
156    *(.init.literal)
157    *(.init)
158    _init_end = ABSOLUTE(.);
159
160    _iram_start = ABSOLUTE(.);
161  } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION)
162
163  .iram0.text : ALIGN(4)
164  {
165    /* Code marked as running out of IRAM */
166    _iram_text_start = ABSOLUTE(.);
167    *(.iram1 .iram1.*)
168    *(.iram0.literal .iram.literal .iram.text.literal .iram0.text .iram.text)
169    *libesp32.a:panic.*(.literal .text .literal.* .text.*)
170    *librtc.a:(.literal .text .literal.* .text.*)
171    *libsubsys__net__l2__ethernet.a:(.literal .text .literal.* .text.*)
172    *libsubsys__net__lib__config.a:(.literal .text .literal.* .text.*)
173    *libsubsys__net__ip.a:(.literal .text .literal.* .text.*)
174    *libsubsys__net.a:(.literal .text .literal.* .text.*)
175    *libarch__xtensa__core.a:(.literal .text .literal.* .text.*)
176    *libkernel.a:(.literal .text .literal.* .text.*)
177    *libsoc.a:rtc_*.*(.literal .text .literal.* .text.*)
178    *libsoc.a:cpu_util.*(.literal .text .literal.* .text.*)
179    *libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*)
180    *libdrivers__flash.a:flash_esp32.*(.literal .text .literal.* .text.*)
181    *libzephyr.a:spi_flash_rom_patch.*(.literal .text .literal.* .text.*)
182    *libzephyr.a:windowspill_asm.*(.literal .text .literal.* .text.*)
183    *libzephyr.a:log_noos.*(.literal .text .literal.* .text.*)
184    *libdrivers__timer.a:xtensa_sys_timer.*(.literal .text .literal.* .text.*)
185    *libzephyr.a:log_core.*(.literal .text .literal.* .text.*)
186    *libzephyr.a:cbprintf_complete.*(.literal .text .literal.* .text.*)
187    *libzephyr.a:printk.*(.literal.printk .literal.vprintk .literal.char_out .text.printk .text.vprintk .text.char_out)
188    *libzephyr.a:log_msg.*(.literal .text .literal.* .text.*)
189    *libzephyr.a:log_list.*(.literal .text .literal.* .text.*)
190    *libdrivers__console.a:uart_console.*(.literal.console_out .text.console_out)
191    *libzephyr.a:log_output.*(.literal .text .literal.* .text.*)
192    *libzephyr.a:log_backend_uart.*(.literal .text .literal.* .text.*)
193    *libzephyr.a:loader.*(.literal .text .literal.* .text.*)
194    *liblib__libc__minimal.a:string.*(.literal .text .literal.* .text.*)
195    *liblib__libc__newlib.a:string.*(.literal .text .literal.* .text.*)
196    *libc.a:*(.literal .text .literal.* .text.*)
197    *libphy.a:( .phyiram .phyiram.*)
198    *libgcov.a:(.literal .text .literal.* .text.*)
199
200    *libnet80211.a:( .wifi0iram  .wifi0iram.* .wifislpiram .wifislpiram.*)
201    *libpp.a:( .wifi0iram  .wifi0iram.* .wifislpiram .wifislpiram.* .wifiorslpiram .wifiorslpiram.*)
202
203    *libnet80211.a:( .wifirxiram  .wifirxiram.* .wifislprxiram .wifislprxiram.*)
204    *libpp.a:( .wifirxiram  .wifirxiram.* .wifislprxiram .wifislprxiram.*)
205
206    . = ALIGN(16);
207
208    _iram_text_end = ABSOLUTE(.);
209    _iram_end = ABSOLUTE(.);
210  } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION)
211
212  .flash.text : ALIGN(16)
213  {
214    _stext = .;
215    _text_start = ABSOLUTE(.);
216
217    *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
218    *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */
219    *(.fini.literal)
220    *(.fini)
221    *(.gnu.version)
222    *(.literal .text .literal.* .text.*)
223
224    /* CPU will try to prefetch up to 16 bytes of
225     * of instructions. This means that any configuration (e.g. MMU, PMS) must allow
226     * safe access to up to 16 bytes after the last real instruction, add
227     * dummy bytes to ensure this
228     */
229    . += 16;
230
231    _text_end = ABSOLUTE(.);
232    _etext = .;
233
234    /* Similar to _iram_start, this symbol goes here so it is
235     * resolved by addr2line in preference to the first symbol in
236     * the flash.text segment.
237     */
238    . = ALIGN(4);
239    _flash_cache_start = ABSOLUTE(0);
240
241    . = ALIGN(4);
242    _iram_end = ABSOLUTE(.);
243
244  } GROUP_DATA_LINK_IN(IRAM_REGION, ROMABLE_REGION)
245
246  /* --- END OF IRAM --- */
247
248  /* --- START OF DRAM --- */
249
250  .dram0.data :
251  {
252    . = ALIGN(16);
253    __data_start = ABSOLUTE(.);
254    _data_start = ABSOLUTE(.);
255
256    _btdm_data_start = ABSOLUTE(.);
257    *libbtdm_app.a:(.data .data.*)
258    . = ALIGN (4);
259    _btdm_data_end = ABSOLUTE(.);
260
261    *(.data)
262    *(.data.*)
263    *(.gnu.linkonce.d.*)
264    *(.data1)
265    *(.sdata)
266    *(.sdata.*)
267    *(.gnu.linkonce.s.*)
268    *(.sdata2)
269    *(.sdata2.*)
270    *(.gnu.linkonce.s2.*)
271    /* rodata for panic handler(libarch__xtensa__core.a) and all
272     * dependent functions should be placed in DRAM to avoid issue
273     * when flash cache is disabled */
274    *libarch__xtensa__core.a:(.rodata .rodata.*)
275    *libkernel.a:fatal.*(.rodata .rodata.*)
276    *libkernel.a:init.*(.rodata .rodata.*)
277    *libzephyr.a:cbprintf_complete*(.rodata .rodata.*)
278    *libzephyr.a:log_core.*(.rodata .rodata.*)
279    *libzephyr.a:log_backend_uart.*(.rodata .rodata.*)
280    *libzephyr.a:log_output.*(.rodata .rodata.*)
281    *libzephyr.a:loader.*(.rodata .rodata.*)
282    *libdrivers__flash.a:flash_esp32.*(.rodata .rodata.*)
283    *libzephyr.a:spi_flash_rom_patch.*(.rodata  .rodata.*)
284    *libdrivers__serial.a:uart_esp32.*(.rodata .rodata.*)
285
286    . = ALIGN(4);
287    #include <snippets-rwdata.ld>
288    . = ALIGN(4);
289
290    KEEP(*(.jcr))
291    *(.dram1 .dram1.*)
292    . = ALIGN(16);
293
294  } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
295
296  #include <snippets-data-sections.ld>
297  #include <zephyr/linker/common-ram.ld>
298  #include <snippets-ram-sections.ld>
299  #include <zephyr/linker/cplusplus-ram.ld>
300  #include <zephyr/linker/kobject-data.ld>
301  #include <zephyr/linker/common-rom/common-rom-logging.ld>
302
303  .dram0.rodata : ALIGN(4)
304  {
305    _rodata_start = ABSOLUTE(.);
306
307    *(.rodata_desc .rodata_desc.*)               /* Should be the first.  App version info.        DO NOT PUT ANYTHING BEFORE IT! */
308    *(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
309
310    __rodata_region_start = ABSOLUTE(.);
311    . = ALIGN(16);
312    #include <snippets-rodata.ld>
313
314    . = ALIGN(4);
315    *(EXCLUDE_FILE (
316        *libarch__xtensa__core.a:*
317        *libkernel.a:fatal.*
318        *libkernel.a:init.*
319        *libzephyr.a:cbprintf_complete*
320        *libzephyr.a:log_core.*
321        *libzephyr.a:log_backend_uart.*
322        *libzephyr.a:log_output.*
323        *libzephyr.a:loader.*
324        *libdrivers__serial.a:uart_esp32.*) .rodata)
325
326    *(EXCLUDE_FILE (
327        *libarch__xtensa__core.a:*
328        *libkernel.a:fatal.*
329        *libkernel.a:init.*
330        *libzephyr.a:cbprintf_complete*
331        *libzephyr.a:log_core.*
332        *libzephyr.a:log_backend_uart.*
333        *libzephyr.a:log_output.*
334        *libzephyr.a:loader.*
335        *libdrivers__serial.a:uart_esp32.*) .rodata.*)
336
337    *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
338    *(.gnu.linkonce.r.*)
339    *(.rodata1)
340    __XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
341    *(.xt_except_table)
342    *(.gcc_except_table .gcc_except_table.*)
343    *(.gnu.linkonce.e.*)
344    *(.gnu.version_r)
345    . = (. + 3) & ~ 3;
346    __eh_frame = ABSOLUTE(.);
347    KEEP(*(.eh_frame))
348    . = (. + 7) & ~ 3;
349
350    /*  C++ exception handlers table:  */
351    __XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
352    *(.xt_except_desc)
353    *(.gnu.linkonce.h.*)
354    __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
355    *(.xt_except_desc_end)
356    *(.dynamic)
357    *(.gnu.version_d)
358    . = ALIGN(4);
359    __rodata_region_end = ABSOLUTE(.);
360    /* Literals are also RO data. */
361    _lit4_start = ABSOLUTE(.);
362    *(*.lit4)
363    *(.lit4.*)
364    *(.gnu.linkonce.lit4.*)
365    _lit4_end = ABSOLUTE(.);
366    . = ALIGN(4);
367    _thread_local_start = ABSOLUTE(.);
368    *(.tdata)
369    *(.tdata.*)
370    *(.tbss)
371    *(.tbss.*)
372    *(.rodata_wlog)
373    *(.rodata_wlog*)
374    _thread_local_end = ABSOLUTE(.);
375    . = ALIGN(4);
376  } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION)
377
378  #include <zephyr/linker/cplusplus-rom.ld>
379  #include <zephyr/linker/common-rom/common-rom-init.ld>
380  #include <zephyr/linker/common-rom/common-rom-kernel-devices.ld>
381  #include <zephyr/linker/common-rom/common-rom-ztest.ld>
382  #include <zephyr/linker/common-rom/common-rom-net.ld>
383  #include <zephyr/linker/common-rom/common-rom-bt.ld>
384  #include <zephyr/linker/common-rom/common-rom-debug.ld>
385  #include <zephyr/linker/common-rom/common-rom-misc.ld>
386  #include <zephyr/linker/thread-local-storage.ld>
387  #include <snippets-sections.ld>
388
389  /* Create an explicit section at the end of all the data that shall be mapped into drom.
390   * This is used to calculate the size of the _image_drom_size variable */
391  .dram0.rodata_end : ALIGN(16)
392  {
393    . = ALIGN(4);
394    _image_rodata_end = ABSOLUTE(.);
395  } GROUP_DATA_LINK_IN(RODATA_REGION, ROMABLE_REGION)
396
397  .dram0.end :
398  {
399    __data_end = ABSOLUTE(.);
400    _data_end = ABSOLUTE(.);
401  } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
402
403  .dram0.noinit (NOLOAD):
404  {
405    . = ALIGN (8);
406    *(.noinit)
407    *(.noinit.*)
408    . = ALIGN (8);
409  } GROUP_LINK_IN(RAMABLE_REGION)
410
411  /* Shared RAM */
412  .dram0.bss (NOLOAD) :
413  {
414    . = ALIGN (8);
415    _bss_start = ABSOLUTE(.); /* required by bluetooth library */
416    __bss_start = ABSOLUTE(.);
417
418    _btdm_bss_start = ABSOLUTE(.);
419    *libbtdm_app.a:(.bss .bss.* COMMON)
420    . = ALIGN (4);
421    _btdm_bss_end = ABSOLUTE(.);
422
423    *(.dynsbss)
424    *(.sbss)
425    *(.sbss.*)
426    *(.gnu.linkonce.sb.*)
427    *(.scommon)
428    *(.sbss2)
429    *(.sbss2.*)
430    *(.gnu.linkonce.sb2.*)
431    *(.dynbss)
432    *(.bss)
433    *(.bss.*)
434    *(.share.mem)
435    *(.gnu.linkonce.b.*)
436    *(COMMON)
437    . = ALIGN (8);
438    __bss_end = ABSOLUTE(.);
439  } GROUP_LINK_IN(RAMABLE_REGION)
440
441  /* Provide total SRAM usage, including IRAM and DRAM */
442  _image_ram_start = __rodata_region_start;
443  #include <zephyr/linker/ram-end.ld>
444  _image_ram_size += _iram_end - _init_start;
445
446  ASSERT(((__bss_end - ORIGIN(dram0_1_seg)) <= LENGTH(dram0_1_seg)),
447          "DRAM segment data does not fit.")
448
449  /* --- END OF DRAM --- */
450
451#ifdef CONFIG_GEN_ISR_TABLES
452#include <zephyr/linker/intlist.ld>
453#endif
454
455#include <zephyr/linker/debug-sections.ld>
456
457  .xtensa.info  0 :  { *(.xtensa.info) }
458  .xt.insn 0 :
459  {
460    KEEP (*(.xt.insn))
461    KEEP (*(.gnu.linkonce.x.*))
462  }
463  .xt.prop 0 :
464  {
465    KEEP (*(.xt.prop))
466    KEEP (*(.xt.prop.*))
467    KEEP (*(.gnu.linkonce.prop.*))
468  }
469  .xt.lit 0 :
470  {
471    KEEP (*(.xt.lit))
472    KEEP (*(.xt.lit.*))
473    KEEP (*(.gnu.linkonce.p.*))
474  }
475  .xt.profile_range 0 :
476  {
477    KEEP (*(.xt.profile_range))
478    KEEP (*(.gnu.linkonce.profile_range.*))
479  }
480  .xt.profile_ranges 0 :
481  {
482    KEEP (*(.xt.profile_ranges))
483    KEEP (*(.gnu.linkonce.xt.profile_ranges.*))
484  }
485  .xt.profile_files 0 :
486  {
487    KEEP (*(.xt.profile_files))
488    KEEP (*(.gnu.linkonce.xt.profile_files.*))
489  }
490}
491
492ASSERT(((_iram_end - ORIGIN(iram0_1_seg)) <= LENGTH(iram0_1_seg)),
493          "IRAM0 segment data does not fit.")
494