1 /*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
4 *
5 */
6
7 #include "pico/runtime.h"
8 #include "pico/runtime_init.h"
9 #include "hardware/structs/scb.h"
10 #ifdef PSA_API_TEST_CRYPTO
11 #include "hardware/ticks.h"
12 #include "hardware/clocks.h"
13 #endif
14
15 #include "stdint.h"
16
17 /* Do not use __cmsis_start */
18 #define __PROGRAM_START
19 #include "tfm_hal_device_header.h"
20
copy_zero_tables(void)21 void copy_zero_tables(void) {
22 typedef struct {
23 uint32_t const* src;
24 uint32_t* dest;
25 uint32_t wlen;
26 } __copy_table_t;
27
28 typedef struct {
29 uint32_t* dest;
30 uint32_t wlen;
31 } __zero_table_t;
32
33 extern const __copy_table_t __copy_table_start__;
34 extern const __copy_table_t __copy_table_end__;
35 extern const __zero_table_t __zero_table_start__;
36 extern const __zero_table_t __zero_table_end__;
37
38 for (__copy_table_t const* pTable = &__copy_table_start__; pTable < &__copy_table_end__; ++pTable) {
39 for(uint32_t i=0u; i<pTable->wlen; ++i) {
40 pTable->dest[i] = pTable->src[i];
41 }
42 }
43
44 for (__zero_table_t const* pTable = &__zero_table_start__; pTable < &__zero_table_end__; ++pTable) {
45 for(uint32_t i=0u; i<pTable->wlen; ++i) {
46 pTable->dest[i] = 0u;
47 }
48 }
49 }
50
hard_assertion_failure(void)51 void hard_assertion_failure(void) {
52 SPM_ASSERT(0);
53 }
54
runtime_run_initializers_from(uintptr_t * from)55 static void runtime_run_initializers_from(uintptr_t *from) {
56
57 /* Start and end points of the constructor list, defined by the linker script. */
58 extern uintptr_t __preinit_array_end;
59
60 /* Call each function in the list, based on the mask
61 We have to take the address of the symbols, as __preinit_array_start *is*
62 the first function value, not the address of it. */
63 for (uintptr_t *p = from; p < &__preinit_array_end; p++) {
64 uintptr_t val = *p;
65 ((void (*)(void))val)();
66 }
67 }
68
runtime_run_initializers(void)69 void runtime_run_initializers(void) {
70 extern uintptr_t __preinit_array_start;
71 runtime_run_initializers_from(&__preinit_array_start);
72 }
73
74 /* We keep the per-core initializers in the standard __preinit_array so a standard C library
75 initialization will fo the core 0 initialization, however we also want to be able to find
76 them after the fact so that we can run them on core 1. Per core initializers have sections
77 __preinit_array.ZZZZZ.nnnnn i.e. the ZZZZZ sorts below all the standard __preinit_array.nnnnn
78 values, and then we sort within the ZZZZZ.
79
80 We create a dummy initializer in __preinit_array.YYYYY (between the standard initializers
81 and the per core initializers), so we find the first per core initializer. Whilst we could
82 have done this via an entry in the linker script, we want to preserve backwards compatibility
83 with RP2040 custom linker scripts. */
first_per_core_initializer(void)84 static void first_per_core_initializer(void) {}
85 PICO_RUNTIME_INIT_FUNC(first_per_core_initializer, "YYYYY");
86
runtime_run_per_core_initializers(void)87 void runtime_run_per_core_initializers(void) {
88 runtime_run_initializers_from(&__pre_init_first_per_core_initializer);
89 }
90
91 extern uint32_t __vectors_start__;
92 extern uint32_t __INITIAL_SP;
93 extern uint32_t __STACK_LIMIT;
94 extern uint64_t __STACK_SEAL;
95
runtime_init(void)96 void runtime_init(void) {
97 scb_hw->vtor = (uintptr_t) &__vectors_start__;
98 copy_zero_tables();
99
100 __disable_irq();
101 __set_PSP((uint32_t)(&__INITIAL_SP));
102
103 __set_MSPLIM((uint32_t)(&__STACK_LIMIT));
104 __set_PSPLIM((uint32_t)(&__STACK_LIMIT));
105
106 __TZ_set_STACKSEAL_S((uint32_t *)(&__STACK_SEAL));
107
108 runtime_run_initializers();
109
110 #ifdef PSA_API_TEST_CRYPTO
111 /* RSA Key generation test takes very long. Use 4 times slower WD
112 reference tick when it is enabled. */
113 tick_start(TICK_WATCHDOG, 4 * clock_get_hz(clk_ref) / MHZ);
114 #endif
115
116 SystemInit();
117 }
118