Secure 启动文件
platform/ext/target/arm/mps2/an521/cmsis_core/startup_an521.c 是 tfm_s 启动文件。可以看到 bl2 和 tfm_s 是同一个启动文件。虽然源码相同,但是 bl2 和 tfm_s 链接的时候,会根据不同的配置,生成不同的 elf 文件。
platform/ext/target/arm/mps2/an521/cmsis_core/startup_an521.c 中启动文件如下
c
extern const VECTOR_TABLE_Type __VECTOR_TABLE[];
const VECTOR_TABLE_Type __VECTOR_TABLE[] __VECTOR_TABLE_ATTRIBUTE = {
(VECTOR_TABLE_Type)(&__INITIAL_SP), /* Initial Stack Pointer */
Reset_Handler, /* Reset Handler */
NMI_Handler, /* -14: NMI Handler */
HardFault_Handler, /* -13: Hard Fault Handler */
MemManage_Handler, /* -12: MPU Fault Handler */
BusFault_Handler, /* -11: Bus Fault Handler */
UsageFault_Handler, /* -10: Usage Fault Handler */
SecureFault_Handler, /* -9: Secure Fault Handler */
0, /* -8: Reserved */
0, /* -7: Reserved */
0, /* -6: Reserved */
SVC_Handler, /* -5: SVCall Handler */
DebugMon_Handler, /* -4: Debug Monitor Handler */
0, /* -3: Reserved */
PendSV_Handler, /* -2: PendSV Handler */
SysTick_Handler, /* -1: SysTick Handler */
NONSEC_WATCHDOG_RESET_Handler, /* 0: Non-Secure Watchdog Reset Request Handler */
NONSEC_WATCHDOG_Handler, /* 1: Non-Secure Watchdog Interrupt Handler */
S32K_TIMER_Handler, /* 2: S32K Timer Handler */
TFM_TIMER0_IRQ_Handler, /* 3: TIMER 0 Handler */
TIMER1_Handler, /* 4: TIMER 1 Handler */
DUALTIMER_Handler, /* 5: Dual Timer Handler */
MHU0_Handler, /* 6: Message Handling Unit 0 */
MHU1_Handler, /* 7: Message Handling Unit 1 */
0, /* 8: Reserved */
MPC_Handler, /* 9: MPC Combined (Secure) Handler */
PPC_Handler, /* 10: PPC Combined (Secure) Handler */
MSC_Handler, /* 11: MSC Combined (Secure) Handler */
BRIDGE_ERROR_Handler, /* 12: Bridge Error (Secure) Handler */
INVALID_INSTR_CACHE_Handler, /* 13: CPU Instruction Cache Invalidation Handler */
0, /* 14: Reserved */
SYS_PPU_Handler, /* 15: SYS PPU Handler */
CPU0_PPU_Handler, /* 16: CPU0 PPU Handler */
CPU1_PPU_Handler, /* 17: CPU1 PPU Handler */
CPU0_DBG_PPU_Handler, /* 18: CPU0 DBG PPU_Handler */
CPU1_DBG_PPU_Handler, /* 19: CPU1 DBG PPU_Handler */
CRYPT_PPU_Handler, /* 20: CRYPT PPU Handler */
0, /* 21: Reserved */
RAM0_PPU_Handler, /* 22: RAM0 PPU Handler */
RAM1_PPU_Handler, /* 23: RAM1 PPU Handler */
RAM2_PPU_Handler, /* 24: RAM2 PPU Handler */
RAM3_PPU_Handler, /* 25: RAM3 PPU Handler */
DBG_PPU_Handler, /* 26: DBG PPU Handler */
0, /* 27: Reserved */
CPU0_CTI_Handler, /* 28: CPU0 CTI Handler */
CPU1_CTI_Handler, /* 29: CPU1 CTI Handler */
0, /* 30: Reserved */
0, /* 31: Reserved */
/* External interrupts */
UARTRX0_Handler, /* 32: UART 0 RX Handler */
UARTTX0_Handler, /* 33: UART 0 TX Handler */
UARTRX1_Handler, /* 34: UART 1 RX Handler */
UARTTX1_Handler, /* 35: UART 1 TX Handler */
UARTRX2_Handler, /* 36: UART 2 RX Handler */
UARTTX2_Handler, /* 37: UART 2 TX Handler */
UARTRX3_Handler, /* 38: UART 3 RX Handler */
UARTTX3_Handler, /* 39: UART 3 TX Handler */
UARTRX4_Handler, /* 40: UART 4 RX Handler */
UARTTX4_Handler, /* 41: UART 4 TX Handler */
UART0_Combined_Handler, /* 42: UART 0 Combined Handler */
UART1_Combined_Handler, /* 43: UART 1 Combined Handler */
UART2_Combined_Handler, /* 44: UART 2 Combined Handler */
UART3_Combined_Handler, /* 45: UART 3 Combined Handler */
UART4_Combined_Handler, /* 46: UART 4 Combined Handler */
UARTOVF_Handler, /* 47: UART 0, 1, 2, 3, 4 & 5 Overflow Handler */
ETHERNET_Handler, /* 48: Ethernet Handler */
I2S_Handler, /* 49: Audio I2S Handler */
TOUCH_SCREEN_Handler, /* 50: Touch Screen Handler */
SPI0_Handler, /* 51: SPI 0 Handler */
SPI1_Handler, /* 52: SPI 1 Handler */
SPI2_Handler, /* 53: SPI 2 Handler */
SPI3_Handler, /* 54: SPI 3 Handler */
SPI4_Handler, /* 55: SPI 4 Handler */
DMA0_ERROR_Handler, /* 56: DMA 0 Error Handler */
DMA0_TC_Handler, /* 57: DMA 0 Terminal Count Handler */
DMA0_Handler, /* 58: DMA 0 Combined Handler */
DMA1_ERROR_Handler, /* 59: DMA 1 Error Handler */
DMA1_TC_Handler, /* 60: DMA 1 Terminal Count Handler */
DMA1_Handler, /* 61: DMA 1 Combined Handler */
DMA2_ERROR_Handler, /* 62: DMA 2 Error Handler */
DMA2_TC_Handler, /* 63: DMA 2 Terminal Count Handler */
DMA2_Handler, /* 64: DMA 2 Combined Handler */
DMA3_ERROR_Handler, /* 65: DMA 3 Error Handler */
DMA3_TC_Handler, /* 66: DMA 3 Terminal Count Handler */
DMA3_Handler, /* 67: DMA 3 Combined Handler */
GPIO0_Combined_Handler, /* 68: GPIO 0 Combined Handler */
GPIO1_Combined_Handler, /* 69: GPIO 1 Combined Handler */
GPIO2_Combined_Handler, /* 70: GPIO 2 Combined Handler */
GPIO3_Combined_Handler, /* 71: GPIO 3 Combined Handler */
GPIO0_0_Handler, /* 72: GPIO0 Pin 0 Handler */
GPIO0_1_Handler, /* 73: GPIO0 Pin 1 Handler */
GPIO0_2_Handler, /* 74: GPIO0 Pin 2 Handler */
GPIO0_3_Handler, /* 75: GPIO0 Pin 3 Handler */
GPIO0_4_Handler, /* 76: GPIO0 Pin 4 Handler */
GPIO0_5_Handler, /* 77: GPIO0 Pin 5 Handler */
GPIO0_6_Handler, /* 78: GPIO0 Pin 6 Handler */
GPIO0_7_Handler, /* 79: GPIO0 Pin 7 Handler */
GPIO0_8_Handler, /* 80: GPIO0 Pin 8 Handler */
GPIO0_9_Handler, /* 81: GPIO0 Pin 9 Handler */
GPIO0_10_Handler, /* 82: GPIO0 Pin 10 Handler */
GPIO0_11_Handler, /* 83: GPIO0 Pin 11 Handler */
GPIO0_12_Handler, /* 84: GPIO0 Pin 12 Handler */
GPIO0_13_Handler, /* 85: GPIO0 Pin 13 Handler */
GPIO0_14_Handler, /* 86: GPIO0 Pin 14 Handler */
GPIO0_15_Handler, /* 87: GPIO0 Pin 15 Handler */
GPIO1_0_Handler, /* 88: GPIO1 Pin 0 Handler */
GPIO1_1_Handler, /* 89: GPIO1 Pin 1 Handler */
GPIO1_2_Handler, /* 90: GPIO1 Pin 2 Handler */
GPIO1_3_Handler, /* 91: GPIO1 Pin 3 Handler */
GPIO1_4_Handler, /* 92: GPIO1 Pin 4 Handler */
GPIO1_5_Handler, /* 93: GPIO1 Pin 5 Handler */
GPIO1_6_Handler, /* 94: GPIO1 Pin 6 Handler */
GPIO1_7_Handler, /* 95: GPIO1 Pin 7 Handler */
};
build_an521_ninja/lib/ext/cmsis-src/CMSIS/Core/Include/m-profile/cmsis_gcc_m.h .vectors 段定义如下
c
#ifndef __VECTOR_TABLE_ATTRIBUTE
#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section(".vectors")))
#endif
VECTOR_TABLE_Type 定义在 platform/ext/target/arm/mps2/an521/cmsis_core/system_core_init.h 中:
c
typedef void(*VECTOR_TABLE_Type)(void);
所以
c
extern const VECTOR_TABLE_Type __VECTOR_TABLE[];
const VECTOR_TABLE_Type __VECTOR_TABLE[] __VECTOR_TABLE_ATTRIBUTE = {
(VECTOR_TABLE_Type)(&__INITIAL_SP), /* Initial Stack Pointer */
Reset_Handler, /* Reset Handler */
__VECTOR_TABLE数组定义在.vectors段,数组元素类型是VECTOR_TABLE_Type,数组放在.vectors段中。- 数组的第一个元素是初始栈指针
- 数组的第二个元素是
Reset_Handler - 数组的第三个元素是
NMI_Handler - 以此类推,数组存放的元素是中断向量表。
硬件复位之后,第一个元素会被写入 MSP,这部分由硬件完成,然后开始执行 Reset_Handler。
设置 MSP,PSP
c
.msp_stack ALIGN(TFM_LINKER_MSP_STACK_ALIGNMENT) (NOLOAD) :
{
. += __msp_stack_size__ - STACKSEAL_SIZE;
} > RAM
Image$$ARM_LIB_STACK$$ZI$$Base = ADDR(.msp_stack);
Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack);
PROVIDE(__stack = Image$$ARM_LIB_STACK$$ZI$$Limit);
c
#define __INITIAL_SP Image$$ARM_LIB_STACK$$ZI$$Limit
#define __STACK_LIMIT Image$$ARM_LIB_STACK$$ZI$$Base
-
定义一个 msp_stack 段
-
Image$$ARM_LIB_STACK$$ZI$$Base起始地址 -
Image$$ARM_LIB_STACK$$ZI$$Limit结束地址 -
__INITIAL_SP指向栈顶。Cortex-M33 使用满递减栈,硬件将这个值写入 MSP。 -
__STACK_LIMIT指向栈底,用于设置 MSPLIM 和 PSPLIM。
GCC 构建通过 platform/include/cmsis_override.h 将 CMSIS 默认的 __INITIAL_SP 和 __STACK_LIMIT 重定义为上面的链接脚本符号。
platform/ext/target/arm/mps2/an521/cmsis_core/startup_an521.c 中,软件设置 PSP 和两个栈限制寄存器:
c
__set_PSP((uint32_t)(&__INITIAL_SP));
__set_MSPLIM((uint32_t)(&__STACK_LIMIT));
__set_PSPLIM((uint32_t)(&__STACK_LIMIT));
Reset_Handler
Reset_Handler 向量前面的第一个 word 是初始 SP,硬件会自动将它写入 MSP。当前 TrustZone 构建下,Reset_Handler 的软件部分如下:
c
void Reset_Handler(void)
{
__disable_irq();
__set_PSP((uint32_t)(&__INITIAL_SP));
__set_MSPLIM((uint32_t)(&__STACK_LIMIT));
__set_PSPLIM((uint32_t)(&__STACK_LIMIT));
__TZ_set_STACKSEAL_S((uint32_t *)(&__STACK_SEAL));
SystemInit(); /* CMSIS System Initialization */
__PROGRAM_START(); /* Enter PreMain (C library entry point) */
}
platform/ext/target/arm/mps2/an521/cmsis_core/system_core_init.c 中 SystemInit 简化后的函数如下
c
void SystemInit(void)
{
SCB->VTOR = (uint32_t) &(__VECTOR_TABLE[0]);
SystemCoreClock = SYSTEM_CLOCK;
PeripheralClock = PERIPHERAL_CLOCK;
}
在 GCC 构建中,__PROGRAM_START 在 build_an521_ninja/lib/ext/cmsis-src/CMSIS/Core/Include/m-profile/cmsis_gcc_m.h 中展开为 __cmsis_start。
c
__STATIC_FORCEINLINE __NO_RETURN void __cmsis_start(void)
{
extern void _start(void) __NO_RETURN;
typedef struct __copy_table {
uint32_t const* src;
uint32_t* dest;
uint32_t wlen;
} __copy_table_t;
typedef struct __zero_table {
uint32_t* dest;
uint32_t wlen;
} __zero_table_t;
extern const __copy_table_t __copy_table_start__;
extern const __copy_table_t __copy_table_end__;
extern const __zero_table_t __zero_table_start__;
extern const __zero_table_t __zero_table_end__;
for (__copy_table_t const* pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) {
for(uint32_t i=0u; i<pTable->wlen; ++i) {
pTable->dest[i] = pTable->src[i];
}
}
for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) {
for(uint32_t i=0u; i<pTable->wlen; ++i) {
pTable->dest[i] = 0u;
}
}
_start();
}
#define __PROGRAM_START __cmsis_start
__cmsis_start 根据链接脚本生成的 copy table 和 zero table,完成 .data 初始化和 .bss 清零,然后调用 _start。
因此,.data 的初始值从 Flash 复制到 RAM,.bss 在 RAM 中清零。
_start 函数实现在 secure_fw/partitions/lib/runtime/crt_start.c。
当前 GCC 构建不定义 __clang_major__,因此执行该文件中的 #else 分支。_start 通过符号调用 main,调用结束后停在死循环中。
c
#else /* defined(__clang_major__) */
void _start(void)
{
main(0, NULL);
while (1)
;
}
#endif /* defined(__clang_major__) */
crt_start.c 中的声明是 main(int argc, char **argv),而 secure_fw/spm/core/main.c 中的定义是 main(void)。它们位于不同的编译单元,链接器只按符号名解析;TF-M 的 main 不读取参数,因此这里不会产生链接错误。
main 函数
secure_fw/spm/core/main.c 是 main 函数的实现文件。
c
int main(void)
{
#ifdef CONFIG_TFM_ENABLE_PROFILING
PROFILING_INIT();
#endif
FIH_DECLARE(fih_rc, FIH_FAILURE);
TFM_COVERITY_DEVIATE_LINE(MISRA_C_2023_Rule_2_2, "Parameters can be changed by user and this code will make effect")
tfm_arch_config_branch_protection();
/* set Main Stack Pointer limit */
tfm_arch_set_msplim(SPM_BOOT_STACK_TOP);
fih_delay_init();
FIH_CALL(tfm_core_init, fih_rc);
if (FIH_NOT_EQ(fih_rc, SPM_SUCCESS)) {
tfm_core_panic();
}
/* All isolation should have been set up at this point */
FIH_LABEL_CRITICAL_POINT();
/*
* Prioritise secure exceptions to avoid NS being able to preempt
* secure SVC or SecureFault. Do it before PSA API initialization.
*/
tfm_arch_set_secure_exception_priorities();
#ifdef TFM_FIH_PROFILE_ON
/* Check secure exception priority */
FIH_CALL(tfm_arch_verify_secure_exception_priorities, fih_rc);
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
tfm_core_panic();
}
#endif
/* Further SPM initialization. */
BACKEND_SPM_INIT();
return 0;
}
main() 完成 SPM、隔离边界、OTP/provisioning 和异常优先级等初始化后返回,_start 随后进入死循环。
附录
链接脚本全文
链接脚本模板是 platform/ext/common/gcc/tfm_isolation_s.ld.template,CMake 配置后生成的文件是 build_an521_ninja/generated/platform/ext/common/gcc/tfm_isolation_s.ld。当前 tfm_s.axf 的链接命令使用生成后的 tfm_isolation_s.ld。
c
;/*
; * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
; * Copyright (c) 2022-2024 Cypress Semiconductor Corporation (an Infineon company)
; * or an affiliate of Cypress Semiconductor Corporation. All rights reserved.
; *
; * Licensed under the Apache License, Version 2.0 (the "License");
; * you may not use this file except in compliance with the License.
; * You may obtain a copy of the License at
; *
; * http://www.apache.org/licenses/LICENSE-2.0
; *
; * Unless required by applicable law or agreed to in writing, software
; * distributed under the License is distributed on an "AS IS" BASIS,
; * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; * See the License for the specific language governing permissions and
; * limitations under the License.
; *
; *
; * This file is derivative of CMSIS V5.00 gcc_arm.ld
; */
/*********** WARNING: This is an auto-generated file. Do not edit! ***********/
/* Linker script to configure memory regions. */
/* This file will be run through the pre-processor. */
#include "region_defs.h"
/* Include file with definitions for section alignments.
* Note: it should be included after region_defs.h to let platform define
* default values if needed. */
#include "tfm_s_linker_alignments.h"
#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) || \
defined(__ARM_ARCH_8_1M_MAIN__)
#define STACKSEAL_SIZE 0x8
#else
#define STACKSEAL_SIZE 0x0
#endif
/*
* Program Header (PHDRS) definitions
*
* These define how different segments of the final image are mapped into
* program headers for the ELF output. Each PHDR entry corresponds to a loadable
* memory segment with specific access permissions (Read, Write, Execute), which is
* defined by FLAGS(n):
* - 0x1 - Executable
* - 0x2 - Writable
* - 0x4 - Readable
*
* - flash: Loadable segment for executable code and read-only data (FLAGS(5) → R X)
* - tfm_data: TFM read/write data, (FLAGS(6) → R W)
* - phdr_<partition>: Dynamically generated loadable segments for each runtime partition
* with read/write permissions (FLAGS(6) → R W)
* - itcm: ITCM segment for executable code (FLAGS(5) → R X)
* - coderam: Executable segment placed in SRAM (FLAGS(5) → R X)
*
*/
PHDRS
{
flash PT_LOAD FLAGS(5); /* R X */
tfm_data PT_LOAD FLAGS(6); /* R W */
phdr_TFM_SP_PS PT_LOAD FLAGS(6); /* R W */
phdr_TFM_SP_ITS PT_LOAD FLAGS(6); /* R W */
phdr_TFM_SP_CRYPTO PT_LOAD FLAGS(6); /* R W */
phdr_TFM_SP_PLATFORM PT_LOAD FLAGS(6); /* R W */
#ifdef S_RUNTIME_ITCM_START
itcm PT_LOAD FLAGS(5); /* R X */
#endif
coderam PT_LOAD FLAGS(5); /* R X */
}
MEMORY
{
FLASH (rx) : ORIGIN = S_CODE_START, LENGTH = S_CODE_SIZE
RAM (rw) : ORIGIN = S_DATA_START, LENGTH = S_DATA_SIZE
#ifdef S_RAM_CODE_START
CODE_RAM (rwx) : ORIGIN = S_RAM_CODE_START, LENGTH = S_RAM_CODE_SIZE
#endif
#ifdef S_RUNTIME_ITCM_START
ITCM (rx) : ORIGIN = S_RUNTIME_ITCM_START, LENGTH = S_RUNTIME_ITCM_SIZE
#define ITCM_FILES *tfm_spm*
#else
#define ITCM_FILES
#endif
#ifdef S_RUNTIME_DTCM_START
DTCM (rw) : ORIGIN = S_RUNTIME_DTCM_START, LENGTH = S_RUNTIME_DTCM_SIZE
#endif
}
/* For Cortex-M0+ VTOR: 256-byte vector table is at the offset 0x00 of the image.
* To keep that table in one block, the image base must be a multiple of 0x100.
* For reference: https://developer.arm.com/documentation/ddi0419/latest/
*/
#if defined(__ARM_ARCH_6M__)
CHECK_ALIGNMENT_256(S_CODE_START)
#endif
#ifndef TFM_LINKER_VENEERS_START
#define TFM_LINKER_VENEERS_START ALIGN(TFM_LINKER_VENEERS_ALIGNMENT)
#endif
#ifndef TFM_LINKER_VENEERS_END
#define TFM_LINKER_VENEERS_END ALIGN(TFM_LINKER_VENEERS_ALIGNMENT)
#endif
#define VENEERS() \
/* \
* Place the CMSE Veneers (containing the SG instruction) after the code, in \
* a separate at least 32 bytes aligned region so that the SAU can \
* programmed to just set this region as Non-Secure Callable. \
*/ \
.gnu.sgstubs TFM_LINKER_VENEERS_START : \
{ \
*(.gnu.sgstubs*) \
} > FLASH :flash \
/* GCC always places veneers at the end of .gnu.sgstubs section, so the only \
* way to align the end of .gnu.sgstubs section is to align start of the \
* next section */ \
.sgstubs_end : TFM_LINKER_VENEERS_END \
{ \
} > FLASH :flash
__msp_stack_size__ = S_MSP_STACK_SIZE;
ENTRY(Reset_Handler)
SECTIONS
{
/* Position tag: Start of code + RO-data */
Image$$PT_RO_START$$Base = ADDR(.TFM_VECTORS);
.TFM_VECTORS : ALIGN(TFM_LINKER_TFM_VECTORS_ALIGNMENT)
{
__vectors_start__ = .;
KEEP(*(.vectors))
__vectors_end__ = .;
} > FLASH :flash
ASSERT(__vectors_start__ != __vectors_end__, ".vectors should not be empty")
#ifdef S_CODE_VECTOR_TABLE_SIZE
ASSERT(. <= ADDR(.TFM_VECTORS) + S_CODE_VECTOR_TABLE_SIZE, ".TFM_VECTORS section size overflow.")
. = ADDR(.TFM_VECTORS) + S_CODE_VECTOR_TABLE_SIZE;
#endif
/* Position tag: Start of unprivileged code (shared, not PXN) */
. = ALIGN(TFM_LINKER_PT_UNPRIV_CODE_ALIGNMENT);
Image$$PT_UNPRIV_CODE_START$$Base = .;
#if defined(CONFIG_TFM_USE_TRUSTZONE) && !defined(TFM_LINKER_VENEERS_LOCATION_END)
VENEERS()
#endif
.ER_UNPRIV_CODE . :
{
/* Shared library code */
*libgcc*:(SORT_BY_ALIGNMENT(.text*))
*libc_nano*:(SORT_BY_ALIGNMENT(.text*))
*libg_nano*:(SORT_BY_ALIGNMENT(.text*))
*libtfm_sprt*:(SORT_BY_ALIGNMENT(.text*))
*libqcbor*:(SORT_BY_ALIGNMENT(.text*))
*libtfm_t_cose_s*:(SORT_BY_ALIGNMENT(.text*))
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
KEEP(*(.eh_frame*))
} > FLASH :flash
/* Position tag: End of unprivileged code (shared, not PXN) */
. = ALIGN(TFM_LINKER_PT_UNPRIV_CODE_ALIGNMENT);
Image$$PT_UNPRIV_CODE_END$$Base = .;
/* Position tag: Start of Application RoT code (unprivileged, PXN) */
. = ALIGN(TFM_LINKER_PT_APP_ROT_CODE_ALIGNMENT);
Image$$PT_APP_ROT_CODE_START$$Base = .;
.ER_APP_ROT_CODE . :
{
*tfm_app_rot_partition*:(SORT_BY_ALIGNMENT(.text*))
*(TFM_*_APP-ROT_ATTR_FN)
*tfm_*partition_ps.*:(SORT_BY_ALIGNMENT(.text*))
*(TFM_SP_PS_APP-ROT_ATTR_FN)
} > FLASH :flash
/* Position tag: End of Application RoT code (unprivileged, PXN) */
. = ALIGN(TFM_LINKER_PT_APP_ROT_CODE_ALIGNMENT);
Image$$PT_APP_ROT_CODE_END$$Base = .;
/* Position tag: Start of PSA RoT code (privileged) */
. = ALIGN(TFM_LINKER_PT_PSA_ROT_CODE_ALIGNMENT);
Image$$PT_PSA_ROT_CODE_START$$Base = .;
.ER_PSA_ROT_CODE . :
{
*tfm_psa_rot_partition*:(SORT_BY_ALIGNMENT(.text*))
*(TFM_*_PSA-ROT_ATTR_FN)
*tfm_*partition_its.*:(SORT_BY_ALIGNMENT(.text*))
*(TFM_SP_ITS_PSA-ROT_ATTR_FN)
*tfm_*partition_crypto.*:(SORT_BY_ALIGNMENT(.text*))
*tfpsacrypto.*:(SORT_BY_ALIGNMENT(.text*))
*tfpsacrypto*acceleration.*:(SORT_BY_ALIGNMENT(.text*))
*(TFM_SP_CRYPTO_PSA-ROT_ATTR_FN)
*tfm_*partition_platform.*:(SORT_BY_ALIGNMENT(.text*))
*(TFM_SP_PLATFORM_PSA-ROT_ATTR_FN)
} > FLASH :flash
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH :flash
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH :flash
__exidx_end = .;
.ER_TFM_CODE ALIGN(4) (READONLY) :
{
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
/* .copy.table */
. = ALIGN(4);
__copy_table_start__ = .;
#ifdef RAM_VECTORS_SUPPORT
/* Copy interrupt vectors from flash to RAM */
LONG (__vectors_start__) /* From */
LONG (__ram_vectors_start__) /* To */
LONG ((__vectors_end__ - __vectors_start__) / 4) /* Size, aligment checked after the section */
#endif
LONG (LOADADDR(.TFM_DATA))
LONG (ADDR(.TFM_DATA))
LONG (SIZEOF(.TFM_DATA) / 4) /* Aligment checked after the section */
LONG (LOADADDR(.ER_TFM_SP_PS_DATA))
LONG (ADDR(.ER_TFM_SP_PS_DATA))
LONG (SIZEOF(.ER_TFM_SP_PS_DATA) / 4) /* Aligment checked after the section */
LONG (LOADADDR(.ER_TFM_SP_ITS_DATA))
LONG (ADDR(.ER_TFM_SP_ITS_DATA))
LONG (SIZEOF(.ER_TFM_SP_ITS_DATA) / 4) /* Aligment checked after the section */
LONG (LOADADDR(.ER_TFM_SP_CRYPTO_DATA))
LONG (ADDR(.ER_TFM_SP_CRYPTO_DATA))
LONG (SIZEOF(.ER_TFM_SP_CRYPTO_DATA) / 4) /* Aligment checked after the section */
LONG (LOADADDR(.ER_TFM_SP_PLATFORM_DATA))
LONG (ADDR(.ER_TFM_SP_PLATFORM_DATA))
LONG (SIZEOF(.ER_TFM_SP_PLATFORM_DATA) / 4) /* Aligment checked after the section */
#ifdef S_RUNTIME_ITCM_START
LONG (LOADADDR(.ER_ITCM_CODE))
LONG (ADDR(.ER_ITCM_CODE))
LONG (SIZEOF(.ER_ITCM_CODE) / 4)
#endif
#ifdef S_RAM_CODE_START
LONG (LOADADDR(.ER_CODE_SRAM))
LONG (ADDR(.ER_CODE_SRAM))
LONG (SIZEOF(.ER_CODE_SRAM) / 4) /* Aligment checked after the section */
#endif
__copy_table_end__ = .;
/* .zero.table */
. = ALIGN(4);
__zero_table_start__ = .;
LONG (ADDR(.TFM_BSS))
LONG (SIZEOF(.TFM_BSS) / 4)
/* Aligment checked after the section */
LONG (ADDR(.ER_TFM_SP_PS_BSS))
LONG (SIZEOF(.ER_TFM_SP_PS_BSS) / 4) /* Aligment checked after the section */
LONG (ADDR(.ER_TFM_SP_ITS_BSS))
LONG (SIZEOF(.ER_TFM_SP_ITS_BSS) / 4) /* Aligment checked after the section */
LONG (ADDR(.ER_TFM_SP_CRYPTO_BSS))
LONG (SIZEOF(.ER_TFM_SP_CRYPTO_BSS) / 4) /* Aligment checked after the section */
LONG (ADDR(.ER_TFM_SP_PLATFORM_BSS))
LONG (SIZEOF(.ER_TFM_SP_PLATFORM_BSS) / 4) /* Aligment checked after the section */
#ifdef CONFIG_TFM_PARTITION_META
LONG (ADDR(.TFM_SP_META_PTR))
LONG (SIZEOF(.TFM_SP_META_PTR) / 4) /* Aligment checked after the section */
#endif
__zero_table_end__ = .;
/* Capture all remaining code (except RAM code) in the privileged TF-M
* code region.
*/
*(SORT_BY_ALIGNMENT(EXCLUDE_FILE(*libflash_drivers* ITCM_FILES) .text*))
} > FLASH :flash
#ifdef RAM_VECTORS_SUPPORT
CHECK_ALIGNMENT_4(__vectors_end__ - __vectors_start__)
#endif
CHECK_ALIGNMENT_4(SIZEOF(.TFM_DATA))
#ifdef S_RAM_CODE_START
CHECK_ALIGNMENT_4(SIZEOF(.ER_CODE_SRAM))
#endif
#ifdef CONFIG_TFM_PARTITION_META
CHECK_ALIGNMENT_4(SIZEOF(.TFM_SP_META_PTR))
#endif
CHECK_ALIGNMENT_4(SIZEOF(.ER_TFM_SP_PS_DATA))
CHECK_ALIGNMENT_4(SIZEOF(.ER_TFM_SP_PS_BSS))
CHECK_ALIGNMENT_4(SIZEOF(.ER_TFM_SP_ITS_DATA))
CHECK_ALIGNMENT_4(SIZEOF(.ER_TFM_SP_ITS_BSS))
CHECK_ALIGNMENT_4(SIZEOF(.ER_TFM_SP_CRYPTO_DATA))
CHECK_ALIGNMENT_4(SIZEOF(.ER_TFM_SP_CRYPTO_BSS))
CHECK_ALIGNMENT_4(SIZEOF(.ER_TFM_SP_PLATFORM_DATA))
CHECK_ALIGNMENT_4(SIZEOF(.ER_TFM_SP_PLATFORM_BSS))
/* Position tag: End of PSA RoT code (privileged) */
. = ALIGN(TFM_LINKER_PT_PSA_ROT_CODE_ALIGNMENT);
Image$$PT_PSA_ROT_CODE_END$$Base = .;
/* Position tag: Start of RO-data (unprivileged, execute-never) */
. = ALIGN(TFM_LINKER_PT_RO_DATA_ALIGNMENT);
Image$$PT_RO_DATA_START$$Base = .;
/* Collect all RO-data into a single unprivileged region */
.ER_RO_DATA . :
{
*(SORT_BY_ALIGNMENT(EXCLUDE_FILE(*libflash_drivers* ITCM_FILES) .rodata*))
} > FLASH :flash
/**** Section for holding partition RO load data */
/*
* Sort the partition info by priority to guarantee the initing order.
* The first loaded partition will be inited at last in SFN model.
*/
.TFM_SP_LOAD_LIST ALIGN(TFM_LINKER_PT_RO_DATA_ALIGNMENT) :
{
KEEP(*(.part_load))
} > FLASH :flash
Image$$TFM_SP_LOAD_LIST$$RO$$Base = ADDR(.TFM_SP_LOAD_LIST);
Image$$TFM_SP_LOAD_LIST$$RO$$Limit = ADDR(.TFM_SP_LOAD_LIST) + SIZEOF(.TFM_SP_LOAD_LIST);
/* Position tag: End of RO-data (unprivileged, execute-never) */
. = ALIGN(TFM_LINKER_PT_RO_DATA_ALIGNMENT);
Image$$PT_RO_DATA_END$$Base = .;
#if defined(CONFIG_TFM_USE_TRUSTZONE) && defined(TFM_LINKER_VENEERS_LOCATION_END)
VENEERS()
#endif
/* Position tag: End of code + RO-data */
. = ALIGN(TFM_LINKER_PT_RO_ALIGNMENT);
Image$$PT_RO_END$$Base = .;
#ifdef S_RAM_CODE_START
/* Flash drivers code that gets copied from Flash */
.ER_CODE_SRAM ALIGN(S_RAM_CODE_START, TFM_LINKER_SRAM_CODE_ALIGNMENT) :
{
KEEP(*libflash_drivers*(SORT_BY_ALIGNMENT(.text*)))
KEEP(*libflash_drivers*(SORT_BY_ALIGNMENT(.rodata*)))
KEEP(*(.ramfunc))
#if defined(S_RAM_CODE_EXTRA_SECTION_NAME)
KEEP(*(S_RAM_CODE_EXTRA_SECTION_NAME))
#endif
. = ALIGN(4); /* This alignment is needed to make the section size 4 bytes aligned */
} > CODE_RAM AT > FLASH :coderam
ASSERT(S_RAM_CODE_START % 4 == 0, "S_RAM_CODE_START must be divisible by 4")
Image$$ER_CODE_SRAM$$RO$$Base = ADDR(.ER_CODE_SRAM);
Image$$ER_CODE_SRAM$$RO$$Limit = ADDR(.ER_CODE_SRAM) + SIZEOF(.ER_CODE_SRAM);
Image$$ER_CODE_SRAM$$Base = ADDR(.ER_CODE_SRAM);
Image$$ER_CODE_SRAM$$Limit = ADDR(.ER_CODE_SRAM) + SIZEOF(.ER_CODE_SRAM);
#endif
/**** Base address of secure data area */
.tfm_secure_data_start (NOLOAD):
{
/* Relocate current position to RAM */
. = ALIGN(4);
} > RAM
/*
* MPU on Armv6-M/v7-M core in multi-core topology may require more strict
* alignment that MPU region base address must align with the MPU region
* size.
* As a result, on Armv6-M/v7-M cores, to save memory resource and MPU
* regions, unprivileged data sections and privileged data sections can be
* separated and gathered in unprivileged/privileged data area respectively
* by defining S_DATA_PRIV_START. If so, the BL2 shared data area is moved
* to the beginning of the privileged data area, otherwise it is kept at the
* beginning of the secure data area.
*/
#ifndef S_DATA_PRIV_START
#ifdef CODE_SHARING
/* The code sharing between bootloader and runtime requires to share the
* global variables.
*/
.TFM_SHARED_SYMBOLS (NOLOAD) ALIGN(TFM_LINKER_SHARED_SYMBOLS_ALIGNMENT) :
{
. += SHARED_SYMBOL_AREA_SIZE;
} > RAM
#endif
#ifdef BOOT_TFM_SHARED_DATA_SIZE
/* Shared area between BL2 and runtime to exchange data */
.tfm_bl2_shared_data ALIGN(TFM_LINKER_BL2_SHARED_DATA_ALIGNMENT) (NOLOAD) :
{
. += BOOT_TFM_SHARED_DATA_SIZE;
} > RAM
#endif
#endif /* !S_DATA_PRIV_START */
/* Position tag: Start of Application RoT data (unprivileged) */
. = ALIGN(TFM_LINKER_PT_APP_ROT_DATA_ALIGNMENT);
Image$$PT_APP_ROT_DATA_START$$Base = .;
#ifdef CONFIG_TFM_PARTITION_META
.TFM_SP_META_PTR ALIGN(TFM_LINKER_SP_META_PTR_ALIGNMENT) (NOLOAD) :
{
*(.bss.SP_META_PTR_SPRTL_INST)
. = ALIGN(TFM_LINKER_SP_META_PTR_ALIGNMENT);
} > RAM
Image$$TFM_SP_META_PTR$$ZI$$Base = ADDR(.TFM_SP_META_PTR);
Image$$TFM_SP_META_PTR$$ZI$$Limit = ADDR(.TFM_SP_META_PTR) + SIZEOF(.TFM_SP_META_PTR);
/* This is needed for the uniform configuration of MPU region. */
Image$$TFM_SP_META_PTR_END$$ZI$$Limit = Image$$TFM_SP_META_PTR$$ZI$$Limit;
#endif
#ifdef CONFIG_TFM_REUSE_COPY_AREA_FOR_SP_STACKS
/* Record the FLASH load address right before the first entry of the copy area */
.flash_marker1 : ALIGN(TFM_LINKER_PT_AROT_PART_PRIVATE_DATA_ALIGNMENT) { } > RAM AT > FLASH :flash
#endif
.ER_TFM_SP_PS_DATA : ALIGN(TFM_LINKER_PT_AROT_PART_PRIVATE_DATA_ALIGNMENT)
{
/* Position tag: Start of Application RoT partition's private data */
Image$$PT_TFM_SP_PS_PRIVATE_DATA_START$$Base = .;
*tfm_*partition_ps.*:(SORT_BY_ALIGNMENT(.data*))
*(TFM_SP_PS_APP-ROT_ATTR_RW)
. = ALIGN(TFM_LINKER_PT_AROT_PART_PRIVATE_DATA_ALIGNMENT);
} > RAM AT > FLASH :phdr_TFM_SP_PS
.ER_TFM_SP_PS_BSS (NOLOAD) : ALIGN(TFM_LINKER_PT_AROT_PART_PRIVATE_DATA_ALIGNMENT)
{
start_of_TFM_SP_PS_bss = .;
*tfm_*partition_ps.*:(SORT_BY_ALIGNMENT(.bss*))
*tfm_*partition_ps.*:(COMMON)
*(TFM_SP_PS_APP-ROT_ATTR_ZI)
. += (. - start_of_TFM_SP_PS_bss) ? 0 : 4;
. = ALIGN(TFM_LINKER_PT_AROT_PART_PRIVATE_DATA_ALIGNMENT);
} > RAM
/* Position tag: End of Application RoT partition's private data */
. = ALIGN(TFM_LINKER_PT_AROT_PART_PRIVATE_DATA_ALIGNMENT);
Image$$PT_TFM_SP_PS_PRIVATE_DATA_END$$Base = .;
/* Position tag: End of Application RoT data (unprivileged) */
. = ALIGN(TFM_LINKER_PT_APP_ROT_DATA_ALIGNMENT);
Image$$PT_APP_ROT_DATA_END$$Base = .;
#ifdef S_DATA_PRIV_START
/**** Privileged data area base address specified by Armv6-M/v7-M platform */
.tfm_secure_priv_data_boundary (NOLOAD) :
{
. = ABSOLUTE(S_DATA_PRIV_START) ;
} > RAM
/*
* Move BL2 shared area to the beginning of privileged data area on
* Armv6-M/v7-M platforms.
*/
#ifdef BOOT_TFM_SHARED_DATA_SIZE
/* Shared area between BL2 and runtime to exchange data */
.tfm_bl2_shared_data ALIGN(TFM_LINKER_BL2_SHARED_DATA_ALIGNMENT) (NOLOAD) :
{
. += BOOT_TFM_SHARED_DATA_SIZE;
} > RAM
#endif
#endif /* S_DATA_PRIV_START */
/* Position tag: Start of PSA RoT data (privileged) */
. = ALIGN(TFM_LINKER_PT_PSA_ROT_DATA_ALIGNMENT);
Image$$PT_PSA_ROT_DATA_START$$Base = .;
.msp_stack ALIGN(TFM_LINKER_MSP_STACK_ALIGNMENT) (NOLOAD) :
{
. += __msp_stack_size__ - STACKSEAL_SIZE;
} > RAM
Image$$ARM_LIB_STACK$$ZI$$Base = ADDR(.msp_stack);
Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack);
PROVIDE(__stack = Image$$ARM_LIB_STACK$$ZI$$Limit);
#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) || \
defined(__ARM_ARCH_8_1M_MAIN__)
.msp_stack_seal_res (NOLOAD) :
{
. += STACKSEAL_SIZE;
} > RAM
__StackSeal = ADDR(.msp_stack_seal_res);
#endif
#ifdef ENABLE_HEAP
__heap_size__ = S_HEAP_SIZE;
.heap ALIGN(TFM_LINKER_TFM_HEAP_ALIGNMENT) (NOLOAD) :
{
__end__ = .;
PROVIDE(end = .);
__HeapBase = .;
. += __heap_size__;
__HeapLimit = .;
__heap_limit = .; /* Add for _sbrk */
} > RAM
#endif
.ER_TFM_SP_ITS_DATA : ALIGN(TFM_LINKER_PT_PROT_PART_PRIVATE_DATA_ALIGNMENT)
{
/* Position tag: Start of PSA RoT partition's private data */
Image$$PT_TFM_SP_ITS_PRIVATE_DATA_START$$Base = .;
*tfm_*partition_its.*:(SORT_BY_ALIGNMENT(.data*))
*(TFM_SP_ITS_PSA-ROT_ATTR_RW)
. = ALIGN(TFM_LINKER_PT_PROT_PART_PRIVATE_DATA_ALIGNMENT);
} > RAM AT > FLASH :phdr_TFM_SP_ITS
.ER_TFM_SP_ITS_BSS (NOLOAD) : ALIGN(TFM_LINKER_PT_PROT_PART_PRIVATE_DATA_ALIGNMENT)
{
*tfm_*partition_its.*:(SORT_BY_ALIGNMENT(.bss*))
*tfm_*partition_its.*:(COMMON)
*(TFM_SP_ITS_PSA-ROT_ATTR_ZI)
. = ALIGN(TFM_LINKER_PT_PROT_PART_PRIVATE_DATA_ALIGNMENT);
/* Position tag: End of PSA RoT partition's private data */
Image$$PT_TFM_SP_ITS_PRIVATE_DATA_END$$Base = .;
} > RAM
.ER_TFM_SP_CRYPTO_DATA : ALIGN(TFM_LINKER_PT_PROT_PART_PRIVATE_DATA_ALIGNMENT)
{
/* Position tag: Start of PSA RoT partition's private data */
Image$$PT_TFM_SP_CRYPTO_PRIVATE_DATA_START$$Base = .;
*tfm_*partition_crypto.*:(SORT_BY_ALIGNMENT(.data*))
*tfpsacrypto.*:(SORT_BY_ALIGNMENT(.data*))
*tfpsacrypto*acceleration.*:(SORT_BY_ALIGNMENT(.data*))
*(TFM_SP_CRYPTO_PSA-ROT_ATTR_RW)
. = ALIGN(TFM_LINKER_PT_PROT_PART_PRIVATE_DATA_ALIGNMENT);
} > RAM AT > FLASH :phdr_TFM_SP_CRYPTO
.ER_TFM_SP_CRYPTO_BSS (NOLOAD) : ALIGN(TFM_LINKER_PT_PROT_PART_PRIVATE_DATA_ALIGNMENT)
{
*tfm_*partition_crypto.*:(SORT_BY_ALIGNMENT(.bss*))
*tfm_*partition_crypto.*:(COMMON)
*tfpsacrypto.*:(SORT_BY_ALIGNMENT(.bss*))
*tfpsacrypto.*:(COMMON)
*tfpsacrypto*acceleration.*:(SORT_BY_ALIGNMENT(.bss*))
*tfpsacrypto*acceleration.*:(COMMON)
*(TFM_SP_CRYPTO_PSA-ROT_ATTR_ZI)
. = ALIGN(TFM_LINKER_PT_PROT_PART_PRIVATE_DATA_ALIGNMENT);
/* Position tag: End of PSA RoT partition's private data */
Image$$PT_TFM_SP_CRYPTO_PRIVATE_DATA_END$$Base = .;
} > RAM
.ER_TFM_SP_PLATFORM_DATA : ALIGN(TFM_LINKER_PT_PROT_PART_PRIVATE_DATA_ALIGNMENT)
{
/* Position tag: Start of PSA RoT partition's private data */
Image$$PT_TFM_SP_PLATFORM_PRIVATE_DATA_START$$Base = .;
*tfm_*partition_platform.*:(SORT_BY_ALIGNMENT(.data*))
*(TFM_SP_PLATFORM_PSA-ROT_ATTR_RW)
. = ALIGN(TFM_LINKER_PT_PROT_PART_PRIVATE_DATA_ALIGNMENT);
} > RAM AT > FLASH :phdr_TFM_SP_PLATFORM
.ER_TFM_SP_PLATFORM_BSS (NOLOAD) : ALIGN(TFM_LINKER_PT_PROT_PART_PRIVATE_DATA_ALIGNMENT)
{
*tfm_*partition_platform.*:(SORT_BY_ALIGNMENT(.bss*))
*tfm_*partition_platform.*:(COMMON)
*(TFM_SP_PLATFORM_PSA-ROT_ATTR_ZI)
. = ALIGN(TFM_LINKER_PT_PROT_PART_PRIVATE_DATA_ALIGNMENT);
/* Position tag: End of PSA RoT partition's private data */
Image$$PT_TFM_SP_PLATFORM_PRIVATE_DATA_END$$Base = .;
} > RAM
.TFM_DATA ALIGN(TFM_LINKER_TFM_DATA_ALIGNMENT) :
{
*(SORT_BY_ALIGNMENT(.data*))
KEEP(*(.jcr*))
. = ALIGN(TFM_LINKER_TFM_DATA_ALIGNMENT);
} > RAM AT > FLASH :tfm_data
#ifdef S_RUNTIME_ITCM_START
.ER_ITCM_CODE :
{
ITCM_FILES:(SORT_BY_ALIGNMENT(.text*))
ITCM_FILES:(SORT_BY_ALIGNMENT(.rodata*))
. = ALIGN(TFM_LINKER_ITCM_CODE_ALIGNMENT);
} > ITCM AT > FLASH :itcm
#endif
#ifdef CONFIG_TFM_REUSE_COPY_AREA_FOR_SP_STACKS
/*
* Align the overlay load region in FLASH.
* We can't rely on section placement alone, since we need the LMA
* to be aligned.
* This expression ensures the next section's load address starts at
* a properly aligned boundary in FLASH for the overlay area.
*/
Image$$PT_OVERLAY_AREA_BEGIN$$Base = LOADADDR(.flash_marker1);
.tfm_runtime_sp_stacks Image$$PT_OVERLAY_AREA_BEGIN$$Base (NOLOAD) : ALIGN(TFM_LINKER_PT_AROT_PART_PRIVATE_DATA_ALIGNMENT)
{
KEEP(*(.tfm_runtime_sp_stacks*))
} > FLASH
Image$$PT_OVERLAY_AREA_END$$Base = .;
#endif /* CONFIG_TFM_REUSE_COPY_AREA_FOR_SP_STACKS */
.TFM_BSS (NOLOAD) : ALIGN(TFM_LINKER_TFM_BSS_ALIGNMENT)
{
__bss_start__ = .;
/* The runtime partition placed order is same as load partition */
__partition_runtime_start__ = .;
KEEP(*(.bss.part_runtime))
__partition_runtime_end__ = .;
. = ALIGN(TFM_LINKER_TFM_BSS_ALIGNMENT);
/* The runtime service placed order is same as load partition */
__service_runtime_start__ = .;
KEEP(*(.bss.serv_runtime))
__service_runtime_end__ = .;
*(SORT_BY_ALIGNMENT(.bss*))
*(COMMON)
*(SORT_BY_ALIGNMENT(.noinit*)) /* Uninitialized RAM */
*(SORT_BY_ALIGNMENT(.cy_sharedmem*)) /* Cypress shared memory */
. = ALIGN(TFM_LINKER_TFM_BSS_ALIGNMENT);
__bss_end__ = .;
} > RAM
Image$$ER_PART_RT_POOL$$ZI$$Base = __partition_runtime_start__;
Image$$ER_PART_RT_POOL$$ZI$$Limit = __partition_runtime_end__;
Image$$ER_SERV_RT_POOL$$ZI$$Base = __service_runtime_start__;
Image$$ER_SERV_RT_POOL$$ZI$$Limit = __service_runtime_end__;
/* Position tag: End of PSA RoT data (privileged) */
. = ALIGN(TFM_LINKER_PT_PSA_ROT_DATA_ALIGNMENT);
Image$$PT_PSA_ROT_DATA_END$$Base = .;
#ifdef RAM_VECTORS_SUPPORT
.ramVectors ALIGN(TFM_LINKER_RAM_VECTORS_ALIGNMENT) (NOLOAD) :
{
__ram_vectors_start__ = .;
KEEP(*(.ram_vectors))
__ram_vectors_end__ = .;
} > RAM
#endif
#ifdef CONFIG_TFM_USE_TRUSTZONE
Image$$ER_VENEER$$Base = ADDR(.gnu.sgstubs);
Image$$VENEER_ALIGN$$Limit = ADDR(.sgstubs_end);
#ifdef TFM_LINKER_VENEERS_SIZE
ASSERT ((Image$$VENEER_ALIGN$$Limit - Image$$ER_VENEER$$Base) <= TFM_LINKER_VENEERS_SIZE, "Veneer region overflowed")
#endif
#endif
Load$$LR$$LR_NS_PARTITION$$Base = NS_PARTITION_START;
#ifdef BL2
Load$$LR$$LR_SECONDARY_PARTITION$$Base = SECONDARY_PARTITION_START;
#endif /* BL2 */
}