xref: /rk3399_ARM-atf/common/bl_common.c (revision aab8209036028c4208834c4d11c904532c6cdda5)
14f6ad66aSAchin Gupta /*
2758ccb80SChris Kay  * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
3*854b4dd9SToshiyuki Ogasahara  * Copyright (c) 2021-2025, Renesas Electronics Corporation. All rights reserved.
44f6ad66aSAchin Gupta  *
582cb2c1aSdp-arm  * SPDX-License-Identifier: BSD-3-Clause
64f6ad66aSAchin Gupta  */
74f6ad66aSAchin Gupta 
809d40e0eSAntonio Nino Diaz #include <assert.h>
909d40e0eSAntonio Nino Diaz #include <errno.h>
1009d40e0eSAntonio Nino Diaz #include <string.h>
1109d40e0eSAntonio Nino Diaz 
1297043ac9SDan Handley #include <arch.h>
13b86048c4SAntonio Nino Diaz #include <arch_features.h>
144f6ad66aSAchin Gupta #include <arch_helpers.h>
1509d40e0eSAntonio Nino Diaz #include <common/bl_common.h>
16758ccb80SChris Kay #include <common/build_message.h>
1709d40e0eSAntonio Nino Diaz #include <common/debug.h>
1809d40e0eSAntonio Nino Diaz #include <drivers/auth/auth_mod.h>
1909d40e0eSAntonio Nino Diaz #include <drivers/io/io_storage.h>
2009d40e0eSAntonio Nino Diaz #include <lib/utils.h>
2109d40e0eSAntonio Nino Diaz #include <lib/xlat_tables/xlat_tables_defs.h>
2209d40e0eSAntonio Nino Diaz #include <plat/common/platform.h>
234f6ad66aSAchin Gupta 
24209a60ccSSoby Mathew #if TRUSTED_BOARD_BOOT
25209a60ccSSoby Mathew # ifdef DYN_DISABLE_AUTH
26209a60ccSSoby Mathew static int disable_auth;
27209a60ccSSoby Mathew 
28209a60ccSSoby Mathew /******************************************************************************
29209a60ccSSoby Mathew  * API to dynamically disable authentication. Only meant for development
30ed51b51fSRoberto Vargas  * systems. This is only invoked if DYN_DISABLE_AUTH is defined.
31209a60ccSSoby Mathew  *****************************************************************************/
dyn_disable_auth(void)32209a60ccSSoby Mathew void dyn_disable_auth(void)
33209a60ccSSoby Mathew {
34209a60ccSSoby Mathew 	INFO("Disabling authentication of images dynamically\n");
35209a60ccSSoby Mathew 	disable_auth = 1;
36209a60ccSSoby Mathew }
37209a60ccSSoby Mathew # endif /* DYN_DISABLE_AUTH */
38209a60ccSSoby Mathew 
39209a60ccSSoby Mathew /******************************************************************************
40209a60ccSSoby Mathew  * Function to determine whether the authentication is disabled dynamically.
41209a60ccSSoby Mathew  *****************************************************************************/
dyn_is_auth_disabled(void)42209a60ccSSoby Mathew static int dyn_is_auth_disabled(void)
43209a60ccSSoby Mathew {
44209a60ccSSoby Mathew # ifdef DYN_DISABLE_AUTH
45209a60ccSSoby Mathew 	return disable_auth;
46209a60ccSSoby Mathew # else
47209a60ccSSoby Mathew 	return 0;
48209a60ccSSoby Mathew # endif
49209a60ccSSoby Mathew }
50209a60ccSSoby Mathew #endif /* TRUSTED_BOARD_BOOT */
51209a60ccSSoby Mathew 
page_align(uintptr_t value,unsigned dir)524c0d0390SSoby Mathew uintptr_t page_align(uintptr_t value, unsigned dir)
534f6ad66aSAchin Gupta {
544f6ad66aSAchin Gupta 	/* Round up the limit to the next page boundary */
55d7b5f408SJimmy Brisson 	if ((value & PAGE_SIZE_MASK) != 0U) {
56d7b5f408SJimmy Brisson 		value &= ~PAGE_SIZE_MASK;
57618e37c3SSaivardhan Thatikonda 		if (dir == UP) {
584c0d0390SSoby Mathew 			value += PAGE_SIZE;
594f6ad66aSAchin Gupta 		}
60618e37c3SSaivardhan Thatikonda 	}
614f6ad66aSAchin Gupta 
624f6ad66aSAchin Gupta 	return value;
634f6ad66aSAchin Gupta }
644f6ad66aSAchin Gupta 
6572600226SYatharth Kochar /*******************************************************************************
6676163b3aSSoby Mathew  * Internal function to load an image at a specific address given
6772600226SYatharth Kochar  * an image ID and extents of free memory.
6872600226SYatharth Kochar  *
6972600226SYatharth Kochar  * If the load is successful then the image information is updated.
7072600226SYatharth Kochar  *
7172600226SYatharth Kochar  * Returns 0 on success, a negative error code otherwise.
7272600226SYatharth Kochar  ******************************************************************************/
load_image(unsigned int image_id,image_info_t * image_data)7376163b3aSSoby Mathew static int load_image(unsigned int image_id, image_info_t *image_data)
7472600226SYatharth Kochar {
75929a290eSSaivardhan Thatikonda 	uintptr_t dev_handle = 0ULL;
76929a290eSSaivardhan Thatikonda 	uintptr_t image_handle = 0ULL;
77929a290eSSaivardhan Thatikonda 	uintptr_t image_spec = 0ULL;
7872600226SYatharth Kochar 	uintptr_t image_base;
79929a290eSSaivardhan Thatikonda 	size_t image_size = 0ULL;
80929a290eSSaivardhan Thatikonda 	size_t bytes_read = 0ULL;
8172600226SYatharth Kochar 	int io_result;
8272600226SYatharth Kochar 
8372600226SYatharth Kochar 	assert(image_data != NULL);
8472600226SYatharth Kochar 	assert(image_data->h.version >= VERSION_2);
8572600226SYatharth Kochar 
8672600226SYatharth Kochar 	image_base = image_data->image_base;
8772600226SYatharth Kochar 
8872600226SYatharth Kochar 	/* Obtain a reference to the image by querying the platform layer */
8972600226SYatharth Kochar 	io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
9072600226SYatharth Kochar 	if (io_result != 0) {
9172600226SYatharth Kochar 		WARN("Failed to obtain reference to image id=%u (%i)\n",
9272600226SYatharth Kochar 			image_id, io_result);
9372600226SYatharth Kochar 		return io_result;
9472600226SYatharth Kochar 	}
9572600226SYatharth Kochar 
9672600226SYatharth Kochar 	/* Attempt to access the image */
9772600226SYatharth Kochar 	io_result = io_open(dev_handle, image_spec, &image_handle);
9872600226SYatharth Kochar 	if (io_result != 0) {
9972600226SYatharth Kochar 		WARN("Failed to access image id=%u (%i)\n",
10072600226SYatharth Kochar 			image_id, io_result);
10172600226SYatharth Kochar 		return io_result;
10272600226SYatharth Kochar 	}
10372600226SYatharth Kochar 
10481542c00SAntonio Nino Diaz 	INFO("Loading image id=%u at address 0x%lx\n", image_id, image_base);
10572600226SYatharth Kochar 
10672600226SYatharth Kochar 	/* Find the size of the image */
10772600226SYatharth Kochar 	io_result = io_size(image_handle, &image_size);
108*854b4dd9SToshiyuki Ogasahara 	if (io_result != 0) {
10972600226SYatharth Kochar 		WARN("Failed to determine the size of the image id=%u (%i)\n",
11072600226SYatharth Kochar 			image_id, io_result);
1111db51f0aSSaivardhan Thatikonda 		goto exit_load_image;
11272600226SYatharth Kochar 	}
11372600226SYatharth Kochar 
114*854b4dd9SToshiyuki Ogasahara 	if (image_size == 0U) {
115*854b4dd9SToshiyuki Ogasahara 		WARN("image id=%u size is zero\n", image_id);
116*854b4dd9SToshiyuki Ogasahara 		io_result = -EIO;
117*854b4dd9SToshiyuki Ogasahara 		goto exit_load_image;
118*854b4dd9SToshiyuki Ogasahara 	}
119*854b4dd9SToshiyuki Ogasahara 
12072600226SYatharth Kochar 	/* Check that the image size to load is within limit */
12172600226SYatharth Kochar 	if (image_size > image_data->image_max_size) {
12272600226SYatharth Kochar 		WARN("Image id=%u size out of bounds\n", image_id);
12372600226SYatharth Kochar 		io_result = -EFBIG;
1241db51f0aSSaivardhan Thatikonda 		goto exit_load_image;
12572600226SYatharth Kochar 	}
12672600226SYatharth Kochar 
12781542c00SAntonio Nino Diaz 	/*
12881542c00SAntonio Nino Diaz 	 * image_data->image_max_size is a uint32_t so image_size will always
12981542c00SAntonio Nino Diaz 	 * fit in image_data->image_size.
13081542c00SAntonio Nino Diaz 	 */
13181542c00SAntonio Nino Diaz 	image_data->image_size = (uint32_t)image_size;
13272600226SYatharth Kochar 
13372600226SYatharth Kochar 	/* We have enough space so load the image now */
13472600226SYatharth Kochar 	/* TODO: Consider whether to try to recover/retry a partially successful read */
13572600226SYatharth Kochar 	io_result = io_read(image_handle, image_base, image_size, &bytes_read);
13672600226SYatharth Kochar 	if ((io_result != 0) || (bytes_read < image_size)) {
13772600226SYatharth Kochar 		WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
1381db51f0aSSaivardhan Thatikonda 		goto exit_load_image;
13972600226SYatharth Kochar 	}
14072600226SYatharth Kochar 
14181542c00SAntonio Nino Diaz 	INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base,
14281542c00SAntonio Nino Diaz 	     (uintptr_t)(image_base + image_size));
14372600226SYatharth Kochar 
1441db51f0aSSaivardhan Thatikonda exit_load_image:
14581542c00SAntonio Nino Diaz 	(void)io_close(image_handle);
14672600226SYatharth Kochar 	/* Ignore improbable/unrecoverable error in 'close' */
14772600226SYatharth Kochar 
14872600226SYatharth Kochar 	/* TODO: Consider maintaining open device connection from this bootloader stage */
14981542c00SAntonio Nino Diaz 	(void)io_dev_close(dev_handle);
15072600226SYatharth Kochar 	/* Ignore improbable/unrecoverable error in 'dev_close' */
15172600226SYatharth Kochar 
15272600226SYatharth Kochar 	return io_result;
15372600226SYatharth Kochar }
15472600226SYatharth Kochar 
1559e7d6631SSandrine Bailleux #if TRUSTED_BOARD_BOOT
1569e7d6631SSandrine Bailleux /*
1579e7d6631SSandrine Bailleux  * This function uses recursion to authenticate the parent images up to the root
1589e7d6631SSandrine Bailleux  * of trust.
1599e7d6631SSandrine Bailleux  */
load_auth_image_recursive(unsigned int image_id,image_info_t * image_data)1609e7d6631SSandrine Bailleux static int load_auth_image_recursive(unsigned int image_id,
161800ba70bSManish V Badarkhe 				    image_info_t *image_data)
16272600226SYatharth Kochar {
16372600226SYatharth Kochar 	int rc;
16472600226SYatharth Kochar 	unsigned int parent_id;
16572600226SYatharth Kochar 
16672600226SYatharth Kochar 	/* Use recursion to authenticate parent images */
16772600226SYatharth Kochar 	rc = auth_mod_get_parent_id(image_id, &parent_id);
16872600226SYatharth Kochar 	if (rc == 0) {
169800ba70bSManish V Badarkhe 		rc = load_auth_image_recursive(parent_id, image_data);
17072600226SYatharth Kochar 		if (rc != 0) {
17172600226SYatharth Kochar 			return rc;
17272600226SYatharth Kochar 		}
17372600226SYatharth Kochar 	}
17472600226SYatharth Kochar 
17572600226SYatharth Kochar 	/* Load the image */
17672600226SYatharth Kochar 	rc = load_image(image_id, image_data);
17772600226SYatharth Kochar 	if (rc != 0) {
17872600226SYatharth Kochar 		return rc;
17972600226SYatharth Kochar 	}
18072600226SYatharth Kochar 
18172600226SYatharth Kochar 	/* Authenticate it */
18272600226SYatharth Kochar 	rc = auth_mod_verify_img(image_id,
18372600226SYatharth Kochar 				 (void *)image_data->image_base,
18472600226SYatharth Kochar 				 image_data->image_size);
18572600226SYatharth Kochar 	if (rc != 0) {
1860f325c67SAntonio Nino Diaz 		/* Authentication error, zero memory and flush it right away. */
187308d359bSDouglas Raillard 		zero_normalmem((void *)image_data->image_base,
18872600226SYatharth Kochar 			       image_data->image_size);
18972600226SYatharth Kochar 		flush_dcache_range(image_data->image_base,
19072600226SYatharth Kochar 				   image_data->image_size);
19172600226SYatharth Kochar 		return -EAUTH;
19272600226SYatharth Kochar 	}
19372600226SYatharth Kochar 
19472600226SYatharth Kochar 	return 0;
19572600226SYatharth Kochar }
1969e7d6631SSandrine Bailleux #endif /* TRUSTED_BOARD_BOOT */
1979e7d6631SSandrine Bailleux 
load_auth_image_internal(unsigned int image_id,image_info_t * image_data)1989e7d6631SSandrine Bailleux static int load_auth_image_internal(unsigned int image_id,
1999e7d6631SSandrine Bailleux 				    image_info_t *image_data)
2009e7d6631SSandrine Bailleux {
2019e7d6631SSandrine Bailleux #if TRUSTED_BOARD_BOOT
2029e7d6631SSandrine Bailleux 	if (dyn_is_auth_disabled() == 0) {
203800ba70bSManish V Badarkhe 		return load_auth_image_recursive(image_id, image_data);
2049e7d6631SSandrine Bailleux 	}
2059e7d6631SSandrine Bailleux #endif
2069e7d6631SSandrine Bailleux 
2070aa0b3afSManish V Badarkhe 	return load_image(image_id, image_data);
2089e7d6631SSandrine Bailleux }
20972600226SYatharth Kochar 
2100f325c67SAntonio Nino Diaz /*******************************************************************************
2110f325c67SAntonio Nino Diaz  * Generic function to load and authenticate an image. The image is actually
2120f325c67SAntonio Nino Diaz  * loaded by calling the 'load_image()' function. Therefore, it returns the
2130f325c67SAntonio Nino Diaz  * same error codes if the loading operation failed, or -EAUTH if the
2140f325c67SAntonio Nino Diaz  * authentication failed. In addition, this function uses recursion to
2159e7d6631SSandrine Bailleux  * authenticate the parent images up to the root of trust (if TBB is enabled).
2160f325c67SAntonio Nino Diaz  ******************************************************************************/
load_auth_image(unsigned int image_id,image_info_t * image_data)2170f325c67SAntonio Nino Diaz int load_auth_image(unsigned int image_id, image_info_t *image_data)
2180f325c67SAntonio Nino Diaz {
21901f62b6dSRoberto Vargas 	int err;
22001f62b6dSRoberto Vargas 
221a03dafe5SYann Gautier 	if ((plat_try_img_ops == NULL) || (plat_try_img_ops->next_instance == NULL)) {
2224b48f7b5SManish V Badarkhe 		err = load_auth_image_internal(image_id, image_data);
223a03dafe5SYann Gautier 	} else {
224a03dafe5SYann Gautier 		do {
225a03dafe5SYann Gautier 			err = load_auth_image_internal(image_id, image_data);
226a03dafe5SYann Gautier 			if (err != 0) {
227a03dafe5SYann Gautier 				if (plat_try_img_ops->next_instance(image_id) != 0) {
228a03dafe5SYann Gautier 					return err;
229a03dafe5SYann Gautier 				}
230a03dafe5SYann Gautier 			}
231a03dafe5SYann Gautier 		} while (err != 0);
232a03dafe5SYann Gautier 	}
23301f62b6dSRoberto Vargas 
2340aa0b3afSManish V Badarkhe 	if (err == 0) {
2350aa0b3afSManish V Badarkhe 		/*
2360aa0b3afSManish V Badarkhe 		 * If loading of the image gets passed (along with its
2370aa0b3afSManish V Badarkhe 		 * authentication in case of Trusted-Boot flow) then measure
2380aa0b3afSManish V Badarkhe 		 * it (if MEASURED_BOOT flag is enabled).
2390aa0b3afSManish V Badarkhe 		 */
2400aa0b3afSManish V Badarkhe 		err = plat_mboot_measure_image(image_id, image_data);
2410aa0b3afSManish V Badarkhe 		if (err != 0) {
2420aa0b3afSManish V Badarkhe 			return err;
2430aa0b3afSManish V Badarkhe 		}
2440aa0b3afSManish V Badarkhe 
2450aa0b3afSManish V Badarkhe 		/*
2460aa0b3afSManish V Badarkhe 		 * Flush the image to main memory so that it can be executed
2470aa0b3afSManish V Badarkhe 		 * later by any CPU, regardless of cache and MMU state.
2480aa0b3afSManish V Badarkhe 		 */
2490aa0b3afSManish V Badarkhe 		flush_dcache_range(image_data->image_base,
2500aa0b3afSManish V Badarkhe 				   image_data->image_size);
2510aa0b3afSManish V Badarkhe 	}
2520aa0b3afSManish V Badarkhe 
25301f62b6dSRoberto Vargas 	return err;
2540f325c67SAntonio Nino Diaz }
2550f325c67SAntonio Nino Diaz 
25668a68c92SSandrine Bailleux /*******************************************************************************
25768a68c92SSandrine Bailleux  * Print the content of an entry_point_info_t structure.
25868a68c92SSandrine Bailleux  ******************************************************************************/
print_entry_point_info(const entry_point_info_t * ep_info)25968a68c92SSandrine Bailleux void print_entry_point_info(const entry_point_info_t *ep_info)
26068a68c92SSandrine Bailleux {
26181542c00SAntonio Nino Diaz 	INFO("Entry point address = 0x%lx\n", ep_info->pc);
2624c0d0390SSoby Mathew 	INFO("SPSR = 0x%x\n", ep_info->spsr);
26368a68c92SSandrine Bailleux 
26468a68c92SSandrine Bailleux #define PRINT_IMAGE_ARG(n)					\
26568a68c92SSandrine Bailleux 	VERBOSE("Argument #" #n " = 0x%llx\n",			\
26668a68c92SSandrine Bailleux 		(unsigned long long) ep_info->args.arg##n)
26768a68c92SSandrine Bailleux 
26868a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(0);
26968a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(1);
27068a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(2);
27168a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(3);
272402b3cf8SJulius Werner #ifdef __aarch64__
27368a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(4);
27468a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(5);
27568a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(6);
27668a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(7);
27751c79b73SSoby Mathew #endif
27868a68c92SSandrine Bailleux #undef PRINT_IMAGE_ARG
27968a68c92SSandrine Bailleux }
280dddf4283Slaurenw-arm 
281dddf4283Slaurenw-arm /*
282dddf4283Slaurenw-arm  * This function is for returning the TF-A version
283dddf4283Slaurenw-arm  */
get_version(void)284dddf4283Slaurenw-arm const char *get_version(void)
285dddf4283Slaurenw-arm {
286758ccb80SChris Kay 	return build_version;
287dddf4283Slaurenw-arm }
288