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