Skip to content

Commit a73e0d7

Browse files
committed
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 <[email protected]>
1 parent 68dbad6 commit a73e0d7

File tree

14 files changed

+349
-36
lines changed

14 files changed

+349
-36
lines changed

platform/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ target_sources(platform_s
9090
target_sources(tfm_s
9191
PRIVATE
9292
ext/common/faults.c
93+
ext/common/picolibc.c
9394
)
9495

9596
target_link_libraries(platform_s

platform/ext/common/gcc/tfm_common_bl2.ld

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,26 @@ SECTIONS
153153
} > RAM AT > FLASH
154154
Image$$ER_DATA$$Base = ADDR(.data);
155155

156+
.tdata : ALIGN_WITH_INPUT
157+
{
158+
*(.tdata .tdata.* .gnu.linkonce.td.*)
159+
PROVIDE( __data_end = . );
160+
PROVIDE( __tdata_end = . );
161+
} >RAM AT>FLASH
162+
163+
.tbss (NOLOAD) :
164+
{
165+
*(.tbss .tbss.* .gnu.linkonce.tb.*)
166+
*(.tcommon)
167+
PROVIDE( __tls_end = . );
168+
PROVIDE( __tbss_end = . );
169+
} >RAM AT>RAM
170+
171+
.tbss_space (NOLOAD) : {
172+
. = ADDR(.tbss);
173+
. = . + SIZEOF(.tbss);
174+
} >RAM AT>RAM
175+
156176
.bss : ALIGN(4)
157177
{
158178
. = ALIGN(4);
@@ -163,6 +183,16 @@ SECTIONS
163183
__bss_end__ = .;
164184
} > RAM
165185

186+
PROVIDE( __bss_end = __bss_end__ );
187+
PROVIDE( __data_start = ADDR(.data) );
188+
PROVIDE( __data_source = LOADADDR(.data) );
189+
PROVIDE( __data_size = __data_end - __data_start );
190+
PROVIDE( __tls_base = SIZEOF(.tdata) ? ADDR(.tdata) : ADDR(.tbss) );
191+
PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
192+
PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
193+
PROVIDE( __bss_start = ADDR(.tbss));
194+
PROVIDE( __bss_size = __bss_end - __bss_start );
195+
166196
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
167197
.msp_stack (NOLOAD) : ALIGN(32)
168198
{
@@ -200,4 +230,6 @@ SECTIONS
200230
Image$$ARM_LIB_HEAP$$ZI$$Limit = ADDR(.heap) + SIZEOF(.heap);
201231

202232
PROVIDE(__stack = Image$$ARM_LIB_STACK$$ZI$$Limit);
233+
PROVIDE( __heap_start = __HeapBase );
234+
PROVIDE( __heap_end = __HeapLimit );
203235
}

platform/ext/common/gcc/tfm_common_ns.ld

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,22 +128,51 @@ SECTIONS
128128

129129
KEEP(*(.jcr*))
130130
. = ALIGN(4);
131-
/* All data end */
132-
__data_end__ = .;
133131

134132
} > RAM
135133

136-
.bss :
134+
.tdata : AT (__etext + SIZEOF(.data))
135+
{
136+
*(.tdata .tdata.* .gnu.linkonce.td.*)
137+
PROVIDE( __data_end = . );
138+
PROVIDE( __data_end__ = . );
139+
PROVIDE( __tdata_end = . );
140+
} > RAM
141+
142+
.tbss (NOLOAD) :
137143
{
138144
. = ALIGN(4);
139145
__bss_start__ = .;
146+
*(.tbss .tbss.* .gnu.linkonce.tb.*)
147+
*(.tcommon)
148+
PROVIDE( __tls_end = . );
149+
PROVIDE( __tbss_end = . );
150+
} > RAM
151+
152+
.tbss_space (NOLOAD) :
153+
{
154+
. = ADDR(.tbss);
155+
. = . + SIZEOF(.tbss);
156+
} > RAM
157+
158+
.bss :
159+
{
160+
. = ALIGN(4);
140161
*(.bss*)
141162
*(COMMON)
142163
. = ALIGN(4);
143164
__bss_end__ = .;
144165
} > RAM
145166

