1;/*
2; * Copyright (c) 2009-2022 Arm Limited
3; *
4; * Licensed under the Apache License, Version 2.0 (the "License");
5; * you may not use this file except in compliance with the License.
6; * You may obtain a copy of the License at
7; *
8; *     http://www.apache.org/licenses/LICENSE-2.0
9; *
10; * Unless required by applicable law or agreed to in writing, software
11; * distributed under the License is distributed on an "AS IS" BASIS,
12; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13; * See the License for the specific language governing permissions and
14; * limitations under the License.
15; *
16; *
17; * This file is derivative of CMSIS V5.00 gcc_arm.ld
18; */
19
20/* Linker script to configure memory regions. */
21/* This file will be run trough the pre-processor. */
22
23#include "region_defs.h"
24
25MEMORY
26{
27  FLASH    (rx)  : ORIGIN = S_CODE_START, LENGTH = S_CODE_SIZE
28  RAM      (rwx) : ORIGIN = S_DATA_START, LENGTH = S_DATA_SIZE
29  VENEERS  (rx)  : ORIGIN = CMSE_VENEER_REGION_START, LENGTH = CMSE_VENEER_REGION_SIZE
30
31#if defined(PSA_PROXY_SHARED_MEMORY_BASE)
32  PSA_PROXY_SHARED_MEMORY_RAM (rw) : ORIGIN = PSA_PROXY_SHARED_MEMORY_BASE, LENGTH = PSA_PROXY_SHARED_MEMORY_SIZE
33#endif
34
35}
36
37__heap_size__  = S_HEAP_SIZE;
38__msp_stack_size__ = S_MSP_STACK_SIZE;
39
40/* Library configurations */
41GROUP(libgcc.a libc.a libm.a libnosys.a libc_nano.a)
42
43ENTRY(Reset_Handler)
44
45SECTIONS
46{
47    .TFM_VECTORS : ALIGN(4)
48    {
49        __vectors_start__ = .;
50        KEEP(*(.vectors))
51        __vectors_end__ = .;
52        *startup*(.text*)
53        . = ALIGN(4);
54    } > FLASH
55
56    .copy.table : ALIGN(4)
57    {
58        __copy_table_start__ = .;
59        LONG (LOADADDR(.TFM_DATA))
60        LONG (ADDR(.TFM_DATA))
61        LONG (SIZEOF(.TFM_DATA) / 4)
62
63        LONG (LOADADDR(.TFM_PSA_ROT_LINKER_DATA))
64        LONG (ADDR(.TFM_PSA_ROT_LINKER_DATA))
65        LONG (SIZEOF(.TFM_PSA_ROT_LINKER_DATA) / 4)
66
67        LONG (LOADADDR(.TFM_APP_ROT_LINKER_DATA))
68        LONG (ADDR(.TFM_APP_ROT_LINKER_DATA))
69        LONG (SIZEOF(.TFM_APP_ROT_LINKER_DATA) / 4)
70        __copy_table_end__ = .;
71    } > FLASH
72
73    .zero.table : ALIGN(4)
74    {
75        __zero_table_start__ = .;
76        LONG (ADDR(.TFM_BSS))
77        LONG (SIZEOF(.TFM_BSS) / 4)
78        LONG (ADDR(.TFM_PSA_ROT_LINKER_BSS))
79        LONG (SIZEOF(.TFM_PSA_ROT_LINKER_BSS) / 4)
80
81        LONG (ADDR(.TFM_APP_ROT_LINKER_BSS))
82        LONG (SIZEOF(.TFM_APP_ROT_LINKER_BSS) / 4)
83#if defined(PSA_PROXY_SHARED_MEMORY_BASE)
84        LONG (PSA_PROXY_SHARED_MEMORY_BASE)
85        LONG (PSA_PROXY_SHARED_MEMORY_SIZE / 4)
86#endif
87#if defined(CONFIG_TFM_PARTITION_META)
88        LONG (ADDR(.TFM_SP_META_PTR))
89        LONG (SIZEOF(.TFM_SP_META_PTR) / 4)
90#endif
91        __zero_table_end__ = .;
92    } > FLASH
93
94    /**** Section for holding partition RO load data */
95    /*
96     * Sort the partition info by priority to guarantee the initing order.
97     * The first loaded partition will be inited at last in SFN model.
98     */
99    .TFM_SP_LOAD_LIST : ALIGN(4)
100    {
101       KEEP(*(.part_load_priority_lowest))
102       KEEP(*(.part_load_priority_low))
103       KEEP(*(.part_load_priority_normal))
104       KEEP(*(.part_load_priority_high))
105    } > FLASH
106    Image$$TFM_SP_LOAD_LIST$$RO$$Base = ADDR(.TFM_SP_LOAD_LIST);
107    Image$$TFM_SP_LOAD_LIST$$RO$$Limit = ADDR(.TFM_SP_LOAD_LIST) + SIZEOF(.TFM_SP_LOAD_LIST);
108    . = ALIGN(32);
109
110    /**** PSA RoT RO part (CODE + RODATA) start here */
111    Image$$TFM_PSA_CODE_START$$Base = .;
112
113    .TFM_PSA_ROT_LINKER : ALIGN(32)
114    {
115        *tfm_psa_rot_partition*:*(.text*)
116        *tfm_psa_rot_partition*:*(.rodata*)
117        *(TFM_*_PSA-ROT_ATTR_FN)
118        . = ALIGN(32);
119    } > FLASH
120
121    Image$$TFM_PSA_ROT_LINKER$$RO$$Base = ADDR(.TFM_PSA_ROT_LINKER);
122    Image$$TFM_PSA_ROT_LINKER$$RO$$Limit = ADDR(.TFM_PSA_ROT_LINKER) + SIZEOF(.TFM_PSA_ROT_LINKER);
123    Image$$TFM_PSA_ROT_LINKER$$Base = ADDR(.TFM_PSA_ROT_LINKER);
124    Image$$TFM_PSA_ROT_LINKER$$Limit = ADDR(.TFM_PSA_ROT_LINKER) + SIZEOF(.TFM_PSA_ROT_LINKER);
125
126    /**** PSA RoT RO part (CODE + RODATA) end here */
127    Image$$TFM_PSA_CODE_END$$Base = .;
128
129
130#if TFM_LVL != 1
131    .ARM.extab :
132    {
133        *(.ARM.extab* .gnu.linkonce.armextab.*)
134    } > FLASH
135
136    __exidx_start = .;
137    .ARM.exidx :
138    {
139        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
140    } > FLASH
141    __exidx_end = .;
142
143#endif /* TFM_LVL != 1 */
144
145    .ER_TFM_CODE : ALIGN(4)
146    {
147        *libplatform_s*:*(.text*)
148        *libtfm_spm*:*(.text*)
149
150        *libplatform_s*:*(.rodata*)
151        *libtfm_spm*:*(.rodata*)
152    } > FLASH
153    /* unpriv data is placed 1st */
154    .dummy_empty : ALIGN(32)
155    {
156        . += 0x0;
157    } > RAM
158/**** Unpriv  DATA start here */
159    Image$$TFM_APP_RW_STACK_START$$Base = ADDR(.dummy_empty);
160#if defined(CONFIG_TFM_PARTITION_META)
161    .TFM_SP_META_PTR : ALIGN(32)
162    {
163        *(.bss.SP_META_PTR_SPRTL_INST)
164        . = ALIGN(32);
165    } > RAM
166    Image$$TFM_SP_META_PTR$$ZI$$Base = ADDR(.TFM_SP_META_PTR);
167    Image$$TFM_SP_META_PTR$$ZI$$Limit = ADDR(.TFM_SP_META_PTR) + SIZEOF(.TFM_SP_META_PTR);
168#endif
169
170    .TFM_APP_ROT_LINKER_DATA : ALIGN(32)
171    {
172        *tfm_app_rot_partition*:*(.data*)
173        *(TFM_*_APP-ROT_ATTR_RW)
174        . = ALIGN(32);
175    } > RAM AT> FLASH
176    Image$$TFM_APP_ROT_LINKER_DATA$$RW$$Base = ADDR(.TFM_APP_ROT_LINKER_DATA);
177    Image$$TFM_APP_ROT_LINKER_DATA$$RW$$Limit = ADDR(.TFM_APP_ROT_LINKER_DATA) + SIZEOF(.TFM_APP_ROT_LINKER_DATA);
178
179    .TFM_APP_ROT_LINKER_BSS : ALIGN(32)
180    {
181        start_of_TFM_APP_ROT_LINKER = .;
182        *tfm_app_rot_partition*:*(.bss*)
183        *tfm_app_rot_partition*:*(COMMON)
184        *(TFM_*_APP-ROT_ATTR_ZI)
185        . += (. - start_of_TFM_APP_ROT_LINKER) ? 0 : 4;
186        . = ALIGN(GTZC_RAM_ALIGN);
187    } > RAM AT> RAM
188
189    ASSERT(GTZC_RAM_ALIGN % 4 == 0, "GTZC_RAM_ALIGN must be divisible by 4")
190
191    Image$$TFM_APP_ROT_LINKER_DATA$$ZI$$Base = ADDR(.TFM_APP_ROT_LINKER_BSS);
192    Image$$TFM_APP_ROT_LINKER_DATA$$ZI$$Limit = ADDR(.TFM_APP_ROT_LINKER_BSS) + SIZEOF(.TFM_APP_ROT_LINKER_BSS);
193
194
195    /**** APPLICATION RoT DATA end here */
196    Image$$TFM_APP_RW_STACK_END$$Base = .;
197
198    /* shared_data and msp_stack are overlapping on purpose when
199     * msp_stack is extended until the beginning of RAM, when shared_date
200     * was read out by partitions
201     */
202    .tfm_bl2_shared_data : ALIGN(32)
203    {
204        . += BOOT_TFM_SHARED_DATA_SIZE;
205    } > RAM
206
207    .msp_stack : ALIGN(32)
208    {
209        . += __msp_stack_size__ - 0x8;
210    } > RAM
211    Image$$ARM_LIB_STACK$$ZI$$Base = ADDR(.msp_stack);
212    Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack);
213
214    .msp_stack_seal_res :
215    {
216        . += 0x8;
217    } > RAM
218    __StackSeal = ADDR(.msp_stack_seal_res);
219
220#if (TFM_LVL == 1)
221    .heap : ALIGN(8)
222    {
223        __end__ = .;
224        PROVIDE(end = .);
225        __HeapBase = .;
226        . += __heap_size__;
227        __HeapLimit = .;
228        __heap_limit = .; /* Add for _sbrk */
229    } > RAM
230#endif /* TFM_LVL == 1 */
231
232#if TFM_LVL != 1
233#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
234    .TFM_SP_SECURE_TEST_PARTITION_LINKER_DATA : ALIGN(32)
235    {
236        *libc_nano*:*(.data*)
237        . = ALIGN(32);
238    } > RAM AT> FLASH
239
240    .TFM_SP_SECURE_TEST_PARTITION_LINKER_BSS : ALIGN(32)
241    {
242        /* FixMe:
243         * Test framework use printf to print out test result. Implementation of
244         * printf in GCC libc use static data and heap as well. To be able to
245         * execute test suites with TFM_LVL=3 this workaround is needed to
246         * allocate libc static data and heap within the data section of secure
247         * test partition. This can be removed if test service will be executed
248         * in privileged mode.
249         */
250        *libc_nano*:*(.bss*)
251        *libc_nano*:*(COMMON)
252
253        __end__ = .;
254        PROVIDE(end = .);
255        __HeapBase = .;
256        . += __heap_size__;
257        __HeapLimit = .;
258        __heap_limit = .; /* Add for _sbrk */
259
260        . = ALIGN(32);
261    } > RAM AT> RAM
262#else /* TFM_PARTITION_TEST_SECURE_SERVICES */
263    .heap : ALIGN(8)
264    {
265        __end__ = .;
266        PROVIDE(end = .);
267        __HeapBase = .;
268        . += __heap_size__;
269        __HeapLimit = .;
270        __heap_limit = .; /* Add for _sbrk */
271    } > RAM AT> RAM
272#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
273#endif /* TFM_LVL != 1 */
274
275    /**** PSA RoT DATA start here */
276
277    Image$$TFM_PSA_RW_STACK_START$$Base = .;
278
279    .TFM_PSA_ROT_LINKER_DATA : ALIGN(32)
280    {
281        *tfm_psa_rot_partition*:*(.data*)
282        *(TFM_*_PSA-ROT_ATTR_RW)
283        . = ALIGN(32);
284    } > RAM AT> FLASH
285    Image$$TFM_PSA_ROT_LINKER_DATA$$RW$$Base = ADDR(.TFM_PSA_ROT_LINKER_DATA);
286    Image$$TFM_PSA_ROT_LINKER_DATA$$RW$$Limit = ADDR(.TFM_PSA_ROT_LINKER_DATA) + SIZEOF(.TFM_PSA_ROT_LINKER_DATA);
287
288    .TFM_PSA_ROT_LINKER_BSS : ALIGN(32)
289    {
290        start_of_TFM_PSA_ROT_LINKER = .;
291        *tfm_psa_rot_partition*:*(.bss*)
292        *tfm_psa_rot_partition*:*(COMMON)
293        *(TFM_*_PSA-ROT_ATTR_ZI)
294        . += (. - start_of_TFM_PSA_ROT_LINKER) ? 0 : 4;
295        . = ALIGN(32);
296    } > RAM AT> RAM
297    Image$$TFM_PSA_ROT_LINKER_DATA$$ZI$$Base = ADDR(.TFM_PSA_ROT_LINKER_BSS);
298    Image$$TFM_PSA_ROT_LINKER_DATA$$ZI$$Limit = ADDR(.TFM_PSA_ROT_LINKER_BSS) + SIZEOF(.TFM_PSA_ROT_LINKER_BSS);
299
300    .TFM_DATA : ALIGN(4)
301    {
302        *(.data*)
303
304        . = ALIGN(4);
305        /* preinit data */
306        PROVIDE_HIDDEN (__preinit_array_start = .);
307        KEEP(*(.preinit_array))
308        PROVIDE_HIDDEN (__preinit_array_end = .);
309
310        . = ALIGN(4);
311        /* init data */
312        PROVIDE_HIDDEN (__init_array_start = .);
313        KEEP(*(SORT(.init_array.*)))
314        KEEP(*(.init_array))
315        PROVIDE_HIDDEN (__init_array_end = .);
316
317        . = ALIGN(4);
318        /* finit data */
319        PROVIDE_HIDDEN (__fini_array_start = .);
320        KEEP(*(SORT(.fini_array.*)))
321        KEEP(*(.fini_array))
322        PROVIDE_HIDDEN (__fini_array_end = .);
323
324        KEEP(*(.jcr*))
325        . = ALIGN(4);
326
327    } > RAM AT> FLASH
328    Image$$ER_TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
329    Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
330
331    /**** PSA RoT DATA end here */
332    Image$$TFM_PSA_RW_STACK_END$$Base = .;
333
334    .TFM_UNPRIV_CODE : ALIGN(GTZC_FLASH_ALIGN)
335    {
336        *(SFN)
337        *(.text*)
338
339        KEEP(*(.init))
340        KEEP(*(.fini))
341
342        /* .ctors */
343        *crtbegin.o(.ctors)
344        *crtbegin?.o(.ctors)
345        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
346        *(SORT(.ctors.*))
347        *(.ctors)
348
349        /* .dtors */
350         *crtbegin.o(.dtors)
351         *crtbegin?.o(.dtors)
352         *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
353         *(SORT(.dtors.*))
354         *(.dtors)
355
356        *(.rodata*)
357
358        KEEP(*(.eh_frame*))
359        . = ALIGN(32);
360    } > FLASH
361    Image$$TFM_UNPRIV_CODE$$RO$$Base = ADDR(.TFM_UNPRIV_CODE);
362    Image$$TFM_UNPRIV_CODE$$RO$$Limit = ADDR(.TFM_UNPRIV_CODE) + SIZEOF(.TFM_UNPRIV_CODE);
363
364    /**** APPLICATION RoT RO part (CODE + RODATA) start here */
365    Image$$TFM_APP_CODE_START$$Base = .;
366
367    .TFM_APP_ROT_LINKER : ALIGN(32)
368    {
369        *tfm_app_rot_partition*:*(.text*)
370        *tfm_app_rot_partition*:*(.rodata*)
371        *(TFM_*_APP-ROT_ATTR_FN)
372        . = ALIGN(32);
373    } > FLASH
374
375    /**** APPLICATION RoT RO part (CODE + RODATA) end here */
376    Image$$TFM_APP_CODE_END$$Base = .;
377
378    Image$$TFM_APP_ROT_LINKER$$RO$$Base = ADDR(.TFM_APP_ROT_LINKER);
379    Image$$TFM_APP_ROT_LINKER$$RO$$Limit = ADDR(.TFM_APP_ROT_LINKER) + SIZEOF(.TFM_APP_ROT_LINKER);
380    Image$$TFM_APP_ROT_LINKER$$Base = ADDR(.TFM_APP_ROT_LINKER);
381    Image$$TFM_APP_ROT_LINKER$$Limit = ADDR(.TFM_APP_ROT_LINKER) + SIZEOF(.TFM_APP_ROT_LINKER);
382
383    .TFM_BSS : ALIGN(4)
384    {
385        __bss_start__ = .;
386
387        /* The runtime partition placed order is same as load partition */
388        __partition_runtime_start__ = .;
389        KEEP(*(.bss.part_runtime_priority_lowest))
390        KEEP(*(.bss.part_runtime_priority_low))
391        KEEP(*(.bss.part_runtime_priority_normal))
392        KEEP(*(.bss.part_runtime_priority_high))
393        __partition_runtime_end__ = .;
394        . = ALIGN(4);
395
396        /* The runtime service placed order is same as load partition */
397        __service_runtime_start__ = .;
398        KEEP(*(.bss.serv_runtime_priority_lowest))
399        KEEP(*(.bss.serv_runtime_priority_low))
400        KEEP(*(.bss.serv_runtime_priority_normal))
401        KEEP(*(.bss.serv_runtime_priority_high))
402        __service_runtime_end__ = .;
403        *(.bss*)
404        *(COMMON)
405        . = ALIGN(4);
406        __bss_end__ = .;
407    } > RAM AT> RAM
408    Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
409    Image$$ER_TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
410    Image$$ER_PART_RT_POOL$$ZI$$Base = __partition_runtime_start__;
411    Image$$ER_PART_RT_POOL$$ZI$$Limit = __partition_runtime_end__;
412    Image$$ER_SERV_RT_POOL$$ZI$$Base = __service_runtime_start__;
413    Image$$ER_SERV_RT_POOL$$ZI$$Limit = __service_runtime_end__;
414
415    Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA);
416    Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS);
417
418#if defined(PSA_PROXY_SHARED_MEMORY_BASE)
419    /* If a variable defined with __attribute__((section())) keyword the
420     * variable is treated like an initialized variable. To not waste memory
421     * NOLOAD attribute used here. The whole section is zero initialized by
422     * adding section information to .zero.table */
423    .PSA_PROXY_SHARED_MEMORY (NOLOAD) : ALIGN(4)
424    {
425        KEEP(*(PSA_PROXY_SHARED_MEMORY_SECTION))
426        . = ALIGN(4);
427    } > PSA_PROXY_SHARED_MEMORY_RAM
428#endif
429
430    /*
431     * Place the CMSE Veneers (containing the SG instruction) after the code, in a
432     * separate 32 bytes aligned region so that the SAU can programmed to just set
433     * this region as Non-Secure Callable.
434     */
435    .gnu.sgstubs : ALIGN(32)
436    {
437        *(.gnu.sgstubs*)
438        . = ALIGN(32);
439    } > VENEERS AT> VENEERS
440    Load$$LR$$LR_VENEER$$Base = ADDR(.gnu.sgstubs);
441    Load$$LR$$LR_VENEER$$Limit = ADDR(.gnu.sgstubs) + SIZEOF(.gnu.sgstubs);
442
443    Load$$LR$$LR_NS_PARTITION$$Base = NS_PARTITION_START;
444
445#ifdef BL2
446    Load$$LR$$LR_SECONDARY_PARTITION$$Base = SECONDARY_PARTITION_START;
447#endif /* BL2 */
448
449    PROVIDE(__stack = Image$$ARM_LIB_STACK$$ZI$$Limit);
450}
451