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)&REGION_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