146-
bss_size = __bss_end__ - __bss_start__;
167+
PROVIDE( __bss_end = __bss_end__ );
168+
PROVIDE( __data_start = ADDR(.data) );
169+
PROVIDE( __data_source = LOADADDR(.data) );
170+
PROVIDE( __data_size = __data_end - __data_start );
171+
PROVIDE( __bss_start = ADDR(.tbss) );
172+
PROVIDE( __bss_size = __bss_end - __bss_start );
173+
PROVIDE( __tls_base = SIZEOF(.tdata) ? ADDR(.tdata) : ADDR(.tbss) );
174+
PROVIDE( __tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)) );
175+
PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
147176

148177
.stack : ALIGN(32)
149178
{
@@ -164,4 +193,6 @@ SECTIONS
164193
} > RAM
165194

166195
PROVIDE(__stack = __StackTop);
196+
PROVIDE( __heap_start = __HeapBase );
197+
PROVIDE( __heap_end = __HeapLimit );
167198
}

platform/ext/common/gcc/tfm_common_s.ld.template

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -576,13 +576,35 @@ SECTIONS
576576
. = ALIGN(4);
577577

578578
} > RAM AT> FLASH
579+
580+
.TFM_TDATA : ALIGN_WITH_INPUT
581+
{
582+
*(.tdata .tdata.* .gnu.linkonce.td.*)
583+
PROVIDE( __data_end = . );
584+
PROVIDE( __tdata_end = . );
585+
} > RAM AT> FLASH
586+
579587
Image$$ER_TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
580-
Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
588+
Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_TDATA) + SIZEOF(.TFM_TDATA);
581589

582-
.TFM_BSS ALIGN(4) (NOLOAD) :
590+
.TFM_TBSS (NOLOAD) :
583591
{
584592
__bss_start__ = .;
585593

594+
*(.tbss .tbss.* .gnu.linkonce.tb.*)
595+
*(.tcommon)
596+
PROVIDE( __tls_end = . );
597+
PROVIDE( __tbss_end = . );
598+
} > RAM AT> RAM
599+
600+
.TFM_TBSS_SPACE (NOLOAD) :
601+
{
602+
. = ADDR(.TFM_TBSS);
603+
. = . + SIZEOF(.TFM_TBSS);
604+
} > RAM AT> RAM
605+
606+
.TFM_BSS ALIGN(4) (NOLOAD) :
607+
{
586608
/* The runtime partition placed order is same as load partition */
587609
__partition_runtime_start__ = .;
588610
KEEP(*(.bss.part_runtime_priority_00))
@@ -603,16 +625,26 @@ SECTIONS
603625
*(COMMON)
604626
. = ALIGN(4);
605627
__bss_end__ = .;
628+
__bss_end = .;
606629
} > RAM AT> RAM
607-
Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
630+
Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_TBSS);
608631
Image$$ER_TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
609632
Image$$ER_PART_RT_POOL$$ZI$$Base = __partition_runtime_start__;
610633
Image$$ER_PART_RT_POOL$$ZI$$Limit = __partition_runtime_end__;
611634
Image$$ER_SERV_RT_POOL$$ZI$$Base = __service_runtime_start__;
612635
Image$$ER_SERV_RT_POOL$$ZI$$Limit = __service_runtime_end__;
613636

