1/*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Description:
8 *      GNU LD linker script.
9 */
10
11#include <arch_scatter.h>
12
13ENTRY(arch_exception_reset)
14
15MEMORY {
16#if FMW_MEM_MODE == ARCH_MEM_MODE_SINGLE_REGION
17    /*
18     * Single region memory layout:
19     *  - MEM0 accepts:
20     *      - Read-only sections
21     *      - Read-write sections
22     *      - Executable sections
23     */
24
25    mem0 (rwx) : ORIGIN = FMW_MEM0_BASE, LENGTH = FMW_MEM0_SIZE
26#elif FMW_MEM_MODE == ARCH_MEM_MODE_DUAL_REGION_RELOCATION
27    /*
28     * Dual region memory layout with initialized data relocation:
29     *  - MEM0 accepts:
30     *      - Read-only sections
31     *      - Executable sections
32     *
33     *  - MEM1 accepts:
34     *      - Read-write sections
35     */
36
37    mem0 (rx) : ORIGIN = FMW_MEM0_BASE, LENGTH = FMW_MEM0_SIZE
38    mem1 (w) : ORIGIN = FMW_MEM1_BASE, LENGTH = FMW_MEM1_SIZE
39#elif FMW_MEM_MODE == ARCH_MEM_MODE_DUAL_REGION_NO_RELOCATION
40    /*
41     * Dual region memory layout without initialized data relocation:
42     *  - MEM0 accepts:
43     *      - Executable sections
44     *
45     *  - MEM1 accepts:
46     *      - Read-only sections
47     *      - Read-write sections
48     */
49
50    mem0 (x) : ORIGIN = FMW_MEM0_BASE, LENGTH = FMW_MEM0_SIZE
51    mem1 (rw) : ORIGIN = FMW_MEM1_BASE, LENGTH = FMW_MEM1_SIZE
52#endif
53}
54
55#if FMW_MEM_MODE == ARCH_MEM_MODE_SINGLE_REGION
56    REGION_ALIAS("r", mem0);
57    REGION_ALIAS("w", mem0);
58    REGION_ALIAS("x", mem0);
59#elif FMW_MEM_MODE == ARCH_MEM_MODE_DUAL_REGION_RELOCATION
60    REGION_ALIAS("r", mem0);
61    REGION_ALIAS("w", mem1);
62    REGION_ALIAS("x", mem0);
63#elif FMW_MEM_MODE == ARCH_MEM_MODE_DUAL_REGION_NO_RELOCATION
64    REGION_ALIAS("r", mem1);
65    REGION_ALIAS("w", mem1);
66    REGION_ALIAS("x", mem0);
67#endif
68
69SECTIONS {
70    /*
71     * Variables defined here:
72     *   - __data_load__: Load address of .data
73     *   - __data_start__: Start address of .data
74     *   - __data_end__: End address of .data and .data-like orphans
75     *   - __bss_start__: Start address of .bss
76     *   - __bss_end__: End address of .bss and .bss-like orphans
77     *   - __stackheap_start__: Start address of .stackheap
78     *   - __stackheap_end__: End address of .stackheap
79     *   - __stack: Initial stack pointer
80     */
81
82    .exceptions : {
83        KEEP(*(.exceptions))
84    } > x
85
86    .text : {
87        *(.text .text.*)
88    } > x
89
90#ifdef __clang__
91    .eh_frame : {
92        (.eh_frame)
93    } > x
94
95    .ARM.exidx : {
96        (.ARM.exidx)
97    } > x
98#endif
99
100    /*
101     * .init and .fini below refer to sections containing functions meant to
102     * run before program startup and after program shutdown. While we don't use
103     * these functions, Newlib refers to them unconditionally and they are,
104     * perhaps counterintuitively, stripped from the binary unless marked as
105     * KEEP.
106     */
107
108    .init : {
109        KEEP(*(.init))
110    } > x
111
112    .fini : {
113        KEEP(*(.fini))
114    } > x
115
116    .init_array : {
117        __init_array_start = .;
118        KEEP(*(.init_array*))
119        __init_array_end = .;
120    } > r
121
122    .fini_array : {
123        __fini_array_start = .;
124        KEEP(*(.fini_array))
125        __fini_array_end = .;
126    } > r
127
128    .rodata : {
129        *(.rodata .rodata.*)
130    } > r
131
132    .data : {
133        __data_load__ = LOADADDR(.data);
134        __data_start__ = ABSOLUTE(.);
135
136        *(.data .data.*)
137    } > w AT> r
138
139    .bss (NOLOAD) : {
140        __bss_start__ = ABSOLUTE(.);
141
142        *(.bss .bss.*)
143    } > w
144
145    .stackheap (NOLOAD) : {
146        __stackheap_start__ = ABSOLUTE(.);
147
148        . = ORIGIN(w) + LENGTH(w);
149
150        __stackheap_end__ = ABSOLUTE(.);
151    } > w
152
153    /*
154     * By default the linker places orphan sections after the section with the
155     * closest matching attributes. Calculating the end of a section based on
156     * the beginning of the next one that we know about means we can include BSS
157     * and DATA sections that we don't know about in these values.
158     */
159
160    __data_end__ = __bss_start__;
161    __bss_end__ = __stackheap_start__;
162
163    __stack = __stackheap_end__;
164}
165