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)®ION_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