xref: /arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_main.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <assert.h>
8*91f16700Schasinglulu 
9*91f16700Schasinglulu #include "../../../../bl1/bl1_private.h"
10*91f16700Schasinglulu #include <arch.h>
11*91f16700Schasinglulu #include <arch_features.h>
12*91f16700Schasinglulu #include <arch_helpers.h>
13*91f16700Schasinglulu #include <bl1/bl1.h>
14*91f16700Schasinglulu #include <common/bl_common.h>
15*91f16700Schasinglulu #include <common/debug.h>
16*91f16700Schasinglulu #include <drivers/auth/auth_mod.h>
17*91f16700Schasinglulu #include <drivers/console.h>
18*91f16700Schasinglulu #include <lib/cpus/errata.h>
19*91f16700Schasinglulu #include <lib/utils.h>
20*91f16700Schasinglulu #include <smccc_helpers.h>
21*91f16700Schasinglulu #include <tools_share/uuid.h>
22*91f16700Schasinglulu #include <plat/arm/common/plat_arm.h>
23*91f16700Schasinglulu #include <plat/common/platform.h>
24*91f16700Schasinglulu 
25*91f16700Schasinglulu #include <platform_def.h>
26*91f16700Schasinglulu 
27*91f16700Schasinglulu 
28*91f16700Schasinglulu void cm_prepare_el2_exit(void);
29*91f16700Schasinglulu 
30*91f16700Schasinglulu void bl1_run_next_image(const struct entry_point_info *bl_ep_info);
31*91f16700Schasinglulu 
32*91f16700Schasinglulu /*******************************************************************************
33*91f16700Schasinglulu  * Function to perform late architectural and platform specific initialization.
34*91f16700Schasinglulu  * It also queries the platform to load and run next BL image. Only called
35*91f16700Schasinglulu  * by the primary cpu after a cold boot.
36*91f16700Schasinglulu  ******************************************************************************/
37*91f16700Schasinglulu void bl1_transfer_bl33(void)
38*91f16700Schasinglulu {
39*91f16700Schasinglulu 	unsigned int image_id;
40*91f16700Schasinglulu 
41*91f16700Schasinglulu 	/* Get the image id of next image to load and run. */
42*91f16700Schasinglulu 	image_id = bl1_plat_get_next_image_id();
43*91f16700Schasinglulu 
44*91f16700Schasinglulu #if !ARM_DISABLE_TRUSTED_WDOG
45*91f16700Schasinglulu 	/* Disable watchdog before leaving BL1 */
46*91f16700Schasinglulu 	plat_arm_secure_wdt_stop();
47*91f16700Schasinglulu #endif
48*91f16700Schasinglulu 
49*91f16700Schasinglulu 	bl1_run_next_image(&bl1_plat_get_image_desc(image_id)->ep_info);
50*91f16700Schasinglulu }
51*91f16700Schasinglulu 
52*91f16700Schasinglulu /*******************************************************************************
53*91f16700Schasinglulu  * This function locates and loads the BL33 raw binary image in the trusted SRAM.
54*91f16700Schasinglulu  * Called by the primary cpu after a cold boot.
55*91f16700Schasinglulu  * TODO: Add support for alternative image load mechanism e.g using virtio/elf
56*91f16700Schasinglulu  * loader etc.
57*91f16700Schasinglulu  ******************************************************************************/
58*91f16700Schasinglulu void bl1_load_bl33(void)
59*91f16700Schasinglulu {
60*91f16700Schasinglulu 	image_desc_t *desc;
61*91f16700Schasinglulu 	image_info_t *info;
62*91f16700Schasinglulu 	int err;
63*91f16700Schasinglulu 
64*91f16700Schasinglulu 	/* Get the image descriptor */
65*91f16700Schasinglulu 	desc = bl1_plat_get_image_desc(BL33_IMAGE_ID);
66*91f16700Schasinglulu 	assert(desc != NULL);
67*91f16700Schasinglulu 
68*91f16700Schasinglulu 	/* Get the image info */
69*91f16700Schasinglulu 	info = &desc->image_info;
70*91f16700Schasinglulu 	INFO("BL1: Loading BL33\n");
71*91f16700Schasinglulu 
72*91f16700Schasinglulu 	err = bl1_plat_handle_pre_image_load(BL33_IMAGE_ID);
73*91f16700Schasinglulu 	if (err != 0) {
74*91f16700Schasinglulu 		ERROR("Failure in pre image load handling of BL33 (%d)\n", err);
75*91f16700Schasinglulu 		plat_error_handler(err);
76*91f16700Schasinglulu 	}
77*91f16700Schasinglulu 
78*91f16700Schasinglulu 	err = load_auth_image(BL33_IMAGE_ID, info);
79*91f16700Schasinglulu 	if (err != 0) {
80*91f16700Schasinglulu 		ERROR("Failed to load BL33 firmware.\n");
81*91f16700Schasinglulu 		plat_error_handler(err);
82*91f16700Schasinglulu 	}
83*91f16700Schasinglulu 
84*91f16700Schasinglulu 	/* Allow platform to handle image information. */
85*91f16700Schasinglulu 	err = bl1_plat_handle_post_image_load(BL33_IMAGE_ID);
86*91f16700Schasinglulu 	if (err != 0) {
87*91f16700Schasinglulu 		ERROR("Failure in post image load handling of BL33 (%d)\n", err);
88*91f16700Schasinglulu 		plat_error_handler(err);
89*91f16700Schasinglulu 	}
90*91f16700Schasinglulu 
91*91f16700Schasinglulu 	NOTICE("BL1: Booting BL33\n");
92*91f16700Schasinglulu }
93*91f16700Schasinglulu 
94*91f16700Schasinglulu /*******************************************************************************
95*91f16700Schasinglulu  * Helper utility to calculate the BL2 memory layout taking into consideration
96*91f16700Schasinglulu  * the BL1 RW data assuming that it is at the top of the memory layout.
97*91f16700Schasinglulu  ******************************************************************************/
98*91f16700Schasinglulu void bl1_calc_bl2_mem_layout(const meminfo_t *bl1_mem_layout,
99*91f16700Schasinglulu 			meminfo_t *bl2_mem_layout)
100*91f16700Schasinglulu {
101*91f16700Schasinglulu 	assert(bl1_mem_layout != NULL);
102*91f16700Schasinglulu 	assert(bl2_mem_layout != NULL);
103*91f16700Schasinglulu 
104*91f16700Schasinglulu 	/*
105*91f16700Schasinglulu 	 * Remove BL1 RW data from the scope of memory visible to BL2.
106*91f16700Schasinglulu 	 * This is assuming BL1 RW data is at the top of bl1_mem_layout.
107*91f16700Schasinglulu 	 */
108*91f16700Schasinglulu 	assert(bl1_mem_layout->total_base < BL1_RW_BASE);
109*91f16700Schasinglulu 	bl2_mem_layout->total_base = bl1_mem_layout->total_base;
110*91f16700Schasinglulu 	bl2_mem_layout->total_size = BL1_RW_BASE - bl1_mem_layout->total_base;
111*91f16700Schasinglulu 
112*91f16700Schasinglulu 	flush_dcache_range((uintptr_t)bl2_mem_layout, sizeof(meminfo_t));
113*91f16700Schasinglulu }
114*91f16700Schasinglulu 
115*91f16700Schasinglulu /*******************************************************************************
116*91f16700Schasinglulu  * This function prepares for entry to BL33
117*91f16700Schasinglulu  ******************************************************************************/
118*91f16700Schasinglulu void bl1_prepare_next_image(unsigned int image_id)
119*91f16700Schasinglulu {
120*91f16700Schasinglulu 	unsigned int mode = MODE_EL1;
121*91f16700Schasinglulu 	image_desc_t *desc;
122*91f16700Schasinglulu 	entry_point_info_t *next_bl_ep;
123*91f16700Schasinglulu 
124*91f16700Schasinglulu #if CTX_INCLUDE_AARCH32_REGS
125*91f16700Schasinglulu 	/*
126*91f16700Schasinglulu 	 * Ensure that the build flag to save AArch32 system registers in CPU
127*91f16700Schasinglulu 	 * context is not set for AArch64-only platforms.
128*91f16700Schasinglulu 	 */
129*91f16700Schasinglulu 	if (el_implemented(1) == EL_IMPL_A64ONLY) {
130*91f16700Schasinglulu 		ERROR("EL1 supports AArch64-only. Please set build flag %s",
131*91f16700Schasinglulu 				"CTX_INCLUDE_AARCH32_REGS = 0\n");
132*91f16700Schasinglulu 		panic();
133*91f16700Schasinglulu 	}
134*91f16700Schasinglulu #endif
135*91f16700Schasinglulu 
136*91f16700Schasinglulu 	/* Get the image descriptor. */
137*91f16700Schasinglulu 	desc = bl1_plat_get_image_desc(image_id);
138*91f16700Schasinglulu 	assert(desc != NULL);
139*91f16700Schasinglulu 
140*91f16700Schasinglulu 	/* Get the entry point info. */
141*91f16700Schasinglulu 	next_bl_ep = &desc->ep_info;
142*91f16700Schasinglulu 
143*91f16700Schasinglulu 	/* FVP-R is only secure */
144*91f16700Schasinglulu 	assert(GET_SECURITY_STATE(next_bl_ep->h.attr) == SECURE);
145*91f16700Schasinglulu 
146*91f16700Schasinglulu 	/* Prepare the SPSR for the next BL image. */
147*91f16700Schasinglulu 	next_bl_ep->spsr = (uint32_t)SPSR_64((uint64_t) mode,
148*91f16700Schasinglulu 		(uint64_t)MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
149*91f16700Schasinglulu 
150*91f16700Schasinglulu 	/* Allow platform to make change */
151*91f16700Schasinglulu 	bl1_plat_set_ep_info(image_id, next_bl_ep);
152*91f16700Schasinglulu 
153*91f16700Schasinglulu 	/* Prepare context for the next EL */
154*91f16700Schasinglulu 	cm_prepare_el2_exit();
155*91f16700Schasinglulu 
156*91f16700Schasinglulu 	/* Indicate that image is in execution state. */
157*91f16700Schasinglulu 	desc->state = IMAGE_STATE_EXECUTED;
158*91f16700Schasinglulu 
159*91f16700Schasinglulu 	print_entry_point_info(next_bl_ep);
160*91f16700Schasinglulu }
161*91f16700Schasinglulu 
162*91f16700Schasinglulu /*******************************************************************************
163*91f16700Schasinglulu  * Setup function for BL1.
164*91f16700Schasinglulu  ******************************************************************************/
165*91f16700Schasinglulu void bl1_setup(void)
166*91f16700Schasinglulu {
167*91f16700Schasinglulu 	/* Perform early platform-specific setup */
168*91f16700Schasinglulu 	bl1_early_platform_setup();
169*91f16700Schasinglulu 
170*91f16700Schasinglulu 	/* Perform late platform-specific setup */
171*91f16700Schasinglulu 	bl1_plat_arch_setup();
172*91f16700Schasinglulu }
173*91f16700Schasinglulu 
174*91f16700Schasinglulu /*******************************************************************************
175*91f16700Schasinglulu  * Function to perform late architectural and platform specific initialization.
176*91f16700Schasinglulu  * It also queries the platform to load and run next BL image. Only called
177*91f16700Schasinglulu  * by the primary cpu after a cold boot.
178*91f16700Schasinglulu  ******************************************************************************/
179*91f16700Schasinglulu void bl1_main(void)
180*91f16700Schasinglulu {
181*91f16700Schasinglulu 	unsigned int image_id;
182*91f16700Schasinglulu 
183*91f16700Schasinglulu 	/* Announce our arrival */
184*91f16700Schasinglulu 	NOTICE(FIRMWARE_WELCOME_STR);
185*91f16700Schasinglulu 	NOTICE("BL1: %s\n", version_string);
186*91f16700Schasinglulu 	NOTICE("BL1: %s\n", build_message);
187*91f16700Schasinglulu 
188*91f16700Schasinglulu 	INFO("BL1: RAM %p - %p\n", (void *)BL1_RAM_BASE, (void *)BL1_RAM_LIMIT);
189*91f16700Schasinglulu 
190*91f16700Schasinglulu 	print_errata_status();
191*91f16700Schasinglulu 
192*91f16700Schasinglulu #if ENABLE_ASSERTIONS
193*91f16700Schasinglulu 	u_register_t val;
194*91f16700Schasinglulu 	/*
195*91f16700Schasinglulu 	 * Ensure that MMU/Caches and coherency are turned on
196*91f16700Schasinglulu 	 */
197*91f16700Schasinglulu 	val = read_sctlr_el2();
198*91f16700Schasinglulu 
199*91f16700Schasinglulu 	assert((val & SCTLR_M_BIT) != 0U);
200*91f16700Schasinglulu 	assert((val & SCTLR_C_BIT) != 0U);
201*91f16700Schasinglulu 	assert((val & SCTLR_I_BIT) != 0U);
202*91f16700Schasinglulu 	/*
203*91f16700Schasinglulu 	 * Check that Cache Writeback Granule (CWG) in CTR_EL0 matches the
204*91f16700Schasinglulu 	 * provided platform value
205*91f16700Schasinglulu 	 */
206*91f16700Schasinglulu 	val = (read_ctr_el0() >> CTR_CWG_SHIFT) & CTR_CWG_MASK;
207*91f16700Schasinglulu 	/*
208*91f16700Schasinglulu 	 * If CWG is zero, then no CWG information is available but we can
209*91f16700Schasinglulu 	 * at least check the platform value is less than the architectural
210*91f16700Schasinglulu 	 * maximum.
211*91f16700Schasinglulu 	 */
212*91f16700Schasinglulu 	if (val != 0) {
213*91f16700Schasinglulu 		assert(SIZE_FROM_LOG2_WORDS(val) == CACHE_WRITEBACK_GRANULE);
214*91f16700Schasinglulu 	} else {
215*91f16700Schasinglulu 		assert(MAX_CACHE_LINE_SIZE >= CACHE_WRITEBACK_GRANULE);
216*91f16700Schasinglulu 	}
217*91f16700Schasinglulu #endif /* ENABLE_ASSERTIONS */
218*91f16700Schasinglulu 
219*91f16700Schasinglulu 	/* Perform remaining generic architectural setup from ELmax */
220*91f16700Schasinglulu 	bl1_arch_setup();
221*91f16700Schasinglulu 
222*91f16700Schasinglulu #if TRUSTED_BOARD_BOOT
223*91f16700Schasinglulu 	/* Initialize authentication module */
224*91f16700Schasinglulu 	auth_mod_init();
225*91f16700Schasinglulu #endif /* TRUSTED_BOARD_BOOT */
226*91f16700Schasinglulu 
227*91f16700Schasinglulu 	/* Perform platform setup in BL1. */
228*91f16700Schasinglulu 	bl1_platform_setup();
229*91f16700Schasinglulu 
230*91f16700Schasinglulu 	/* Get the image id of next image to load and run. */
231*91f16700Schasinglulu 	image_id = bl1_plat_get_next_image_id();
232*91f16700Schasinglulu 
233*91f16700Schasinglulu 	/*
234*91f16700Schasinglulu 	 * We currently interpret any image id other than
235*91f16700Schasinglulu 	 * BL2_IMAGE_ID as the start of firmware update.
236*91f16700Schasinglulu 	 */
237*91f16700Schasinglulu 	if (image_id == BL33_IMAGE_ID) {
238*91f16700Schasinglulu 		bl1_load_bl33();
239*91f16700Schasinglulu 	} else {
240*91f16700Schasinglulu 		NOTICE("BL1-FWU: *******FWU Process Started*******\n");
241*91f16700Schasinglulu 	}
242*91f16700Schasinglulu 
243*91f16700Schasinglulu 	bl1_prepare_next_image(image_id);
244*91f16700Schasinglulu 
245*91f16700Schasinglulu 	console_flush();
246*91f16700Schasinglulu 
247*91f16700Schasinglulu 	bl1_transfer_bl33();
248*91f16700Schasinglulu }
249*91f16700Schasinglulu 
250*91f16700Schasinglulu /*******************************************************************************
251*91f16700Schasinglulu  * Function called just before handing over to the next BL to inform the user
252*91f16700Schasinglulu  * about the boot progress. In debug mode, also print details about the BL
253*91f16700Schasinglulu  * image's execution context.
254*91f16700Schasinglulu  ******************************************************************************/
255*91f16700Schasinglulu void bl1_print_next_bl_ep_info(const entry_point_info_t *bl_ep_info)
256*91f16700Schasinglulu {
257*91f16700Schasinglulu 	NOTICE("BL1: Booting BL31\n");
258*91f16700Schasinglulu 	print_entry_point_info(bl_ep_info);
259*91f16700Schasinglulu }
260*91f16700Schasinglulu 
261*91f16700Schasinglulu #if SPIN_ON_BL1_EXIT
262*91f16700Schasinglulu void print_debug_loop_message(void)
263*91f16700Schasinglulu {
264*91f16700Schasinglulu 	NOTICE("BL1: Debug loop, spinning forever\n");
265*91f16700Schasinglulu 	NOTICE("BL1: Please connect the debugger to continue\n");
266*91f16700Schasinglulu }
267*91f16700Schasinglulu #endif
268*91f16700Schasinglulu 
269