From 8d8f3414bad842aadd4195c69d994607b7e02aa9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 19 May 2025 15:54:48 -0700 Subject: [PATCH 1/2] Use picolibc instead of newlib-nano 1. Add picolibc bits to linker scripts. Picolibc uses thread local storage for unshared data, and the picolibc startup code relies on carefully constructed linker script that allocates one TLS block in RAM for applications that don't have explicit TLS support. The picolibc startup code also uses different symbols than the tf-m startup code. 2. Support picolibc stdio. There was already picolibc support code present in the library for the ARM LLVM toolchain. The conditionals which selected it have been changed to use __PICOLIBC__ instead of __clang_major__. 3. Add _exit stub. Code using assert or abort end up calling _exit through the picolibc signal handling code. 4. Switch to picolibc.specs. This is needed for toolchains which don't use picolibc by default, and can also be used without trouble in toolchains where picolibc is the default. Signed-off-by: Keith Packard --- platform/CMakeLists.txt | 1 + platform/ext/common/gcc/tfm_common_bl2.ld | 32 +++++++++++++ platform/ext/common/gcc/tfm_common_ns.ld | 39 +++++++++++++-- .../ext/common/gcc/tfm_common_s.ld.template | 40 ++++++++++++++-- .../common/gcc/tfm_isolation_s.ld.template | 43 ++++++++++++++++- platform/ext/common/picolibc.c | 48 +++++++++++++++++++ platform/ext/common/syscalls_stub.c | 10 ++++ platform/ext/common/uart_stdout.c | 2 +- .../adi/max32657/device/gcc/max32657_sla.ld | 36 +++++++++++++- .../target/stm/common/hal/template/gcc/bl2.ld | 42 ++++++++++++++-- .../Device/Source/gcc/tfm_common_s.ld | 35 +++++++++++--- .../Device/Source/gcc/tfm_common_s.ld | 43 ++++++++++++++--- platform/ns/toolchain_ns_GNUARM.cmake | 7 ++- toolchain_GNUARM.cmake | 7 ++- 14 files changed, 349 insertions(+), 36 deletions(-) create mode 100644 platform/ext/common/picolibc.c diff --git a/platform/CMakeLists.txt b/platform/CMakeLists.txt index 15367499f8..48e8b059f5 100644 --- a/platform/CMakeLists.txt +++ b/platform/CMakeLists.txt @@ -90,6 +90,7 @@ target_sources(platform_s target_sources(tfm_s PRIVATE ext/common/faults.c + ext/common/picolibc.c ) target_link_libraries(platform_s diff --git a/platform/ext/common/gcc/tfm_common_bl2.ld b/platform/ext/common/gcc/tfm_common_bl2.ld index de6049c5da..3cdd8be115 100644 --- a/platform/ext/common/gcc/tfm_common_bl2.ld +++ b/platform/ext/common/gcc/tfm_common_bl2.ld @@ -153,6 +153,26 @@ SECTIONS } > RAM AT > FLASH Image$$ER_DATA$$Base = ADDR(.data); + .tdata : ALIGN_WITH_INPUT + { + *(.tdata .tdata.* .gnu.linkonce.td.*) + PROVIDE( __data_end = . ); + PROVIDE( __tdata_end = . ); + } >RAM AT>FLASH + + .tbss (NOLOAD) : + { + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + PROVIDE( __tls_end = . ); + PROVIDE( __tbss_end = . ); + } >RAM AT>RAM + + .tbss_space (NOLOAD) : { + . = ADDR(.tbss); + . = . + SIZEOF(.tbss); + } >RAM AT>RAM + .bss : ALIGN(4) { . = ALIGN(4); @@ -163,6 +183,16 @@ SECTIONS __bss_end__ = .; } > RAM + PROVIDE( __bss_end = __bss_end__ ); + PROVIDE( __data_start = ADDR(.data) ); + PROVIDE( __data_source = LOADADDR(.data) ); + PROVIDE( __data_size = __data_end - __data_start ); + PROVIDE( __tls_base = SIZEOF(.tdata) ? ADDR(.tdata) : ADDR(.tbss) ); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + PROVIDE( __bss_start = ADDR(.tbss)); + PROVIDE( __bss_size = __bss_end - __bss_start ); + #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) .msp_stack (NOLOAD) : ALIGN(32) { @@ -200,4 +230,6 @@ SECTIONS Image$$ARM_LIB_HEAP$$ZI$$Limit = ADDR(.heap) + SIZEOF(.heap); PROVIDE(__stack = Image$$ARM_LIB_STACK$$ZI$$Limit); + PROVIDE( __heap_start = __HeapBase ); + PROVIDE( __heap_end = __HeapLimit ); } diff --git a/platform/ext/common/gcc/tfm_common_ns.ld b/platform/ext/common/gcc/tfm_common_ns.ld index dd303d9dca..2bc32909b6 100644 --- a/platform/ext/common/gcc/tfm_common_ns.ld +++ b/platform/ext/common/gcc/tfm_common_ns.ld @@ -128,22 +128,51 @@ SECTIONS KEEP(*(.jcr*)) . = ALIGN(4); - /* All data end */ - __data_end__ = .; } > RAM - .bss : + .tdata : AT (__etext + SIZEOF(.data)) + { + *(.tdata .tdata.* .gnu.linkonce.td.*) + PROVIDE( __data_end = . ); + PROVIDE( __data_end__ = . ); + PROVIDE( __tdata_end = . ); + } > RAM + + .tbss (NOLOAD) : { . = ALIGN(4); __bss_start__ = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + PROVIDE( __tls_end = . ); + PROVIDE( __tbss_end = . ); + } > RAM + + .tbss_space (NOLOAD) : + { + . = ADDR(.tbss); + . = . + SIZEOF(.tbss); + } > RAM + + .bss : + { + . = ALIGN(4); *(.bss*) *(COMMON) . = ALIGN(4); __bss_end__ = .; } > RAM - bss_size = __bss_end__ - __bss_start__; + PROVIDE( __bss_end = __bss_end__ ); + PROVIDE( __data_start = ADDR(.data) ); + PROVIDE( __data_source = LOADADDR(.data) ); + PROVIDE( __data_size = __data_end - __data_start ); + PROVIDE( __bss_start = ADDR(.tbss) ); + PROVIDE( __bss_size = __bss_end - __bss_start ); + PROVIDE( __tls_base = SIZEOF(.tdata) ? ADDR(.tdata) : ADDR(.tbss) ); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); .stack : ALIGN(32) { @@ -164,4 +193,6 @@ SECTIONS } > RAM PROVIDE(__stack = __StackTop); + PROVIDE( __heap_start = __HeapBase ); + PROVIDE( __heap_end = __HeapLimit ); } diff --git a/platform/ext/common/gcc/tfm_common_s.ld.template b/platform/ext/common/gcc/tfm_common_s.ld.template index f0e1332af6..a508c08271 100644 --- a/platform/ext/common/gcc/tfm_common_s.ld.template +++ b/platform/ext/common/gcc/tfm_common_s.ld.template @@ -573,13 +573,35 @@ SECTIONS . = ALIGN(4); } > RAM AT> FLASH + + .TFM_TDATA : ALIGN_WITH_INPUT + { + *(.tdata .tdata.* .gnu.linkonce.td.*) + PROVIDE( __data_end = . ); + PROVIDE( __tdata_end = . ); + } > RAM AT> FLASH + Image$$ER_TFM_DATA$$RW$$Base = ADDR(.TFM_DATA); - Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA); + Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_TDATA) + SIZEOF(.TFM_TDATA); - .TFM_BSS ALIGN(4) (NOLOAD) : + .TFM_TBSS (NOLOAD) : { __bss_start__ = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + PROVIDE( __tls_end = . ); + PROVIDE( __tbss_end = . ); + } > RAM AT> RAM + + .TFM_TBSS_SPACE (NOLOAD) : + { + . = ADDR(.TFM_TBSS); + . = . + SIZEOF(.TFM_TBSS); + } > RAM AT> RAM + + .TFM_BSS ALIGN(4) (NOLOAD) : + { /* The runtime partition placed order is same as load partition */ __partition_runtime_start__ = .; KEEP(*(.bss.part_runtime_priority_00)) @@ -600,8 +622,9 @@ SECTIONS *(COMMON) . = ALIGN(4); __bss_end__ = .; + __bss_end = .; } > RAM AT> RAM - Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS); + Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_TBSS); Image$$ER_TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS); Image$$ER_PART_RT_POOL$$ZI$$Base = __partition_runtime_start__; Image$$ER_PART_RT_POOL$$ZI$$Limit = __partition_runtime_end__; @@ -609,7 +632,16 @@ SECTIONS Image$$ER_SERV_RT_POOL$$ZI$$Limit = __service_runtime_end__; Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA); - Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS); + Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS); + + PROVIDE( __data_start = ADDR(.TFM_DATA) ); + PROVIDE( __data_source = LOADADDR(.TFM_DATA) ); + PROVIDE( __data_size = __data_end - __data_start ); + PROVIDE( __bss_start = ADDR(.TFM_TBSS) ); + PROVIDE( __bss_size = __bss_end - __bss_start ); + PROVIDE( __tls_base = SIZEOF(.TFM_TDATA) ? ADDR(.TFM_TDATA) : ADDR(.TFM_TBSS) ); + PROVIDE( __tls_align = MAX(ALIGNOF(.TFM_TDATA), ALIGNOF(.TFM_TBSS)) ); + PROVIDE(__arm32_tls_tcb_offset = MAX(8, __tls_align) ); #if defined(CONFIG_TFM_USE_TRUSTZONE) Image$$ER_VENEER$$Base = ADDR(.gnu.sgstubs); diff --git a/platform/ext/common/gcc/tfm_isolation_s.ld.template b/platform/ext/common/gcc/tfm_isolation_s.ld.template index b93816a815..9a654975a4 100644 --- a/platform/ext/common/gcc/tfm_isolation_s.ld.template +++ b/platform/ext/common/gcc/tfm_isolation_s.ld.template @@ -210,20 +210,22 @@ SECTIONS . = ALIGN(4); /* preinit data */ PROVIDE_HIDDEN (__preinit_array_start = .); + PROVIDE_HIDDEN (__bothinit_array_start = .); KEEP(*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); . = ALIGN(4); /* init data */ PROVIDE_HIDDEN (__init_array_start = .); - KEEP(*(SORT(.init_array.*))) + KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*))) KEEP(*(.init_array)) PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE_HIDDEN (__bothinit_array_end = .); . = ALIGN(4); /* finit data */ PROVIDE_HIDDEN (__fini_array_start = .); - KEEP(*(SORT(.fini_array.*))) + KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*))) KEEP(*(.fini_array)) PROVIDE_HIDDEN (__fini_array_end = .); @@ -251,6 +253,10 @@ SECTIONS LONG (ADDR(.ER_CODE_SRAM)) LONG (SIZEOF(.ER_CODE_SRAM) / 4) #endif + LONG (LOADADDR(.TFM_TDATA)) + LONG (ADDR(.TFM_TLS_BASE)) + LONG (SIZEOF(.TFM_TDATA) / 4) + __copy_table_end__ = .; /* .zero.table */ @@ -265,6 +271,10 @@ SECTIONS LONG (ADDR(.TFM_SP_META_PTR)) LONG (SIZEOF(.TFM_SP_META_PTR) / 4) #endif + + LONG (ADDR(.TFM_TLS_BASE) + SIZEOF(.TFM_TDATA)) + LONG ((SIZEOF(.TFM_TLS_BASE) - SIZEOF(.TFM_TDATA)) / 4) + __zero_table_end__ = .; /* Capture all remaining code (except RAM code) in the privileged TF-M @@ -549,6 +559,10 @@ SECTIONS . = ALIGN(4); } > RAM AT > FLASH + PROVIDE(__data_source = LOADADDR(.TFM_DATA)); + PROVIDE(__data_start = ADDR(.TFM_DATA)); + PROVIDE(__data_size = SIZEOF(.TFM_DATA)); + .TFM_BSS ALIGN(4) (NOLOAD) : { __bss_start__ = .; @@ -574,6 +588,31 @@ SECTIONS . = ALIGN(4); __bss_end__ = .; } > RAM + + PROVIDE(__bss_start = ADDR(.TFM_BSS)); + PROVIDE(__bss_size = SIZEOF(.TFM_BSS)); + + .TFM_TDATA : + { + PROVIDE( __tls_start_addr = . ); + *(.tdata .tdata.* .gnu.linkonce.td.*) + } > RAM + + .TFM_TBSS : + { + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + PROVIDE( __tls_end_addr = . ); + } > RAM + + .TFM_TLS_BASE : { + . = . + (__tls_end_addr - __tls_start_addr); + } > RAM + PROVIDE( __tls_base = ADDR(.TFM_TLS_BASE) ); + PROVIDE( __tls_align = MAX(ALIGNOF(.TFM_TDATA), ALIGNOF(.TFM_TBSS)) ); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + PROVIDE( __arm64_tls_tcb_offset = MAX(16, __tls_align) ); + 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__; diff --git a/platform/ext/common/picolibc.c b/platform/ext/common/picolibc.c new file mode 100644 index 0000000000..4438ebe8e2 --- /dev/null +++ b/platform/ext/common/picolibc.c @@ -0,0 +1,48 @@ +/* + * Copyright © 2025, Keith Packard + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include "config_impl.h" + +/* + * Picolibc's startup code only initializes a single data and bss + * segment. Augment that by initializing the remaining segments using + * the lists provided by the linker script in a constructor which will + * be called from _start + */ + +#if defined(__PICOLIBC__) && TFM_ISOLATION_LEVEL > 0 + +static void __attribute__((constructor)) +picolibc_startup(void) +{ + 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) { + memcpy(pTable->dest, pTable->src, pTable->wlen << 2); + } + + for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) { + memset(pTable->dest, 0, pTable->wlen << 2); + } +} +#endif diff --git a/platform/ext/common/syscalls_stub.c b/platform/ext/common/syscalls_stub.c index 9ebe78e97e..7256b774b3 100644 --- a/platform/ext/common/syscalls_stub.c +++ b/platform/ext/common/syscalls_stub.c @@ -14,6 +14,14 @@ #include #include +#ifdef __PICOLIBC__ +__attribute__((weak)) +void _exit(int status) +{ + (void) status; + for(;;); +} +#else __attribute__((weak)) void _close(void) { @@ -53,3 +61,5 @@ __attribute__((weak)) void _write(void) { } + +#endif /* !__PICOLIBC__ */ diff --git a/platform/ext/common/uart_stdout.c b/platform/ext/common/uart_stdout.c index fec035ada7..e1fdb82f27 100644 --- a/platform/ext/common/uart_stdout.c +++ b/platform/ext/common/uart_stdout.c @@ -85,7 +85,7 @@ int fputc(int ch, FILE *f) /* Redirect sdtio for PicoLib in LLVM toolchain as per https://github.com/picolibc/picolibc/blob/main/doc/os.md 'fputch()' named intentionally different from 'fputc()' from picolib */ -#elif defined(__clang_major__) +#elif defined(__PICOLIBC__) int fputch(char ch, struct __file *f) { diff --git a/platform/ext/target/adi/max32657/device/gcc/max32657_sla.ld b/platform/ext/target/adi/max32657/device/gcc/max32657_sla.ld index 10a91a559f..feca070d43 100644 --- a/platform/ext/target/adi/max32657/device/gcc/max32657_sla.ld +++ b/platform/ext/target/adi/max32657/device/gcc/max32657_sla.ld @@ -156,16 +156,48 @@ SECTIONS } > RAM AT > FLASH Image$$ER_DATA$$Base = ADDR(.data); - .bss : ALIGN(4) + .tdata : { + *(.tdata .tdata.* .gnu.linkonce.td.*) + PROVIDE(__data_end = .); + PROVIDE(__data_end__ = .); + PROVIDE(__tdata_end = .); + } > RAM AT > FLASH + + .tbss (NOLOAD) : { . = ALIGN(4); __bss_start__ = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + PROVIDE( __tls_end = . ); + PROVIDE( __tbss_end = . ); + } > RAM + + .tbss_space (NOLOAD) : { + . = ADDR(.tbss); + . = . + SIZEOF(.tbss); + } > RAM + + .bss : ALIGN(4) + { + . = ALIGN(4); *(.bss*) *(COMMON) . = ALIGN(4); __bss_end__ = .; + PROVIDE(__bss_end = .); } > RAM + bss_size = __bss_end__ - __bss_start__; + PROVIDE(__data_start = ADDR(.data)); + PROVIDE(__data_source = LOADADDR(.data)); + PROVIDE(__data_size = __data_end - __data_start ); + PROVIDE( __bss_start = ADDR(.tbss)); + PROVIDE( __bss_size = __bss_end - __bss_start ); + PROVIDE( __tls_base = SIZEOF(.tdata) ? ADDR(.tdata) : ADDR(.tbss) ); + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE(__arm32_tls_tcb_offset = MAX(8, __tls_align) ); + #if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) .msp_stack (NOLOAD) : ALIGN(32) { @@ -196,9 +228,11 @@ SECTIONS __end__ = .; PROVIDE(end = .); __HeapBase = .; + PROVIDE(__heap_start = .); . += __heap_size__; __HeapLimit = .; __heap_limit = .; /* Add for _sbrk */ + PROVIDE(__heap_end = .); } > RAM Image$$ARM_LIB_HEAP$$ZI$$Limit = ADDR(.heap) + SIZEOF(.heap); diff --git a/platform/ext/target/stm/common/hal/template/gcc/bl2.ld b/platform/ext/target/stm/common/hal/template/gcc/bl2.ld index 04910acd3b..d325d47304 100644 --- a/platform/ext/target/stm/common/hal/template/gcc/bl2.ld +++ b/platform/ext/target/stm/common/hal/template/gcc/bl2.ld @@ -169,24 +169,56 @@ SECTIONS KEEP(*(.jcr*)) . = ALIGN(4); + + } > RAM + + .tdata : ALIGN_WITH_INPUT { + *(.tdata .tdata.* .gnu.linkonce.td.*) + PROVIDE(__data_end = .); + PROVIDE(__tdata_end = .); /* All data end */ __data_end__ = .; - } > RAM + Image$$ER_CODE$$Base = __Vectors ; - Image$$ER_CODE$$Limit = __etext + + SIZEOF(.data); + Image$$ER_CODE$$Limit = __etext + + SIZEOF(.data) + SIZEOF(.tdata); + + .tbss (NOLOAD) : { + . = ALIGN(4); + __bss_start__ = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + PROVIDE( __tls_end = . ); + PROVIDE( __tbss_end = . ); + } > RAM + + .tbss_space (NOLOAD) : { + . = ADDR(.tbss); + . = . + SIZEOF(.tbss); + } > RAM + .bss : { . = ALIGN(4); - __bss_start__ = .; *(.bss*) *(COMMON) . = ALIGN(4); __bss_end__ = .; + PROVIDE(__bss_end = .); } > RAM bss_size = __bss_end__ - __bss_start__; + PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) ); + PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) ); + PROVIDE(__data_source = LOADADDR(.data)); + PROVIDE(__data_start = ADDR(.data)); + PROVIDE( __data_size = __data_end - __data_start ); + PROVIDE( __bss_start = ADDR(.tbss)); + PROVIDE( __bss_size = __bss_end - __bss_start ); + PROVIDE( __tls_first = SIZEOF(.tdata) ? ADDR(.tdata) : ADDR(.tbss) ); + PROVIDE( __tls_base = __tls_first ); + .msp_stack : { . = ALIGN(8); @@ -208,4 +240,8 @@ SECTIONS } > RAM PROVIDE(__stack = Image$$ARM_LIB_STACK$$ZI$$Limit); + + PROVIDE(__heap_start = ADDR(.heap)); + PROVIDE(__heap_end = ADDR(.heap) + SIZEOF(.heap)); + } diff --git a/platform/ext/target/stm/common/stm32h5xx/Device/Source/gcc/tfm_common_s.ld b/platform/ext/target/stm/common/stm32h5xx/Device/Source/gcc/tfm_common_s.ld index 930d7b4ae3..6044ffb704 100644 --- a/platform/ext/target/stm/common/stm32h5xx/Device/Source/gcc/tfm_common_s.ld +++ b/platform/ext/target/stm/common/stm32h5xx/Device/Source/gcc/tfm_common_s.ld @@ -295,14 +295,22 @@ SECTIONS .TFM_DATA : ALIGN(4) { + PROVIDE(__data_start = .); *(.data*) KEEP(*(.jcr*)) . = ALIGN(4); } > RAM AT> FLASH + + .TFM_TDATA : ALIGN_WITH_INPUT { + *(.tdata .tdata.* .gnu.linkonce.td.*) + PROVIDE(__data_end = .); + PROVIDE(__tdata_end = .); + } > RAM AT> FLASH + Image$$ER_TFM_DATA$$RW$$Base = ADDR(.TFM_DATA); - Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA); + Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_TDATA) + SIZEOF(.TFM_TDATA); /**** PSA RoT DATA end here */ Image$$TFM_PSA_RW_STACK_END$$Base = .; @@ -376,10 +384,22 @@ SECTIONS Image$$TFM_APP_ROT_LINKER$$Base = ADDR(.TFM_APP_ROT_LINKER); Image$$TFM_APP_ROT_LINKER$$Limit = ADDR(.TFM_APP_ROT_LINKER) + SIZEOF(.TFM_APP_ROT_LINKER); - .TFM_BSS (NOLOAD): ALIGN(4) - { + .TFM_TBSS (NOLOAD) : { __bss_start__ = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + PROVIDE( __tls_end = . ); + PROVIDE( __tbss_end = . ); + } > RAM AT> RAM + + .TFM_TBSS_SPACE (NOLOAD) : { + . = ADDR(.TFM_TBSS); + . = . + SIZEOF(.TFM_TBSS); + } > RAM AT> RAM + + .TFM_BSS (NOLOAD): ALIGN(4) + { /* The runtime partition placed order is same as load partition */ __partition_runtime_start__ = .; KEEP(*(.bss.part_runtime_priority_00)) @@ -400,16 +420,17 @@ SECTIONS *(COMMON) . = ALIGN(4); __bss_end__ = .; + PROVIDE(__bss_end = .); } > RAM AT> RAM - Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS); - Image$$ER_TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS); + Image$$ER_TFM_DATA$$ZI$$Base = __bss_start__; + Image$$ER_TFM_DATA$$ZI$$Limit = __bss_end__; 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__; - Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA); - Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS); + Image$$ER_TFM_DATA$$Base = __data_start; + Image$$ER_TFM_DATA$$Limit = __bss_end; #if defined(PSA_PROXY_SHARED_MEMORY_BASE) /* If a variable defined with __attribute__((section())) keyword the diff --git a/platform/ext/target/stm/common/stm32u5xx/Device/Source/gcc/tfm_common_s.ld b/platform/ext/target/stm/common/stm32u5xx/Device/Source/gcc/tfm_common_s.ld index 591c193c17..693685b00c 100644 --- a/platform/ext/target/stm/common/stm32u5xx/Device/Source/gcc/tfm_common_s.ld +++ b/platform/ext/target/stm/common/stm32u5xx/Device/Source/gcc/tfm_common_s.ld @@ -129,7 +129,7 @@ SECTIONS __copy_table_start__ = .; LONG (LOADADDR(.TFM_DATA)) LONG (ADDR(.TFM_DATA)) - LONG (SIZEOF(.TFM_DATA) / 4) + LONG ((SIZEOF(.TFM_DATA) + SIZEOF(.TFM_TDATA)) / 4) LONG (LOADADDR(.TFM_PSA_ROT_LINKER_DATA)) LONG (ADDR(.TFM_PSA_ROT_LINKER_DATA)) @@ -142,8 +142,8 @@ SECTIONS . = ALIGN(4); __zero_table_start__ = .; - LONG (ADDR(.TFM_BSS)) - LONG (SIZEOF(.TFM_BSS) / 4) + LONG (ADDR(.TFM_TBSS)) + LONG ((SIZEOF(.TFM_BSS) + SIZEOF(.TFM_TBSS)) / 4) LONG (ADDR(.TFM_PSA_ROT_LINKER_BSS)) LONG (SIZEOF(.TFM_PSA_ROT_LINKER_BSS) / 4) @@ -320,8 +320,15 @@ SECTIONS . = ALIGN(4); } > RAM AT> FLASH + + .TFM_TDATA : ALIGN_WITH_INPUT { + *(.tdata .tdata.* .gnu.linkonce.td.*) + PROVIDE(__data_end = .); + PROVIDE(__tdata_end = .); + } > RAM AT> FLASH + Image$$ER_TFM_DATA$$RW$$Base = ADDR(.TFM_DATA); - Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA); + Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_TDATA) + SIZEOF(.TFM_TDATA); /**** PSA RoT DATA end here */ Image$$TFM_PSA_RW_STACK_END$$Base = .; @@ -374,6 +381,20 @@ SECTIONS Image$$TFM_APP_ROT_LINKER$$Base = ADDR(.TFM_APP_ROT_LINKER); Image$$TFM_APP_ROT_LINKER$$Limit = ADDR(.TFM_APP_ROT_LINKER) + SIZEOF(.TFM_APP_ROT_LINKER); + .TFM_TBSS (NOLOAD) : { + __bss_start__ = .; + + *(.tbss .tbss.* .gnu.linkonce.tb.*) + *(.tcommon) + PROVIDE( __tls_end = . ); + PROVIDE( __tbss_end = . ); + } > RAM AT> RAM + + .TFM_TBSS_SPACE (NOLOAD) : { + . = ADDR(.TFM_TBSS); + . = . + SIZEOF(.TFM_TBSS); + } > RAM AT> RAM + .TFM_BSS (NOLOAD): ALIGN(4) { __bss_start__ = .; @@ -398,8 +419,9 @@ SECTIONS *(COMMON) . = ALIGN(4); __bss_end__ = .; + __bss_end = .; } > RAM AT> RAM - Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS); + Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_TBSS); Image$$ER_TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS); Image$$ER_PART_RT_POOL$$ZI$$Base = __partition_runtime_start__; Image$$ER_PART_RT_POOL$$ZI$$Limit = __partition_runtime_end__; @@ -407,7 +429,16 @@ SECTIONS Image$$ER_SERV_RT_POOL$$ZI$$Limit = __service_runtime_end__; Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA); - Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS); + Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS); + + PROVIDE(__data_start = ADDR(.TFM_DATA)); + PROVIDE(__data_source = LOADADDR(.TFM_DATA)); + PROVIDE(__data_size = __data_end - __data_start ); + PROVIDE( __bss_start = ADDR(.TFM_TBSS)); + PROVIDE( __bss_size = __bss_end - __bss_start ); + PROVIDE( __tls_base = SIZEOF(.TFM_TDATA) ? ADDR(.TFM_TDATA) : ADDR(.TFM_TBSS) ); + PROVIDE( __tls_align = MAX(ALIGNOF(.TFM_TDATA), ALIGNOF(.TFM_TBSS)) ); + PROVIDE(__arm32_tls_tcb_offset = MAX(8, __tls_align) ); #if defined(PSA_PROXY_SHARED_MEMORY_BASE) /* If a variable defined with __attribute__((section())) keyword the diff --git a/platform/ns/toolchain_ns_GNUARM.cmake b/platform/ns/toolchain_ns_GNUARM.cmake index 41782d967f..d52412ce56 100644 --- a/platform/ns/toolchain_ns_GNUARM.cmake +++ b/platform/ns/toolchain_ns_GNUARM.cmake @@ -177,8 +177,7 @@ string(APPEND CMAKE_ASM_LINK_FLAGS " " ${LINKER_CP_OPTION}) add_compile_definitions($<$:__ARM_ARCH_8_1M_MAIN__=1>) add_compile_options( - -specs=nano.specs - -specs=nosys.specs + -specs=picolibc.specs -Wall -Wno-format -Wno-array-parameter @@ -200,8 +199,8 @@ add_compile_options( add_link_options( --entry=Reset_Handler - -specs=nano.specs - -specs=nosys.specs + -specs=picolibc.specs + -mthumb LINKER:-check-sections LINKER:-fatal-warnings LINKER:--gc-sections diff --git a/toolchain_GNUARM.cmake b/toolchain_GNUARM.cmake index 4be140048d..99ce2cb0b2 100644 --- a/toolchain_GNUARM.cmake +++ b/toolchain_GNUARM.cmake @@ -107,8 +107,7 @@ if(GCC_VERSION VERSION_GREATER_EQUAL "8.0.0") endif() add_compile_options( - -specs=nano.specs - -specs=nosys.specs + -specs=picolibc.specs -Wall -Wno-format -Wno-array-parameter @@ -147,8 +146,8 @@ endif() add_link_options( --entry=Reset_Handler - -specs=nano.specs - -specs=nosys.specs + -specs=picolibc.specs + -mthumb LINKER:-check-sections LINKER:-fatal-warnings LINKER:--gc-sections From e9b741272ff1bf36ad638daa2a52f49eb6eded49 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Jul 2025 17:10:35 -0700 Subject: [PATCH 2/2] ld: Reset linker '.' value after .ER_CODE_SRAM section When processing the .ER_CODE_SRAM section, the location counter is set to the VMA of that section, so after processing the next section will use that VMA instead of the next available address in the FLASH region. Reset the location counter to the next available FLASH address after processing this section will ensure that any subsequent FLASH data is placed in the correct location. This test fails without this patch: $ west build -p -b lpcxpresso55s69/lpc55s69/cpu0/ns \ samples/synchronization -T sample.kernel.synchronization .../ld: address 0x14003e84 of bin/tfm_s.axf section `.ER_TFM_CODE' is not within region `FLASH' .../ld: address 0x14005c20 of bin/tfm_s.axf section `.TFM_UNPRIV_CODE' is not within region `FLASH' .../ld: bin/tfm_s.axf section `.TFM_PSA_ROT_LINKER_DATA' will not fit in region `FLASH' .../ld: address 0x14003e84 of bin/tfm_s.axf section `.ER_TFM_CODE' is not within region `FLASH' .../ld: address 0x14005c20 of bin/tfm_s.axf section `.TFM_UNPRIV_CODE' is not within region `FLASH' .../ld: ERROR: CMSE stub (.gnu.sgstubs section) too far (0x10008540) from destination (0x14003ee4) Note that the linker is generating addresses within the CODE_RAM memory region rather than the FLASH region. Signed-off-by: Keith Packard --- platform/ext/common/gcc/tfm_common_s.ld.template | 3 +++ platform/ext/common/gcc/tfm_isolation_s.ld.template | 3 +++ platform/ext/common/llvm/tfm_isolation_s.ld.template | 3 +++ .../ext/target/arm/musca_b1/Device/Source/gcc/musca_bl2.ld | 4 ++++ .../ext/target/arm/musca_b1/Device/Source/llvm/musca_bl2.ld | 4 ++++ platform/ext/target/rpi/rp2350/linker_s.ld | 3 +++ 6 files changed, 20 insertions(+) diff --git a/platform/ext/common/gcc/tfm_common_s.ld.template b/platform/ext/common/gcc/tfm_common_s.ld.template index a508c08271..a5e92fbd72 100644 --- a/platform/ext/common/gcc/tfm_common_s.ld.template +++ b/platform/ext/common/gcc/tfm_common_s.ld.template @@ -192,6 +192,9 @@ SECTIONS . = ALIGN(4); /* This alignment is needed to make the section size 4 bytes aligned */ } > CODE_RAM AT > FLASH + /* Reset current position for subsequent sections */ + . = LOADADDR(.ER_CODE_SRAM) + SIZEOF(.ER_CODE_SRAM); + 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); diff --git a/platform/ext/common/gcc/tfm_isolation_s.ld.template b/platform/ext/common/gcc/tfm_isolation_s.ld.template index 9a654975a4..6031a361d2 100644 --- a/platform/ext/common/gcc/tfm_isolation_s.ld.template +++ b/platform/ext/common/gcc/tfm_isolation_s.ld.template @@ -337,6 +337,9 @@ SECTIONS . = ALIGN(4); /* This alignment is needed to make the section size 4 bytes aligned */ } > CODE_RAM AT > FLASH + /* Reset current position for subsequent sections */ + . = LOADADDR(.ER_CODE_SRAM) + SIZEOF(.ER_CODE_SRAM); + 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); diff --git a/platform/ext/common/llvm/tfm_isolation_s.ld.template b/platform/ext/common/llvm/tfm_isolation_s.ld.template index b5a4588c4d..21f77c913e 100644 --- a/platform/ext/common/llvm/tfm_isolation_s.ld.template +++ b/platform/ext/common/llvm/tfm_isolation_s.ld.template @@ -303,6 +303,9 @@ SECTIONS . = ALIGN(4); /* This alignment is needed to make the section size 4 bytes aligned */ } > CODE_RAM AT > FLASH + /* Reset current position for subsequent sections */ + . = LOADADDR(.ER_CODE_SRAM) + SIZEOF(.ER_CODE_SRAM); + 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); diff --git a/platform/ext/target/arm/musca_b1/Device/Source/gcc/musca_bl2.ld b/platform/ext/target/arm/musca_b1/Device/Source/gcc/musca_bl2.ld index c0878d790c..46c46eb626 100644 --- a/platform/ext/target/arm/musca_b1/Device/Source/gcc/musca_bl2.ld +++ b/platform/ext/target/arm/musca_b1/Device/Source/gcc/musca_bl2.ld @@ -58,6 +58,10 @@ SECTIONS *libflash_drivers.o(.rodata*) . = ALIGN(4); /* This alignment is needed to make the section size 4 bytes aligned */ } > CODE_RAM AT > FLASH + + /* Reset current position for subsequent sections */ + . = LOADADDR(.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); diff --git a/platform/ext/target/arm/musca_b1/Device/Source/llvm/musca_bl2.ld b/platform/ext/target/arm/musca_b1/Device/Source/llvm/musca_bl2.ld index 09aef8d9c6..2cf14e0511 100644 --- a/platform/ext/target/arm/musca_b1/Device/Source/llvm/musca_bl2.ld +++ b/platform/ext/target/arm/musca_b1/Device/Source/llvm/musca_bl2.ld @@ -57,6 +57,10 @@ SECTIONS *libflash_drivers.o(.rodata*) . = ALIGN(4); /* This alignment is needed to make the section size 4 bytes aligned */ } > CODE_RAM AT > FLASH + + /* Reset current position for subsequent sections */ + . = LOADADDR(.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); diff --git a/platform/ext/target/rpi/rp2350/linker_s.ld b/platform/ext/target/rpi/rp2350/linker_s.ld index 084b1fc67c..fad054fa91 100644 --- a/platform/ext/target/rpi/rp2350/linker_s.ld +++ b/platform/ext/target/rpi/rp2350/linker_s.ld @@ -150,6 +150,9 @@ SECTIONS . = ALIGN(4); /* This alignment is needed to make the section size 4 bytes aligned */ } > CODE_RAM AT > FLASH + /* Reset current position for subsequent sections */ + . = LOADADDR(.ER_CODE_SRAM) + SIZEOF(.ER_CODE_SRAM); + 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);