xref: /aosp_15_r20/external/arm-trusted-firmware/common/bl_common.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park  * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.
3*54fd6939SJiyong Park  *
4*54fd6939SJiyong Park  * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park  */
6*54fd6939SJiyong Park 
7*54fd6939SJiyong Park #include <assert.h>
8*54fd6939SJiyong Park #include <errno.h>
9*54fd6939SJiyong Park #include <string.h>
10*54fd6939SJiyong Park 
11*54fd6939SJiyong Park #include <arch.h>
12*54fd6939SJiyong Park #include <arch_features.h>
13*54fd6939SJiyong Park #include <arch_helpers.h>
14*54fd6939SJiyong Park #include <common/bl_common.h>
15*54fd6939SJiyong Park #include <common/debug.h>
16*54fd6939SJiyong Park #include <drivers/auth/auth_mod.h>
17*54fd6939SJiyong Park #include <drivers/io/io_storage.h>
18*54fd6939SJiyong Park #include <lib/utils.h>
19*54fd6939SJiyong Park #include <lib/xlat_tables/xlat_tables_defs.h>
20*54fd6939SJiyong Park #include <plat/common/platform.h>
21*54fd6939SJiyong Park 
22*54fd6939SJiyong Park #if TRUSTED_BOARD_BOOT
23*54fd6939SJiyong Park # ifdef DYN_DISABLE_AUTH
24*54fd6939SJiyong Park static int disable_auth;
25*54fd6939SJiyong Park 
26*54fd6939SJiyong Park /******************************************************************************
27*54fd6939SJiyong Park  * API to dynamically disable authentication. Only meant for development
28*54fd6939SJiyong Park  * systems. This is only invoked if DYN_DISABLE_AUTH is defined.
29*54fd6939SJiyong Park  *****************************************************************************/
dyn_disable_auth(void)30*54fd6939SJiyong Park void dyn_disable_auth(void)
31*54fd6939SJiyong Park {
32*54fd6939SJiyong Park 	INFO("Disabling authentication of images dynamically\n");
33*54fd6939SJiyong Park 	disable_auth = 1;
34*54fd6939SJiyong Park }
35*54fd6939SJiyong Park # endif /* DYN_DISABLE_AUTH */
36*54fd6939SJiyong Park 
37*54fd6939SJiyong Park /******************************************************************************
38*54fd6939SJiyong Park  * Function to determine whether the authentication is disabled dynamically.
39*54fd6939SJiyong Park  *****************************************************************************/
dyn_is_auth_disabled(void)40*54fd6939SJiyong Park static int dyn_is_auth_disabled(void)
41*54fd6939SJiyong Park {
42*54fd6939SJiyong Park # ifdef DYN_DISABLE_AUTH
43*54fd6939SJiyong Park 	return disable_auth;
44*54fd6939SJiyong Park # else
45*54fd6939SJiyong Park 	return 0;
46*54fd6939SJiyong Park # endif
47*54fd6939SJiyong Park }
48*54fd6939SJiyong Park #endif /* TRUSTED_BOARD_BOOT */
49*54fd6939SJiyong Park 
page_align(uintptr_t value,unsigned dir)50*54fd6939SJiyong Park uintptr_t page_align(uintptr_t value, unsigned dir)
51*54fd6939SJiyong Park {
52*54fd6939SJiyong Park 	/* Round up the limit to the next page boundary */
53*54fd6939SJiyong Park 	if ((value & PAGE_SIZE_MASK) != 0U) {
54*54fd6939SJiyong Park 		value &= ~PAGE_SIZE_MASK;
55*54fd6939SJiyong Park 		if (dir == UP)
56*54fd6939SJiyong Park 			value += PAGE_SIZE;
57*54fd6939SJiyong Park 	}
58*54fd6939SJiyong Park 
59*54fd6939SJiyong Park 	return value;
60*54fd6939SJiyong Park }
61*54fd6939SJiyong Park 
62*54fd6939SJiyong Park /*******************************************************************************
63*54fd6939SJiyong Park  * Internal function to load an image at a specific address given
64*54fd6939SJiyong Park  * an image ID and extents of free memory.
65*54fd6939SJiyong Park  *
66*54fd6939SJiyong Park  * If the load is successful then the image information is updated.
67*54fd6939SJiyong Park  *
68*54fd6939SJiyong Park  * Returns 0 on success, a negative error code otherwise.
69*54fd6939SJiyong Park  ******************************************************************************/
load_image(unsigned int image_id,image_info_t * image_data)70*54fd6939SJiyong Park static int load_image(unsigned int image_id, image_info_t *image_data)
71*54fd6939SJiyong Park {
72*54fd6939SJiyong Park 	uintptr_t dev_handle;
73*54fd6939SJiyong Park 	uintptr_t image_handle;
74*54fd6939SJiyong Park 	uintptr_t image_spec;
75*54fd6939SJiyong Park 	uintptr_t image_base;
76*54fd6939SJiyong Park 	size_t image_size;
77*54fd6939SJiyong Park 	size_t bytes_read;
78*54fd6939SJiyong Park 	int io_result;
79*54fd6939SJiyong Park 
80*54fd6939SJiyong Park 	assert(image_data != NULL);
81*54fd6939SJiyong Park 	assert(image_data->h.version >= VERSION_2);
82*54fd6939SJiyong Park 
83*54fd6939SJiyong Park 	image_base = image_data->image_base;
84*54fd6939SJiyong Park 
85*54fd6939SJiyong Park 	/* Obtain a reference to the image by querying the platform layer */
86*54fd6939SJiyong Park 	io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
87*54fd6939SJiyong Park 	if (io_result != 0) {
88*54fd6939SJiyong Park 		WARN("Failed to obtain reference to image id=%u (%i)\n",
89*54fd6939SJiyong Park 			image_id, io_result);
90*54fd6939SJiyong Park 		return io_result;
91*54fd6939SJiyong Park 	}
92*54fd6939SJiyong Park 
93*54fd6939SJiyong Park 	/* Attempt to access the image */
94*54fd6939SJiyong Park 	io_result = io_open(dev_handle, image_spec, &image_handle);
95*54fd6939SJiyong Park 	if (io_result != 0) {
96*54fd6939SJiyong Park 		WARN("Failed to access image id=%u (%i)\n",
97*54fd6939SJiyong Park 			image_id, io_result);
98*54fd6939SJiyong Park 		return io_result;
99*54fd6939SJiyong Park 	}
100*54fd6939SJiyong Park 
101*54fd6939SJiyong Park 	INFO("Loading image id=%u at address 0x%lx\n", image_id, image_base);
102*54fd6939SJiyong Park 
103*54fd6939SJiyong Park 	/* Find the size of the image */
104*54fd6939SJiyong Park 	io_result = io_size(image_handle, &image_size);
105*54fd6939SJiyong Park 	if ((io_result != 0) || (image_size == 0U)) {
106*54fd6939SJiyong Park 		WARN("Failed to determine the size of the image id=%u (%i)\n",
107*54fd6939SJiyong Park 			image_id, io_result);
108*54fd6939SJiyong Park 		goto exit;
109*54fd6939SJiyong Park 	}
110*54fd6939SJiyong Park 
111*54fd6939SJiyong Park 	/* Check that the image size to load is within limit */
112*54fd6939SJiyong Park 	if (image_size > image_data->image_max_size) {
113*54fd6939SJiyong Park 		WARN("Image id=%u size out of bounds\n", image_id);
114*54fd6939SJiyong Park 		io_result = -EFBIG;
115*54fd6939SJiyong Park 		goto exit;
116*54fd6939SJiyong Park 	}
117*54fd6939SJiyong Park 
118*54fd6939SJiyong Park 	/*
119*54fd6939SJiyong Park 	 * image_data->image_max_size is a uint32_t so image_size will always
120*54fd6939SJiyong Park 	 * fit in image_data->image_size.
121*54fd6939SJiyong Park 	 */
122*54fd6939SJiyong Park 	image_data->image_size = (uint32_t)image_size;
123*54fd6939SJiyong Park 
124*54fd6939SJiyong Park 	/* We have enough space so load the image now */
125*54fd6939SJiyong Park 	/* TODO: Consider whether to try to recover/retry a partially successful read */
126*54fd6939SJiyong Park 	io_result = io_read(image_handle, image_base, image_size, &bytes_read);
127*54fd6939SJiyong Park 	if ((io_result != 0) || (bytes_read < image_size)) {
128*54fd6939SJiyong Park 		WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
129*54fd6939SJiyong Park 		goto exit;
130*54fd6939SJiyong Park 	}
131*54fd6939SJiyong Park 
132*54fd6939SJiyong Park 	INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base,
133*54fd6939SJiyong Park 	     (uintptr_t)(image_base + image_size));
134*54fd6939SJiyong Park 
135*54fd6939SJiyong Park exit:
136*54fd6939SJiyong Park 	(void)io_close(image_handle);
137*54fd6939SJiyong Park 	/* Ignore improbable/unrecoverable error in 'close' */
138*54fd6939SJiyong Park 
139*54fd6939SJiyong Park 	/* TODO: Consider maintaining open device connection from this bootloader stage */
140*54fd6939SJiyong Park 	(void)io_dev_close(dev_handle);
141*54fd6939SJiyong Park 	/* Ignore improbable/unrecoverable error in 'dev_close' */
142*54fd6939SJiyong Park 
143*54fd6939SJiyong Park 	return io_result;
144*54fd6939SJiyong Park }
145*54fd6939SJiyong Park 
146*54fd6939SJiyong Park /*
147*54fd6939SJiyong Park  * Load an image and flush it out to main memory so that it can be executed
148*54fd6939SJiyong Park  * later by any CPU, regardless of cache and MMU state.
149*54fd6939SJiyong Park  */
load_image_flush(unsigned int image_id,image_info_t * image_data)150*54fd6939SJiyong Park static int load_image_flush(unsigned int image_id,
151*54fd6939SJiyong Park 			    image_info_t *image_data)
152*54fd6939SJiyong Park {
153*54fd6939SJiyong Park 	int rc;
154*54fd6939SJiyong Park 
155*54fd6939SJiyong Park 	rc = load_image(image_id, image_data);
156*54fd6939SJiyong Park 	if (rc == 0) {
157*54fd6939SJiyong Park 		flush_dcache_range(image_data->image_base,
158*54fd6939SJiyong Park 				   image_data->image_size);
159*54fd6939SJiyong Park 	}
160*54fd6939SJiyong Park 
161*54fd6939SJiyong Park 	return rc;
162*54fd6939SJiyong Park }
163*54fd6939SJiyong Park 
164*54fd6939SJiyong Park 
165*54fd6939SJiyong Park #if TRUSTED_BOARD_BOOT
166*54fd6939SJiyong Park /*
167*54fd6939SJiyong Park  * This function uses recursion to authenticate the parent images up to the root
168*54fd6939SJiyong Park  * of trust.
169*54fd6939SJiyong Park  */
load_auth_image_recursive(unsigned int image_id,image_info_t * image_data,int is_parent_image)170*54fd6939SJiyong Park static int load_auth_image_recursive(unsigned int image_id,
171*54fd6939SJiyong Park 				    image_info_t *image_data,
172*54fd6939SJiyong Park 				    int is_parent_image)
173*54fd6939SJiyong Park {
174*54fd6939SJiyong Park 	int rc;
175*54fd6939SJiyong Park 	unsigned int parent_id;
176*54fd6939SJiyong Park 
177*54fd6939SJiyong Park 	/* Use recursion to authenticate parent images */
178*54fd6939SJiyong Park 	rc = auth_mod_get_parent_id(image_id, &parent_id);
179*54fd6939SJiyong Park 	if (rc == 0) {
180*54fd6939SJiyong Park 		rc = load_auth_image_recursive(parent_id, image_data, 1);
181*54fd6939SJiyong Park 		if (rc != 0) {
182*54fd6939SJiyong Park 			return rc;
183*54fd6939SJiyong Park 		}
184*54fd6939SJiyong Park 	}
185*54fd6939SJiyong Park 
186*54fd6939SJiyong Park 	/* Load the image */
187*54fd6939SJiyong Park 	rc = load_image(image_id, image_data);
188*54fd6939SJiyong Park 	if (rc != 0) {
189*54fd6939SJiyong Park 		return rc;
190*54fd6939SJiyong Park 	}
191*54fd6939SJiyong Park 
192*54fd6939SJiyong Park 	/* Authenticate it */
193*54fd6939SJiyong Park 	rc = auth_mod_verify_img(image_id,
194*54fd6939SJiyong Park 				 (void *)image_data->image_base,
195*54fd6939SJiyong Park 				 image_data->image_size);
196*54fd6939SJiyong Park 	if (rc != 0) {
197*54fd6939SJiyong Park 		/* Authentication error, zero memory and flush it right away. */
198*54fd6939SJiyong Park 		zero_normalmem((void *)image_data->image_base,
199*54fd6939SJiyong Park 			       image_data->image_size);
200*54fd6939SJiyong Park 		flush_dcache_range(image_data->image_base,
201*54fd6939SJiyong Park 				   image_data->image_size);
202*54fd6939SJiyong Park 		return -EAUTH;
203*54fd6939SJiyong Park 	}
204*54fd6939SJiyong Park 
205*54fd6939SJiyong Park 	if (is_parent_image == 0) {
206*54fd6939SJiyong Park 		/*
207*54fd6939SJiyong Park 		 * Measure the image.
208*54fd6939SJiyong Park 		 * We do not measure its parents because these only play a role
209*54fd6939SJiyong Park 		 * in authentication, which is orthogonal to measured boot.
210*54fd6939SJiyong Park 		 *
211*54fd6939SJiyong Park 		 * TODO: Change this code if we change our minds about measuring
212*54fd6939SJiyong Park 		 * certificates.
213*54fd6939SJiyong Park 		 */
214*54fd6939SJiyong Park 		rc = plat_mboot_measure_image(image_id, image_data);
215*54fd6939SJiyong Park 		if (rc != 0) {
216*54fd6939SJiyong Park 			return rc;
217*54fd6939SJiyong Park 		}
218*54fd6939SJiyong Park 
219*54fd6939SJiyong Park 		/*
220*54fd6939SJiyong Park 		 * Flush the image to main memory so that it can be executed
221*54fd6939SJiyong Park 		 * later by any CPU, regardless of cache and MMU state. This
222*54fd6939SJiyong Park 		 * is only needed for child images, not for the parents
223*54fd6939SJiyong Park 		 * (certificates).
224*54fd6939SJiyong Park 		 */
225*54fd6939SJiyong Park 		flush_dcache_range(image_data->image_base,
226*54fd6939SJiyong Park 				   image_data->image_size);
227*54fd6939SJiyong Park 	}
228*54fd6939SJiyong Park 
229*54fd6939SJiyong Park 	return 0;
230*54fd6939SJiyong Park }
231*54fd6939SJiyong Park #endif /* TRUSTED_BOARD_BOOT */
232*54fd6939SJiyong Park 
load_auth_image_internal(unsigned int image_id,image_info_t * image_data)233*54fd6939SJiyong Park static int load_auth_image_internal(unsigned int image_id,
234*54fd6939SJiyong Park 				    image_info_t *image_data)
235*54fd6939SJiyong Park {
236*54fd6939SJiyong Park #if TRUSTED_BOARD_BOOT
237*54fd6939SJiyong Park 	if (dyn_is_auth_disabled() == 0) {
238*54fd6939SJiyong Park 		return load_auth_image_recursive(image_id, image_data, 0);
239*54fd6939SJiyong Park 	}
240*54fd6939SJiyong Park #endif
241*54fd6939SJiyong Park 
242*54fd6939SJiyong Park 	return load_image_flush(image_id, image_data);
243*54fd6939SJiyong Park }
244*54fd6939SJiyong Park 
245*54fd6939SJiyong Park /*******************************************************************************
246*54fd6939SJiyong Park  * Generic function to load and authenticate an image. The image is actually
247*54fd6939SJiyong Park  * loaded by calling the 'load_image()' function. Therefore, it returns the
248*54fd6939SJiyong Park  * same error codes if the loading operation failed, or -EAUTH if the
249*54fd6939SJiyong Park  * authentication failed. In addition, this function uses recursion to
250*54fd6939SJiyong Park  * authenticate the parent images up to the root of trust (if TBB is enabled).
251*54fd6939SJiyong Park  ******************************************************************************/
load_auth_image(unsigned int image_id,image_info_t * image_data)252*54fd6939SJiyong Park int load_auth_image(unsigned int image_id, image_info_t *image_data)
253*54fd6939SJiyong Park {
254*54fd6939SJiyong Park 	int err;
255*54fd6939SJiyong Park 
256*54fd6939SJiyong Park /*
257*54fd6939SJiyong Park  * All firmware banks should be part of the same non-volatile storage as per
258*54fd6939SJiyong Park  * PSA FWU specification, hence don't check for any alternate boot source
259*54fd6939SJiyong Park  * when PSA FWU is enabled.
260*54fd6939SJiyong Park  */
261*54fd6939SJiyong Park #if PSA_FWU_SUPPORT
262*54fd6939SJiyong Park 	err = load_auth_image_internal(image_id, image_data);
263*54fd6939SJiyong Park #else
264*54fd6939SJiyong Park 	do {
265*54fd6939SJiyong Park 		err = load_auth_image_internal(image_id, image_data);
266*54fd6939SJiyong Park 	} while ((err != 0) && (plat_try_next_boot_source() != 0));
267*54fd6939SJiyong Park #endif /* PSA_FWU_SUPPORT */
268*54fd6939SJiyong Park 
269*54fd6939SJiyong Park 	return err;
270*54fd6939SJiyong Park }
271*54fd6939SJiyong Park 
272*54fd6939SJiyong Park /*******************************************************************************
273*54fd6939SJiyong Park  * Print the content of an entry_point_info_t structure.
274*54fd6939SJiyong Park  ******************************************************************************/
print_entry_point_info(const entry_point_info_t * ep_info)275*54fd6939SJiyong Park void print_entry_point_info(const entry_point_info_t *ep_info)
276*54fd6939SJiyong Park {
277*54fd6939SJiyong Park 	INFO("Entry point address = 0x%lx\n", ep_info->pc);
278*54fd6939SJiyong Park 	INFO("SPSR = 0x%x\n", ep_info->spsr);
279*54fd6939SJiyong Park 
280*54fd6939SJiyong Park #define PRINT_IMAGE_ARG(n)					\
281*54fd6939SJiyong Park 	VERBOSE("Argument #" #n " = 0x%llx\n",			\
282*54fd6939SJiyong Park 		(unsigned long long) ep_info->args.arg##n)
283*54fd6939SJiyong Park 
284*54fd6939SJiyong Park 	PRINT_IMAGE_ARG(0);
285*54fd6939SJiyong Park 	PRINT_IMAGE_ARG(1);
286*54fd6939SJiyong Park 	PRINT_IMAGE_ARG(2);
287*54fd6939SJiyong Park 	PRINT_IMAGE_ARG(3);
288*54fd6939SJiyong Park #ifdef __aarch64__
289*54fd6939SJiyong Park 	PRINT_IMAGE_ARG(4);
290*54fd6939SJiyong Park 	PRINT_IMAGE_ARG(5);
291*54fd6939SJiyong Park 	PRINT_IMAGE_ARG(6);
292*54fd6939SJiyong Park 	PRINT_IMAGE_ARG(7);
293*54fd6939SJiyong Park #endif
294*54fd6939SJiyong Park #undef PRINT_IMAGE_ARG
295*54fd6939SJiyong Park }
296