1 /*
2  * Copyright (c) 2019-2022, 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 MEASURED_BOOT_API
21 #include "region_defs.h"
22 #include "tfm_boot_status.h"
23 #include "boot_measurement.h"
24 #endif /* 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)&REGION_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 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 /* MEASURED_BOOT_API */
350