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 "tfm_plat_otp.h"
18 #include "fih.h"
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 #ifndef TFM_BL1_MEMORY_MAPPED_FLASH
27 /* Flash device name must be specified by target */
28 extern ARM_DRIVER_FLASH FLASH_DEV_NAME_BL1;
29 #endif /* !TFM_BL1_MEMORY_MAPPED_FLASH */
30 
31 REGION_DECLARE(Image$$, ER_DATA, $$Base)[];
32 REGION_DECLARE(Image$$, ARM_LIB_HEAP, $$ZI$$Limit)[];
33 #if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) \
34  || defined(__ARM_ARCH_8_1M_MAIN__)
35 REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Base);
36 #endif /* defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) \
37        || defined(__ARM_ARCH_8_1M_MAIN__) */
38 
39 /*!
40  * \brief Chain-loading the next image in the boot sequence.
41  *
42  * This function calls the Reset_Handler of the next image in the boot sequence,
43  * usually it is the secure firmware. Before passing the execution to next image
44  * there is conditional rule to remove the secrets from the memory. This must be
45  * done if the following conditions are satisfied:
46  *  - Memory is shared between SW components at different stages of the trusted
47  *    boot process.
48  *  - There are secrets in the memory: KDF parameter, symmetric key,
49  *    manufacturer sensitive code/data, etc.
50  */
51 
boot_jump_to_next_image(uint32_t reset_handler_addr)52 __WEAK __attribute__((naked)) void boot_jump_to_next_image(uint32_t reset_handler_addr)
53 {
54     __ASM volatile(
55 #if !defined(__ICCARM__)
56         ".syntax unified                 \n"
57 #endif
58         "mov     r7, r0                  \n"
59         "movs    r0, #0                  \n" /* Clear registers: R0-R12, */
60         "mov     r1, r0                  \n" /* except R7 */
61         "mov     r2, r0                  \n"
62         "mov     r3, r0                  \n"
63         "mov     r4, r0                  \n"
64         "mov     r5, r0                  \n"
65         "mov     r6, r0                  \n"
66         "mov     r8, r0                  \n"
67         "mov     r9, r0                  \n"
68         "mov     r10, r0                 \n"
69         "mov     r11, r0                 \n"
70         "mov     r12, r0                 \n"
71         "mov     lr,  r0                 \n"
72         "bx      r7                      \n" /* Jump to Reset_handler */
73     );
74 }
75 
76 /* bootloader platform-specific hw initialization */
boot_platform_init(void)77 __WEAK int32_t boot_platform_init(void)
78 {
79     enum tfm_plat_err_t plat_err;
80 
81 #if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) \
82  || defined(__ARM_ARCH_8_1M_MAIN__)
83     /* Initialize stack limit register */
84     uint32_t msp_stack_bottom =
85             (uint32_t)&REGION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Base);
86 
87     __set_MSPLIM(msp_stack_bottom);
88 #endif /* defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) \
89        || defined(__ARM_ARCH_8_1M_MAIN__) */
90 
91 #if defined(TFM_BL1_LOGGING) || defined(TEST_BL1_1) || defined(TEST_BL1_2)
92     stdio_init();
93 #endif /* defined(TFM_BL1_LOGGING) || defined(TEST_BL1_1) || defined(TEST_BL1_2) */
94 
95     plat_err = tfm_plat_otp_init();
96     if (plat_err != TFM_PLAT_ERR_SUCCESS) {
97         return 1;
98     }
99 
100 #ifdef TFM_BL1_2_IN_FLASH
101     if (FLASH_DEV_NAME_BL1.Initialize(NULL) != ARM_DRIVER_OK) {
102         return 1;
103     }
104 #endif /* TFM_BL1_2_IN_FLASH */
105 
106     /* Clear boot data area */
107     memset((void*)BOOT_TFM_SHARED_DATA_BASE, 0, BOOT_TFM_SHARED_DATA_SIZE);
108 
109     return 0;
110 }
111 
boot_platform_post_init(void)112 __WEAK int32_t boot_platform_post_init(void)
113 {
114     return 0;
115 }
116 
boot_platform_quit(struct boot_arm_vector_table * vt)117 __WEAK void boot_platform_quit(struct boot_arm_vector_table *vt)
118 {
119     /* Clang at O0, stores variables on the stack with SP relative addressing.
120      * When manually set the SP then the place of reset vector is lost.
121      * Static variables are stored in 'data' or 'bss' section, change of SP has
122      * no effect on them.
123      */
124     static struct boot_arm_vector_table *vt_cpy;
125 
126 #ifdef TFM_BL1_2_IN_FLASH
127     if (FLASH_DEV_NAME_BL1.Uninitialize() != ARM_DRIVER_OK) {
128         while (1){}
129     }
130 #endif /* TFM_BL1_2_IN_FLASH */
131 
132 #if defined(TFM_BL1_LOGGING) || defined(TEST_BL1_1) || defined(TEST_BL1_2)
133     stdio_uninit();
134 #endif /* defined(TFM_BL1_LOGGING) || defined(TEST_BL1_1) || defined(TEST_BL1_2) */
135 
136     vt_cpy = vt;
137 #if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) \
138  || defined(__ARM_ARCH_8_1M_MAIN__)
139     /* Restore the Main Stack Pointer Limit register's reset value
140      * before passing execution to runtime firmware to make the
141      * bootloader transparent to it.
142      */
143     __set_MSPLIM(0);
144 #endif /* defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) \
145        || defined(__ARM_ARCH_8_1M_MAIN__) */
146 
147     __set_MSP(vt_cpy->msp);
148     __DSB();
149     __ISB();
150 
151     boot_jump_to_next_image(vt_cpy->reset);
152 }
153 
boot_platform_pre_load(uint32_t image_id)154 __WEAK int boot_platform_pre_load(uint32_t image_id)
155 {
156     return 0;
157 }
158 
boot_platform_post_load(uint32_t image_id)159 __WEAK int boot_platform_post_load(uint32_t image_id)
160 {
161     return 0;
162 }
163 
164 #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)165 static int boot_add_data_to_shared_area(uint8_t        major_type,
166                                         uint16_t       minor_type,
167                                         size_t         size,
168                                         const uint8_t *data)
169 {
170     struct shared_data_tlv_entry tlv_entry = {0};
171     struct tfm_boot_data *boot_data;
172     uintptr_t tlv_end, offset;
173 
174     if (data == NULL) {
175         return -1;
176     }
177 
178     boot_data = (struct tfm_boot_data *)BOOT_TFM_SHARED_DATA_BASE;
179 
180     /* Check whether the shared area needs to be initialized. */
181     if ((boot_data->header.tlv_magic != SHARED_DATA_TLV_INFO_MAGIC) ||
182         (boot_data->header.tlv_tot_len > BOOT_TFM_SHARED_DATA_SIZE)) {
183 
184         memset((void *)BOOT_TFM_SHARED_DATA_BASE, 0, BOOT_TFM_SHARED_DATA_SIZE);
185         boot_data->header.tlv_magic   = SHARED_DATA_TLV_INFO_MAGIC;
186         boot_data->header.tlv_tot_len = SHARED_DATA_HEADER_SIZE;
187     }
188 
189     /* Get the boundaries of TLV section. */
190     tlv_end = BOOT_TFM_SHARED_DATA_BASE + boot_data->header.tlv_tot_len;
191     offset  = BOOT_TFM_SHARED_DATA_BASE + SHARED_DATA_HEADER_SIZE;
192 
193     /* Check whether TLV entry is already added. Iterates over the TLV section
194      * looks for the same entry if found then returns with error.
195      */
196     while (offset < tlv_end) {
197         /* Create local copy to avoid unaligned access */
198         memcpy(&tlv_entry, (const void *)offset, SHARED_DATA_ENTRY_HEADER_SIZE);
199         if (GET_MAJOR(tlv_entry.tlv_type) == major_type &&
200             GET_MINOR(tlv_entry.tlv_type) == minor_type) {
201             return -1;
202         }
203 
204         offset += SHARED_DATA_ENTRY_SIZE(tlv_entry.tlv_len);
205     }
206 
207     /* Add TLV entry. */
208     tlv_entry.tlv_type = SET_TLV_TYPE(major_type, minor_type);
209     tlv_entry.tlv_len  = size;
210 
211     /* Check integer overflow and overflow of shared data area. */
212     if (SHARED_DATA_ENTRY_SIZE(size) >
213         (UINT16_MAX - boot_data->header.tlv_tot_len)) {
214         return -1;
215     } else if ((SHARED_DATA_ENTRY_SIZE(size) + boot_data->header.tlv_tot_len) >
216                BOOT_TFM_SHARED_DATA_SIZE) {
217         return -1;
218     }
219 
220     offset = tlv_end;
221     memcpy((void *)offset, &tlv_entry, SHARED_DATA_ENTRY_HEADER_SIZE);
222 
223     offset += SHARED_DATA_ENTRY_HEADER_SIZE;
224     memcpy((void *)offset, data, size);
225 
226     boot_data->header.tlv_tot_len += SHARED_DATA_ENTRY_SIZE(size);
227 
228     return 0;
229 }
230 
boot_store_measurement(uint8_t index,const uint8_t * measurement,size_t measurement_size,const struct boot_measurement_metadata * metadata,bool lock_measurement)231 __WEAK int boot_store_measurement(
232                             uint8_t index,
233                             const uint8_t *measurement,
234                             size_t measurement_size,
235                             const struct boot_measurement_metadata *metadata,
236                             bool lock_measurement)
237 {
238     uint16_t minor_type;
239     uint8_t claim;
240     int rc;
241 
242     if (index >= BOOT_MEASUREMENT_SLOT_MAX) {
243         return -1;
244     }
245 
246     minor_type = SET_MBS_MINOR(index, SW_MEASURE_METADATA);
247     rc = boot_add_data_to_shared_area(TLV_MAJOR_MBS,
248                                       minor_type,
249                                       sizeof(struct boot_measurement_metadata),
250                                       (const uint8_t *)metadata);
251     if (rc) {
252         return rc;
253     }
254 
255     claim = lock_measurement ? SW_MEASURE_VALUE_NON_EXTENDABLE
256                              : SW_MEASURE_VALUE;
257     minor_type = SET_MBS_MINOR(index, claim);
258     rc = boot_add_data_to_shared_area(TLV_MAJOR_MBS,
259                                       minor_type,
260                                       measurement_size,
261                                       measurement);
262 
263     return rc;
264 }
265 #endif /* TFM_MEASURED_BOOT_API */
266 
boot_initiate_recovery_mode(uint32_t image_id)267 __WEAK int boot_initiate_recovery_mode(uint32_t image_id)
268 {
269     (void)image_id;
270 
271     /* We haven't done anything, therefore recovery has failed */
272     return 1;
273 }
274