614637
Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA);
615-
Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS);
638+
Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
639+
640+
PROVIDE( __data_start = ADDR(.TFM_DATA) );
641+
PROVIDE( __data_source = LOADADDR(.TFM_DATA) );
642+
PROVIDE( __data_size = __data_end - __data_start );
643+
PROVIDE( __bss_start = ADDR(.TFM_TBSS) );
644+
PROVIDE( __bss_size = __bss_end - __bss_start );
645+
PROVIDE( __tls_base = SIZEOF(.TFM_TDATA) ? ADDR(.TFM_TDATA) : ADDR(.TFM_TBSS) );
646+
PROVIDE( __tls_align = MAX(ALIGNOF(.TFM_TDATA), ALIGNOF(.TFM_TBSS)) );
647+
PROVIDE(__arm32_tls_tcb_offset = MAX(8, __tls_align) );
616648

617649
#if defined(CONFIG_TFM_USE_TRUSTZONE)
618650
Image$$ER_VENEER$$Base = ADDR(.gnu.sgstubs);

platform/ext/common/gcc/tfm_isolation_s.ld.template

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,20 +210,22 @@ SECTIONS
210210
. = ALIGN(4);
211211
/* preinit data */
212212
PROVIDE_HIDDEN (__preinit_array_start = .);
213+
PROVIDE_HIDDEN (__bothinit_array_start = .);
213214
KEEP(*(.preinit_array))
214215
PROVIDE_HIDDEN (__preinit_array_end = .);
215216

216217
. = ALIGN(4);
217218
/* init data */
218219
PROVIDE_HIDDEN (__init_array_start = .);
219-
KEEP(*(SORT(.init_array.*)))
220+
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)))
220221
KEEP(*(.init_array))
221222
PROVIDE_HIDDEN (__init_array_end = .);
223+
PROVIDE_HIDDEN (__bothinit_array_end = .);
222224

223225
. = ALIGN(4);
224226
/* finit data */
225227
PROVIDE_HIDDEN (__fini_array_start = .);
226-
KEEP(*(SORT(.fini_array.*)))
228+
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*)))
227229
KEEP(*(.fini_array))
228230
PROVIDE_HIDDEN (__fini_array_end = .);
229231

@@ -251,6 +253,10 @@ SECTIONS
251253
LONG (ADDR(.ER_CODE_SRAM))
252254
LONG (SIZEOF(.ER_CODE_SRAM) / 4)
253255
#endif
256+
LONG (LOADADDR(.TFM_TDATA))
257+
LONG (ADDR(.TFM_TLS_BASE))
258+
LONG (SIZEOF(.TFM_TDATA) / 4)
259+
254260
__copy_table_end__ = .;
255261

256262
/* .zero.table */
@@ -265,6 +271,10 @@ SECTIONS
265271
LONG (ADDR(.TFM_SP_META_PTR))
266272
LONG (SIZEOF(.TFM_SP_META_PTR) / 4)
267273
#endif
274+
275+
LONG (ADDR(.TFM_TLS_BASE) + SIZEOF(.TFM_TDATA))
276+
LONG ((SIZEOF(.TFM_TLS_BASE) - SIZEOF(.TFM_TDATA)) / 4)
277+
268278
__zero_table_end__ = .;
269279

