1 /*
2 * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include <string.h>
9 #include "target_cfg.h"
10 #include "region.h"
11 #include "tfm_hal_device_header.h"
12 #include "boot_hal.h"
13 #include "Driver_Flash.h"
14 #include "flash_layout.h"
15 #include "region_defs.h"
16 #include "uart_stdout.h"
17 #include "fih.h"
18
19 #ifdef TFM_MEASURED_BOOT_API
20 #include "region_defs.h"
21 #include "tfm_boot_status.h"
22 #include "boot_measurement.h"
23 #endif /* TFM_MEASURED_BOOT_API */
24
25 #ifndef TFM_BL1_MEMORY_MAPPED_FLASH
26 /* Flash device name must be specified by target */
27 extern ARM_DRIVER_FLASH FLASH_DEV_NAME_BL1;
28 #endif /* !TFM_BL1_MEMORY_MAPPED_FLASH */
29
30 REGION_DECLARE(Image$$, ER_DATA, $$Base)[];
31 REGION_DECLARE(Image$$, ARM_LIB_HEAP, $$ZI$$Limit)[];
32 #if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) \
33 || defined(__ARM_ARCH_8_1M_MAIN__)
34 REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Base);
35 #endif /* defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) \
36 || defined(__ARM_ARCH_8_1M_MAIN__) */
37
38 #if defined(__ICCARM__)
39 REGION_DECLARE(Image$$, BL1_1_ER_DATA, $$Base)[];
40 REGION_DECLARE(Image$$, BL1_1_ER_DATA, $$Limit)[];
41 REGION_DECLARE(Image$$, BL1_2_ER_DATA, $$Base)[];
42 REGION_DECLARE(Image$$, BL1_2_ER_DATA, $$Limit)[];
43 #else
44 REGION_DECLARE(Image$$, BL1_1_ER_DATA_START, $$Base)[];
45 REGION_DECLARE(Image$$, BL1_1_ER_DATA_LIMIT, $$Base)[];
46 REGION_DECLARE(Image$$, BL1_2_ER_DATA_START, $$Base)[];
47 REGION_DECLARE(Image$$, BL1_2_ER_DATA_LIMIT, $$Base)[];
48 #endif
49 /* Erase both BL1 data sections at the end of BL1_2
50 * At the point this function is called, the SP has been set to the next image's
51 * initial SP and this function itself will wipe the executing image's data
52 * region. Therefore, to avoid using any stack or static memory, this function
53 * is implemented as a naked function using only assembly.
54 */
boot_clear_ram_area(void)55 __WEAK __attribute__((naked)) void boot_clear_ram_area(void)
56 {
57 __ASM volatile(
58 #if !defined(__ICCARM__)
59 ".syntax unified \n"
60 #endif
61 /* Clear the entire BL1_1 data section */
62 "movs r0, #0 \n"
63 #if defined(__ICCARM__)
64 "ldr r1, =BL1_1_ER_DATA$$Base \n"
65 "ldr r2, =BL1_1_ER_DATA$$Limit \n"
66 #else
67 "ldr r1, =Image$$BL1_1_ER_DATA_START$$Base \n"
68 "ldr r2, =Image$$BL1_1_ER_DATA_LIMIT$$Base \n"
69 #endif
70 "subs r2, r2, r1 \n"
71 "Loop_1: \n"
72 "subs r2, #4 \n"
73 "blt Clear_done_1 \n"
74 "str r0, [r1, r2] \n"
75 "b Loop_1 \n"
76 "Clear_done_1: \n"
77 /* Clear the entire BL1_2 data section */
78 "movs r0, #0 \n"
79 #if defined(__ICCARM__)
80 "ldr r1, =BL1_2_ER_DATA$$Base \n"
81 "ldr r2, =BL1_2_ER_DATA$$Limit \n"
82 #else
83 "ldr r1, =Image$$BL1_2_ER_DATA_START$$Base \n"
84 "ldr r2, =Image$$BL1_2_ER_DATA_LIMIT$$Base \n"
85 #endif
86 "subs r2, r2, r1 \n"
87 "Loop_2: \n"
88 "subs r2, #4 \n"
89 "blt Clear_done_2 \n"
90 "str r0, [r1, r2] \n"
91 "b Loop_2 \n"
92 "Clear_done_2: \n"
93 "bx lr \n"
94 :
95 :
96 : "r0" , "r1" , "r2" , "memory"
97 );
98 }
99
100 /*!
101 * \brief Chain-loading the next image in the boot sequence.
102 *
103 * This function calls the Reset_Handler of the next image in the boot sequence,
104 * usually it is the secure firmware. Before passing the execution to next image
105 * there is conditional rule to remove the secrets from the memory. This must be
106 * done if the following conditions are satisfied:
107 * - Memory is shared between SW components at different stages of the trusted
108 * boot process.
109 * - There are secrets in the memory: KDF parameter, symmetric key,
110 * manufacturer sensitive code/data, etc.
111 */
112 #if defined(__ICCARM__)
113 #pragma required = boot_clear_ram_area
114 #endif
115
boot_jump_to_next_image(uint32_t reset_handler_addr)116 __WEAK __attribute__((naked)) void boot_jump_to_next_image(uint32_t reset_handler_addr)
117 {
118 __ASM volatile(
119 #if !defined(__ICCARM__)
120 ".syntax unified \n"
121 #endif
122 "mov r7, r0 \n"
123 "bl boot_clear_ram_area \n" /* Clear RAM before jump */
124 "movs r0, #0 \n" /* Clear registers: R0-R12, */
125 "mov r1, r0 \n" /* except R7 */
126 "mov r2, r0 \n"
127 "mov r3, r0 \n"
128 "mov r4, r0 \n"
129 "mov r5, r0 \n"
130 "mov r6, r0 \n"
131 "mov r8, r0 \n"
132 "mov r9, r0 \n"
133 "mov r10, r0 \n"
134 "mov r11, r0 \n"
135 "mov r12, r0 \n"
136 "mov lr, r0 \n"
137 "bx r7 \n" /* Jump to Reset_handler */
138 );
139 }
140
141 /* bootloader platform-specific hw initialization */
boot_platform_init(void)142 __WEAK int32_t boot_platform_init(void)
143 {
144 #if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) \
145 || defined(__ARM_ARCH_8_1M_MAIN__)
146 /* Initialize stack limit register */
147 uint32_t msp_stack_bottom =
148 (uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Base);
149
150 __set_MSPLIM(msp_stack_bottom);
151 #endif /* defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) \
152 || defined(__ARM_ARCH_8_1M_MAIN__) */
153
154 #if defined(TFM_BL1_LOGGING) || defined(TEST_BL1_1) || defined(TEST_BL1_2)
155 stdio_init();
156 #endif /* defined(TFM_BL1_LOGGING) || defined(TEST_BL1_1) || defined(TEST_BL1_2) */
157
158 #ifndef TFM_BL1_MEMORY_MAPPED_FLASH
159 if (FLASH_DEV_NAME_BL1.Initialize(NULL) != ARM_DRIVER_OK) {
160 return 1;
161 }
162 #endif /* !TFM_BL1_MEMORY_MAPPED_FLASH */
163
164 return 0;
165 }
166
boot_platform_post_init(void)167 __WEAK int32_t boot_platform_post_init(void)
168 {
169 return 0;
170 }
171
boot_platform_quit(struct boot_arm_vector_table * vt)172 __WEAK void boot_platform_quit(struct boot_arm_vector_table *vt)
173 {
174 /* Clang at O0, stores variables on the stack with SP relative addressing.
175 * When manually set the SP then the place of reset vector is lost.
176 * Static variables are stored in 'data' or 'bss' section, change of SP has
177 * no effect on them.
178 */
179 static struct boot_arm_vector_table *vt_cpy;
180
181 #ifndef TFM_BL1_MEMORY_MAPPED_FLASH
182 if (FLASH_DEV_NAME_BL1.Uninitialize() != ARM_DRIVER_OK) {
183 while (1){}
184 }
185 #endif /* !TFM_BL1_MEMORY_MAPPED_FLASH */
186
187 #if defined(TFM_BL1_LOGGING) || defined(TEST_BL1_1) || defined(TEST_BL1_2)
188 stdio_uninit();
189 #endif /* defined(TFM_BL1_LOGGING) || defined(TEST_BL1_1) || defined(TEST_BL1_2) */
190
191 vt_cpy = vt;
192 #if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) \
193 || defined(__ARM_ARCH_8_1M_MAIN__)
194 /* Restore the Main Stack Pointer Limit register's reset value
195 * before passing execution to runtime firmware to make the
196 * bootloader transparent to it.
197 */
198 __set_MSPLIM(0);
199 #endif /* defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) \
200 || defined(__ARM_ARCH_8_1M_MAIN__) */
201
202 __set_MSP(vt_cpy->msp);
203 __DSB();
204 __ISB();
205
206 boot_jump_to_next_image(vt_cpy->reset);
207 }
208
boot_platform_pre_load(uint32_t image_id)209 __WEAK int boot_platform_pre_load(uint32_t image_id)
210 {
211 return 0;
212 }
213
boot_platform_post_load(uint32_t image_id)214 __WEAK int boot_platform_post_load(uint32_t image_id)
215 {
216 return 0;
217 }
218
219 #ifdef TFM_MEASURED_BOOT_API
boot_add_data_to_shared_area(uint8_t major_type,uint16_t minor_type,size_t size,const uint8_t * data)220 static int boot_add_data_to_shared_area(uint8_t major_type,
221 uint16_t minor_type,
222 size_t size,
223 const uint8_t *data)
224 {
225 struct shared_data_tlv_entry tlv_entry = {0};
226 struct tfm_boot_data *boot_data;
227 uintptr_t tlv_end, offset;
228
229 if (data == NULL) {
230 return -1;
231 }
232
233 boot_data = (struct tfm_boot_data *)BOOT_TFM_SHARED_DATA_BASE;
234
235 /* Check whether the shared area needs to be initialized. */
236 if ((boot_data->header.tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) ||
237 (boot_data->header.tlv_tot_len > BOOT_TFM_SHARED_DATA_SIZE)) {
238
239 memset((void *)BOOT_TFM_SHARED_DATA_BASE, 0, BOOT_TFM_SHARED_DATA_SIZE);
240 boot_data->header.tlv_magic = SHARED_DATA_TLV_INFO_MAGIC;
241 boot_data->header.tlv_tot_len = SHARED_DATA_HEADER_SIZE;
242 }
243
244 /* Get the boundaries of TLV section. */
245 tlv_end = BOOT_TFM_SHARED_DATA_BASE + boot_data->header.tlv_tot_len;
246 offset = BOOT_TFM_SHARED_DATA_BASE + SHARED_DATA_HEADER_SIZE;
247
248 /* Check whether TLV entry is already added. Iterates over the TLV section
249 * looks for the same entry if found then returns with error.
250 */
251 while (offset < tlv_end) {
252 /* Create local copy to avoid unaligned access */
253 memcpy(&tlv_entry, (const void *)offset, SHARED_DATA_ENTRY_HEADER_SIZE);
254 if (GET_MAJOR(tlv_entry.tlv_type) == major_type &&
255 GET_MINOR(tlv_entry.tlv_type) == minor_type) {
256 return -1;
257 }
258
259 offset += SHARED_DATA_ENTRY_SIZE(tlv_entry.tlv_len);
260 }
261
262 /* Add TLV entry. */
263 tlv_entry.tlv_type = SET_TLV_TYPE(major_type, minor_type);
264 tlv_entry.tlv_len = size;
265
266 /* Check integer overflow and overflow of shared data area. */
267 if (SHARED_DATA_ENTRY_SIZE(size) >
268 (UINT16_MAX - boot_data->header.tlv_tot_len)) {
269 return -1;
270 } else if ((SHARED_DATA_ENTRY_SIZE(size) + boot_data->header.tlv_tot_len) >
271 BOOT_TFM_SHARED_DATA_SIZE) {
272 return -1;
273 }
274
275 offset = tlv_end;
276 memcpy((void *)offset, &tlv_entry, SHARED_DATA_ENTRY_HEADER_SIZE);
277
278 offset += SHARED_DATA_ENTRY_HEADER_SIZE;
279 memcpy((void *)offset, data, size);
280
281 boot_data->header.tlv_tot_len += SHARED_DATA_ENTRY_SIZE(size);
282
283 return 0;
284 }
285
boot_store_measurement(uint8_t index,const uint8_t * measurement,size_t measurement_size,const struct boot_measurement_metadata * metadata,bool lock_measurement)286 __WEAK int boot_store_measurement(
287 uint8_t index,
288 const uint8_t *measurement,
289 size_t measurement_size,
290 const struct boot_measurement_metadata *metadata,
291 bool lock_measurement)
292 {
293 uint16_t minor_type;
294 uint8_t claim;
295 int rc;
296
297 if (index >= BOOT_MEASUREMENT_SLOT_MAX) {
298 return -1;
299 }
300
301 minor_type = SET_MBS_MINOR(index, SW_MEASURE_METADATA);
302 rc = boot_add_data_to_shared_area(TLV_MAJOR_MBS,
303 minor_type,
304 sizeof(struct boot_measurement_metadata),
305 (const uint8_t *)metadata);
306 if (rc) {
307 return rc;
308 }
309
310 claim = lock_measurement ? SW_MEASURE_VALUE_NON_EXTENDABLE
311 : SW_MEASURE_VALUE;
312 minor_type = SET_MBS_MINOR(index, claim);
313 rc = boot_add_data_to_shared_area(TLV_MAJOR_MBS,
314 minor_type,
315 measurement_size,
316 measurement);
317
318 return rc;
319 }
320 #endif /* TFM_MEASURED_BOOT_API */
321
boot_initiate_recovery_mode(uint32_t image_id)322 __WEAK int boot_initiate_recovery_mode(uint32_t image_id)
323 {
324 (void)image_id;
325
326 /* We haven't done anything, therefore recovery has failed */
327 return 1;
328 }
329