xref: /rk3399_ARM-atf/common/bl_common.c (revision 402b3cf8766fe2cb4ae462f7ee7761d08a1ba56c)
14f6ad66aSAchin Gupta /*
2b86048c4SAntonio Nino Diaz  * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
34f6ad66aSAchin Gupta  *
482cb2c1aSdp-arm  * SPDX-License-Identifier: BSD-3-Clause
54f6ad66aSAchin Gupta  */
64f6ad66aSAchin Gupta 
709d40e0eSAntonio Nino Diaz #include <assert.h>
809d40e0eSAntonio Nino Diaz #include <errno.h>
909d40e0eSAntonio Nino Diaz #include <string.h>
1009d40e0eSAntonio Nino Diaz 
1197043ac9SDan Handley #include <arch.h>
12b86048c4SAntonio Nino Diaz #include <arch_features.h>
134f6ad66aSAchin Gupta #include <arch_helpers.h>
1409d40e0eSAntonio Nino Diaz #include <common/bl_common.h>
1509d40e0eSAntonio Nino Diaz #include <common/debug.h>
1609d40e0eSAntonio Nino Diaz #include <drivers/auth/auth_mod.h>
1709d40e0eSAntonio Nino Diaz #include <drivers/io/io_storage.h>
1809d40e0eSAntonio Nino Diaz #include <lib/utils.h>
1909d40e0eSAntonio Nino Diaz #include <lib/xlat_tables/xlat_tables_defs.h>
2009d40e0eSAntonio Nino Diaz #include <plat/common/platform.h>
214f6ad66aSAchin Gupta 
22209a60ccSSoby Mathew #if TRUSTED_BOARD_BOOT
23209a60ccSSoby Mathew # ifdef DYN_DISABLE_AUTH
24209a60ccSSoby Mathew static int disable_auth;
25209a60ccSSoby Mathew 
26209a60ccSSoby Mathew /******************************************************************************
27209a60ccSSoby Mathew  * API to dynamically disable authentication. Only meant for development
28ed51b51fSRoberto Vargas  * systems. This is only invoked if DYN_DISABLE_AUTH is defined.
29209a60ccSSoby Mathew  *****************************************************************************/
30209a60ccSSoby Mathew void dyn_disable_auth(void)
31209a60ccSSoby Mathew {
32209a60ccSSoby Mathew 	INFO("Disabling authentication of images dynamically\n");
33209a60ccSSoby Mathew 	disable_auth = 1;
34209a60ccSSoby Mathew }
35209a60ccSSoby Mathew # endif /* DYN_DISABLE_AUTH */
36209a60ccSSoby Mathew 
37209a60ccSSoby Mathew /******************************************************************************
38209a60ccSSoby Mathew  * Function to determine whether the authentication is disabled dynamically.
39209a60ccSSoby Mathew  *****************************************************************************/
40209a60ccSSoby Mathew static int dyn_is_auth_disabled(void)
41209a60ccSSoby Mathew {
42209a60ccSSoby Mathew # ifdef DYN_DISABLE_AUTH
43209a60ccSSoby Mathew 	return disable_auth;
44209a60ccSSoby Mathew # else
45209a60ccSSoby Mathew 	return 0;
46209a60ccSSoby Mathew # endif
47209a60ccSSoby Mathew }
48209a60ccSSoby Mathew #endif /* TRUSTED_BOARD_BOOT */
49209a60ccSSoby Mathew 
504c0d0390SSoby Mathew uintptr_t page_align(uintptr_t value, unsigned dir)
514f6ad66aSAchin Gupta {
524f6ad66aSAchin Gupta 	/* Round up the limit to the next page boundary */
5381542c00SAntonio Nino Diaz 	if ((value & (PAGE_SIZE - 1U)) != 0U) {
5481542c00SAntonio Nino Diaz 		value &= ~(PAGE_SIZE - 1U);
554f6ad66aSAchin Gupta 		if (dir == UP)
564c0d0390SSoby Mathew 			value += PAGE_SIZE;
574f6ad66aSAchin Gupta 	}
584f6ad66aSAchin Gupta 
594f6ad66aSAchin Gupta 	return value;
604f6ad66aSAchin Gupta }
614f6ad66aSAchin Gupta 
6272600226SYatharth Kochar /*******************************************************************************
6376163b3aSSoby Mathew  * Internal function to load an image at a specific address given
6472600226SYatharth Kochar  * an image ID and extents of free memory.
6572600226SYatharth Kochar  *
6672600226SYatharth Kochar  * If the load is successful then the image information is updated.
6772600226SYatharth Kochar  *
6872600226SYatharth Kochar  * Returns 0 on success, a negative error code otherwise.
6972600226SYatharth Kochar  ******************************************************************************/
7076163b3aSSoby Mathew static int load_image(unsigned int image_id, image_info_t *image_data)
7172600226SYatharth Kochar {
7272600226SYatharth Kochar 	uintptr_t dev_handle;
7372600226SYatharth Kochar 	uintptr_t image_handle;
7472600226SYatharth Kochar 	uintptr_t image_spec;
7572600226SYatharth Kochar 	uintptr_t image_base;
7672600226SYatharth Kochar 	size_t image_size;
7772600226SYatharth Kochar 	size_t bytes_read;
7872600226SYatharth Kochar 	int io_result;
7972600226SYatharth Kochar 
8072600226SYatharth Kochar 	assert(image_data != NULL);
8172600226SYatharth Kochar 	assert(image_data->h.version >= VERSION_2);
8272600226SYatharth Kochar 
8372600226SYatharth Kochar 	image_base = image_data->image_base;
8472600226SYatharth Kochar 
8572600226SYatharth Kochar 	/* Obtain a reference to the image by querying the platform layer */
8672600226SYatharth Kochar 	io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
8772600226SYatharth Kochar 	if (io_result != 0) {
8872600226SYatharth Kochar 		WARN("Failed to obtain reference to image id=%u (%i)\n",
8972600226SYatharth Kochar 			image_id, io_result);
9072600226SYatharth Kochar 		return io_result;
9172600226SYatharth Kochar 	}
9272600226SYatharth Kochar 
9372600226SYatharth Kochar 	/* Attempt to access the image */
9472600226SYatharth Kochar 	io_result = io_open(dev_handle, image_spec, &image_handle);
9572600226SYatharth Kochar 	if (io_result != 0) {
9672600226SYatharth Kochar 		WARN("Failed to access image id=%u (%i)\n",
9772600226SYatharth Kochar 			image_id, io_result);
9872600226SYatharth Kochar 		return io_result;
9972600226SYatharth Kochar 	}
10072600226SYatharth Kochar 
10181542c00SAntonio Nino Diaz 	INFO("Loading image id=%u at address 0x%lx\n", image_id, image_base);
10272600226SYatharth Kochar 
10372600226SYatharth Kochar 	/* Find the size of the image */
10472600226SYatharth Kochar 	io_result = io_size(image_handle, &image_size);
10581542c00SAntonio Nino Diaz 	if ((io_result != 0) || (image_size == 0U)) {
10672600226SYatharth Kochar 		WARN("Failed to determine the size of the image id=%u (%i)\n",
10772600226SYatharth Kochar 			image_id, io_result);
10872600226SYatharth Kochar 		goto exit;
10972600226SYatharth Kochar 	}
11072600226SYatharth Kochar 
11172600226SYatharth Kochar 	/* Check that the image size to load is within limit */
11272600226SYatharth Kochar 	if (image_size > image_data->image_max_size) {
11372600226SYatharth Kochar 		WARN("Image id=%u size out of bounds\n", image_id);
11472600226SYatharth Kochar 		io_result = -EFBIG;
11572600226SYatharth Kochar 		goto exit;
11672600226SYatharth Kochar 	}
11772600226SYatharth Kochar 
11881542c00SAntonio Nino Diaz 	/*
11981542c00SAntonio Nino Diaz 	 * image_data->image_max_size is a uint32_t so image_size will always
12081542c00SAntonio Nino Diaz 	 * fit in image_data->image_size.
12181542c00SAntonio Nino Diaz 	 */
12281542c00SAntonio Nino Diaz 	image_data->image_size = (uint32_t)image_size;
12372600226SYatharth Kochar 
12472600226SYatharth Kochar 	/* We have enough space so load the image now */
12572600226SYatharth Kochar 	/* TODO: Consider whether to try to recover/retry a partially successful read */
12672600226SYatharth Kochar 	io_result = io_read(image_handle, image_base, image_size, &bytes_read);
12772600226SYatharth Kochar 	if ((io_result != 0) || (bytes_read < image_size)) {
12872600226SYatharth Kochar 		WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
12972600226SYatharth Kochar 		goto exit;
13072600226SYatharth Kochar 	}
13172600226SYatharth Kochar 
13281542c00SAntonio Nino Diaz 	INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base,
13381542c00SAntonio Nino Diaz 	     (uintptr_t)(image_base + image_size));
13472600226SYatharth Kochar 
13572600226SYatharth Kochar exit:
13681542c00SAntonio Nino Diaz 	(void)io_close(image_handle);
13772600226SYatharth Kochar 	/* Ignore improbable/unrecoverable error in 'close' */
13872600226SYatharth Kochar 
13972600226SYatharth Kochar 	/* TODO: Consider maintaining open device connection from this bootloader stage */
14081542c00SAntonio Nino Diaz 	(void)io_dev_close(dev_handle);
14172600226SYatharth Kochar 	/* Ignore improbable/unrecoverable error in 'dev_close' */
14272600226SYatharth Kochar 
14372600226SYatharth Kochar 	return io_result;
14472600226SYatharth Kochar }
14572600226SYatharth Kochar 
1460f325c67SAntonio Nino Diaz static int load_auth_image_internal(unsigned int image_id,
1470f325c67SAntonio Nino Diaz 				    image_info_t *image_data,
1480f325c67SAntonio Nino Diaz 				    int is_parent_image)
14972600226SYatharth Kochar {
15072600226SYatharth Kochar 	int rc;
15172600226SYatharth Kochar 
15272600226SYatharth Kochar #if TRUSTED_BOARD_BOOT
153209a60ccSSoby Mathew 	if (dyn_is_auth_disabled() == 0) {
15472600226SYatharth Kochar 		unsigned int parent_id;
15572600226SYatharth Kochar 
15672600226SYatharth Kochar 		/* Use recursion to authenticate parent images */
15772600226SYatharth Kochar 		rc = auth_mod_get_parent_id(image_id, &parent_id);
15872600226SYatharth Kochar 		if (rc == 0) {
1590f325c67SAntonio Nino Diaz 			rc = load_auth_image_internal(parent_id, image_data, 1);
16072600226SYatharth Kochar 			if (rc != 0) {
16172600226SYatharth Kochar 				return rc;
16272600226SYatharth Kochar 			}
16372600226SYatharth Kochar 		}
164209a60ccSSoby Mathew 	}
16572600226SYatharth Kochar #endif /* TRUSTED_BOARD_BOOT */
16672600226SYatharth Kochar 
16772600226SYatharth Kochar 	/* Load the image */
16872600226SYatharth Kochar 	rc = load_image(image_id, image_data);
16972600226SYatharth Kochar 	if (rc != 0) {
17072600226SYatharth Kochar 		return rc;
17172600226SYatharth Kochar 	}
17272600226SYatharth Kochar 
17372600226SYatharth Kochar #if TRUSTED_BOARD_BOOT
174209a60ccSSoby Mathew 	if (dyn_is_auth_disabled() == 0) {
17572600226SYatharth Kochar 		/* Authenticate it */
17672600226SYatharth Kochar 		rc = auth_mod_verify_img(image_id,
17772600226SYatharth Kochar 					 (void *)image_data->image_base,
17872600226SYatharth Kochar 					 image_data->image_size);
17972600226SYatharth Kochar 		if (rc != 0) {
1800f325c67SAntonio Nino Diaz 			/* Authentication error, zero memory and flush it right away. */
181308d359bSDouglas Raillard 			zero_normalmem((void *)image_data->image_base,
18272600226SYatharth Kochar 			       image_data->image_size);
18372600226SYatharth Kochar 			flush_dcache_range(image_data->image_base,
18472600226SYatharth Kochar 					   image_data->image_size);
18572600226SYatharth Kochar 			return -EAUTH;
18672600226SYatharth Kochar 		}
187209a60ccSSoby Mathew 	}
18876163b3aSSoby Mathew #endif /* TRUSTED_BOARD_BOOT */
18972600226SYatharth Kochar 
19072600226SYatharth Kochar 	/*
19172600226SYatharth Kochar 	 * Flush the image to main memory so that it can be executed later by
19276163b3aSSoby Mathew 	 * any CPU, regardless of cache and MMU state. If TBB is enabled, then
19376163b3aSSoby Mathew 	 * the file has been successfully loaded and authenticated and flush
19476163b3aSSoby Mathew 	 * only for child images, not for the parents (certificates).
19572600226SYatharth Kochar 	 */
19681542c00SAntonio Nino Diaz 	if (is_parent_image == 0) {
1970f325c67SAntonio Nino Diaz 		flush_dcache_range(image_data->image_base,
1980f325c67SAntonio Nino Diaz 				   image_data->image_size);
1990f325c67SAntonio Nino Diaz 	}
20076163b3aSSoby Mathew 
20172600226SYatharth Kochar 
20272600226SYatharth Kochar 	return 0;
20372600226SYatharth Kochar }
20472600226SYatharth Kochar 
2050f325c67SAntonio Nino Diaz /*******************************************************************************
2060f325c67SAntonio Nino Diaz  * Generic function to load and authenticate an image. The image is actually
2070f325c67SAntonio Nino Diaz  * loaded by calling the 'load_image()' function. Therefore, it returns the
2080f325c67SAntonio Nino Diaz  * same error codes if the loading operation failed, or -EAUTH if the
2090f325c67SAntonio Nino Diaz  * authentication failed. In addition, this function uses recursion to
2100f325c67SAntonio Nino Diaz  * authenticate the parent images up to the root of trust.
2110f325c67SAntonio Nino Diaz  ******************************************************************************/
2120f325c67SAntonio Nino Diaz int load_auth_image(unsigned int image_id, image_info_t *image_data)
2130f325c67SAntonio Nino Diaz {
21401f62b6dSRoberto Vargas 	int err;
21501f62b6dSRoberto Vargas 
21601f62b6dSRoberto Vargas 	do {
21701f62b6dSRoberto Vargas 		err = load_auth_image_internal(image_id, image_data, 0);
21881542c00SAntonio Nino Diaz 	} while ((err != 0) && (plat_try_next_boot_source() != 0));
21901f62b6dSRoberto Vargas 
22001f62b6dSRoberto Vargas 	return err;
2210f325c67SAntonio Nino Diaz }
2220f325c67SAntonio Nino Diaz 
22368a68c92SSandrine Bailleux /*******************************************************************************
22468a68c92SSandrine Bailleux  * Print the content of an entry_point_info_t structure.
22568a68c92SSandrine Bailleux  ******************************************************************************/
22668a68c92SSandrine Bailleux void print_entry_point_info(const entry_point_info_t *ep_info)
22768a68c92SSandrine Bailleux {
22881542c00SAntonio Nino Diaz 	INFO("Entry point address = 0x%lx\n", ep_info->pc);
2294c0d0390SSoby Mathew 	INFO("SPSR = 0x%x\n", ep_info->spsr);
23068a68c92SSandrine Bailleux 
23168a68c92SSandrine Bailleux #define PRINT_IMAGE_ARG(n)					\
23268a68c92SSandrine Bailleux 	VERBOSE("Argument #" #n " = 0x%llx\n",			\
23368a68c92SSandrine Bailleux 		(unsigned long long) ep_info->args.arg##n)
23468a68c92SSandrine Bailleux 
23568a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(0);
23668a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(1);
23768a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(2);
23868a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(3);
239*402b3cf8SJulius Werner #ifdef __aarch64__
24068a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(4);
24168a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(5);
24268a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(6);
24368a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(7);
24451c79b73SSoby Mathew #endif
24568a68c92SSandrine Bailleux #undef PRINT_IMAGE_ARG
24668a68c92SSandrine Bailleux }
247b86048c4SAntonio Nino Diaz 
248*402b3cf8SJulius Werner #ifdef __aarch64__
249b86048c4SAntonio Nino Diaz /*******************************************************************************
250b86048c4SAntonio Nino Diaz  * Handle all possible cases regarding ARMv8.3-PAuth.
251b86048c4SAntonio Nino Diaz  ******************************************************************************/
252b86048c4SAntonio Nino Diaz void bl_handle_pauth(void)
253b86048c4SAntonio Nino Diaz {
254b86048c4SAntonio Nino Diaz #if ENABLE_PAUTH
255b86048c4SAntonio Nino Diaz 	/*
256b86048c4SAntonio Nino Diaz 	 * ENABLE_PAUTH = 1 && CTX_INCLUDE_PAUTH_REGS = 1
257b86048c4SAntonio Nino Diaz 	 *
258b86048c4SAntonio Nino Diaz 	 * Check that the system supports address authentication to avoid
259b86048c4SAntonio Nino Diaz 	 * getting an access fault when accessing the registers. This is all
260b86048c4SAntonio Nino Diaz 	 * that is needed to check. If any of the authentication mechanisms is
261b86048c4SAntonio Nino Diaz 	 * supported, the system knows about ARMv8.3-PAuth, so all the registers
262b86048c4SAntonio Nino Diaz 	 * are available and accessing them won't generate a fault.
263b86048c4SAntonio Nino Diaz 	 *
264b86048c4SAntonio Nino Diaz 	 * Obtain 128-bit instruction key A from the platform and save it to the
265b86048c4SAntonio Nino Diaz 	 * system registers. Pointer authentication can't be enabled here or the
266b86048c4SAntonio Nino Diaz 	 * authentication will fail when returning from this function.
267b86048c4SAntonio Nino Diaz 	 */
268b6fd4183SAntonio Nino Diaz 	assert(is_armv8_3_pauth_apa_api_present());
269b86048c4SAntonio Nino Diaz 
270b86048c4SAntonio Nino Diaz 	uint64_t *apiakey = plat_init_apiakey();
271b86048c4SAntonio Nino Diaz 
272b86048c4SAntonio Nino Diaz 	write_apiakeylo_el1(apiakey[0]);
273b86048c4SAntonio Nino Diaz 	write_apiakeyhi_el1(apiakey[1]);
274b86048c4SAntonio Nino Diaz #else /* if !ENABLE_PAUTH */
275b86048c4SAntonio Nino Diaz 
276b86048c4SAntonio Nino Diaz # if CTX_INCLUDE_PAUTH_REGS
277b86048c4SAntonio Nino Diaz 	/*
278b86048c4SAntonio Nino Diaz 	 * ENABLE_PAUTH = 0 && CTX_INCLUDE_PAUTH_REGS = 1
279b86048c4SAntonio Nino Diaz 	 *
280b86048c4SAntonio Nino Diaz 	 * Assert that the ARMv8.3-PAuth registers are present or an access
281b86048c4SAntonio Nino Diaz 	 * fault will be triggered when they are being saved or restored.
282b86048c4SAntonio Nino Diaz 	 */
283b86048c4SAntonio Nino Diaz 	assert(is_armv8_3_pauth_present());
284b86048c4SAntonio Nino Diaz # else
285b86048c4SAntonio Nino Diaz 	/*
286b86048c4SAntonio Nino Diaz 	 * ENABLE_PAUTH = 0 && CTX_INCLUDE_PAUTH_REGS = 0
287b86048c4SAntonio Nino Diaz 	 *
288b86048c4SAntonio Nino Diaz 	 * Pointer authentication is allowed in the Non-secure world, but
289b86048c4SAntonio Nino Diaz 	 * prohibited in the Secure world. The Trusted Firmware doesn't save the
290b86048c4SAntonio Nino Diaz 	 * registers during a world switch. No check needed.
291b86048c4SAntonio Nino Diaz 	 */
292b86048c4SAntonio Nino Diaz # endif /* CTX_INCLUDE_PAUTH_REGS */
293b86048c4SAntonio Nino Diaz 
294b86048c4SAntonio Nino Diaz #endif /* ENABLE_PAUTH */
295b86048c4SAntonio Nino Diaz }
296*402b3cf8SJulius Werner #endif /* __aarch64__ */
297