270280
/* Capture all remaining code (except RAM code) in the privileged TF-M
@@ -552,6 +562,10 @@ SECTIONS
552562
. = ALIGN(4);
553563
} > RAM AT > FLASH
554564

565+
PROVIDE(__data_source = LOADADDR(.TFM_DATA));
566+
PROVIDE(__data_start = ADDR(.TFM_DATA));
567+
PROVIDE(__data_size = SIZEOF(.TFM_DATA));
568+
555569
.TFM_BSS ALIGN(4) (NOLOAD) :
556570
{
557571
__bss_start__ = .;
@@ -577,6 +591,31 @@ SECTIONS
577591
. = ALIGN(4);
578592
__bss_end__ = .;
579593
} > RAM
594+
595+
PROVIDE(__bss_start = ADDR(.TFM_BSS));
596+
PROVIDE(__bss_size = SIZEOF(.TFM_BSS));
597+
598+
.TFM_TDATA :
599+
{
600+
PROVIDE( __tls_start_addr = . );
601+
*(.tdata .tdata.* .gnu.linkonce.td.*)
602+
} > RAM
603+
604+
.TFM_TBSS :
605+
{
606+
*(.tbss .tbss.* .gnu.linkonce.tb.*)
607+
*(.tcommon)
608+
PROVIDE( __tls_end_addr = . );
609+
} > RAM
610+
611+
.TFM_TLS_BASE : {
612+
. = . + (__tls_end_addr - __tls_start_addr);
613+
} > RAM
614+
PROVIDE( __tls_base = ADDR(.TFM_TLS_BASE) );
615+
PROVIDE( __tls_align = MAX(ALIGNOF(.TFM_TDATA), ALIGNOF(.TFM_TBSS)) );
616+
PROVIDE( __arm32_tls_tcb_offset = MAX(8, __tls_align) );
617+
PROVIDE( __arm64_tls_tcb_offset = MAX(16, __tls_align) );
618+
580619
Image$$ER_PART_RT_POOL$$ZI$$Base = __partition_runtime_start__;
581620
Image$$ER_PART_RT_POOL$$ZI$$Limit = __partition_runtime_end__;
582621
Image$$ER_SERV_RT_POOL$$ZI$$Base = __service_runtime_start__;

platform/ext/common/picolibc.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright © 2025, Keith Packard <[email protected]>
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*
6+
*/
7+
8+
#include <stdint.h>
9+
#include <string.h>
10+
#include "config_impl.h"
11+
12+
/*
13+
* Picolibc's startup code only initializes a single data and bss
14+
* segment. Augment that by initializing the remaining segments using
15+
* the lists provided by the linker script in a constructor which will
16+
* be called from _start
17+
*/
18+
19+
#if defined(__PICOLIBC__) && TFM_ISOLATION_LEVEL > 0
20+
21+
static void __attribute__((constructor))
22+
picolibc_startup(void)
23+
{
24+
typedef struct __copy_table {
25+
uint32_t const* src;
26+
uint32_t* dest;
27+
uint32_t wlen;
28+
} __copy_table_t;
29+
30+
typedef struct __zero_table {
31+
uint32_t* dest;
32+
uint32_t wlen;
33+
} __zero_table_t;
34+
35+
extern const __copy_table_t __copy_table_start__;
36+
extern const __copy_table_t __copy_table_end__;
37+
extern const __zero_table_t __zero_table_start__;
38+
extern const __zero_table_t __zero_table_end__;
39+
40+
for (__copy_table_t const* pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) {
41+
memcpy(pTable->dest, pTable->src, pTable->wlen << 2);
42+
}
43+
44+
for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) {
45+
memset(pTable->dest, 0, pTable->wlen << 2);
46+
}
47+
}
48+
#endif

platform/ext/common/syscalls_stub.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@
1414
#include <stddef.h>
1515
#include <stdint.h>
1616

17+
#ifdef __PICOLIBC__
18+
__attribute__((weak))
19+
void _exit(int status)
20+
{
21+
(void) status;
22+
for(;;);
23+
}
24+
#else
1725
__attribute__((weak))
1826
void _close(void)
1927
{
@@ -53,3 +61,5 @@ __attribute__((weak))
5361
void _write(void)
5462
{
5563
}
64+
65+
#endif /* !__PICOLIBC__ */

platform/ext/common/uart_stdout.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ int fputc(int ch, FILE *f)
8585
/* Redirect sdtio for PicoLib in LLVM toolchain
8686
as per https://github.com/picolibc/picolibc/blob/main/doc/os.md
8787
'fputch()' named intentionally different from 'fputc()' from picolib */
88-
#elif defined(__clang_major__)
88+
#elif defined(__PICOLIBC__)
8989

9090
int fputch(char ch, struct __file *f)
9191
{

0 commit comments

Comments
 (0)