xref: /rk3399_ARM-atf/common/bl_common.c (revision 09d40e0e08283a249e7dce0e106c07c5141f9b7e)
14f6ad66aSAchin Gupta /*
2209a60ccSSoby Mathew  * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
34f6ad66aSAchin Gupta  *
482cb2c1aSdp-arm  * SPDX-License-Identifier: BSD-3-Clause
54f6ad66aSAchin Gupta  */
64f6ad66aSAchin Gupta 
7*09d40e0eSAntonio Nino Diaz #include <assert.h>
8*09d40e0eSAntonio Nino Diaz #include <errno.h>
9*09d40e0eSAntonio Nino Diaz #include <string.h>
10*09d40e0eSAntonio Nino Diaz 
1197043ac9SDan Handley #include <arch.h>
124f6ad66aSAchin Gupta #include <arch_helpers.h>
13*09d40e0eSAntonio Nino Diaz #include <common/bl_common.h>
14*09d40e0eSAntonio Nino Diaz #include <common/debug.h>
15*09d40e0eSAntonio Nino Diaz #include <drivers/auth/auth_mod.h>
16*09d40e0eSAntonio Nino Diaz #include <drivers/io/io_storage.h>
17*09d40e0eSAntonio Nino Diaz #include <lib/utils.h>
18*09d40e0eSAntonio Nino Diaz #include <lib/xlat_tables/xlat_tables_defs.h>
19*09d40e0eSAntonio Nino Diaz #include <plat/common/platform.h>
204f6ad66aSAchin Gupta 
21209a60ccSSoby Mathew #if TRUSTED_BOARD_BOOT
22209a60ccSSoby Mathew # ifdef DYN_DISABLE_AUTH
23209a60ccSSoby Mathew static int disable_auth;
24209a60ccSSoby Mathew 
25209a60ccSSoby Mathew /******************************************************************************
26209a60ccSSoby Mathew  * API to dynamically disable authentication. Only meant for development
27ed51b51fSRoberto Vargas  * systems. This is only invoked if DYN_DISABLE_AUTH is defined.
28209a60ccSSoby Mathew  *****************************************************************************/
29209a60ccSSoby Mathew void dyn_disable_auth(void)
30209a60ccSSoby Mathew {
31209a60ccSSoby Mathew 	INFO("Disabling authentication of images dynamically\n");
32209a60ccSSoby Mathew 	disable_auth = 1;
33209a60ccSSoby Mathew }
34209a60ccSSoby Mathew # endif /* DYN_DISABLE_AUTH */
35209a60ccSSoby Mathew 
36209a60ccSSoby Mathew /******************************************************************************
37209a60ccSSoby Mathew  * Function to determine whether the authentication is disabled dynamically.
38209a60ccSSoby Mathew  *****************************************************************************/
39209a60ccSSoby Mathew static int dyn_is_auth_disabled(void)
40209a60ccSSoby Mathew {
41209a60ccSSoby Mathew # ifdef DYN_DISABLE_AUTH
42209a60ccSSoby Mathew 	return disable_auth;
43209a60ccSSoby Mathew # else
44209a60ccSSoby Mathew 	return 0;
45209a60ccSSoby Mathew # endif
46209a60ccSSoby Mathew }
47209a60ccSSoby Mathew #endif /* TRUSTED_BOARD_BOOT */
48209a60ccSSoby Mathew 
494c0d0390SSoby Mathew uintptr_t page_align(uintptr_t value, unsigned dir)
504f6ad66aSAchin Gupta {
514f6ad66aSAchin Gupta 	/* Round up the limit to the next page boundary */
5281542c00SAntonio Nino Diaz 	if ((value & (PAGE_SIZE - 1U)) != 0U) {
5381542c00SAntonio Nino Diaz 		value &= ~(PAGE_SIZE - 1U);
544f6ad66aSAchin Gupta 		if (dir == UP)
554c0d0390SSoby Mathew 			value += PAGE_SIZE;
564f6ad66aSAchin Gupta 	}
574f6ad66aSAchin Gupta 
584f6ad66aSAchin Gupta 	return value;
594f6ad66aSAchin Gupta }
604f6ad66aSAchin Gupta 
618f55dfb4SSandrine Bailleux /******************************************************************************
628f55dfb4SSandrine Bailleux  * Determine whether the memory region delimited by 'addr' and 'size' is free,
638f55dfb4SSandrine Bailleux  * given the extents of free memory.
647b6d330cSSandrine Bailleux  * Return 1 if it is free, 0 if it is not free or if the input values are
657b6d330cSSandrine Bailleux  * invalid.
668f55dfb4SSandrine Bailleux  *****************************************************************************/
6799c5ebafSSandrine Bailleux int is_mem_free(uintptr_t free_base, size_t free_size,
684c0d0390SSoby Mathew 		uintptr_t addr, size_t size)
694f6ad66aSAchin Gupta {
707b6d330cSSandrine Bailleux 	uintptr_t free_end, requested_end;
717b6d330cSSandrine Bailleux 
727b6d330cSSandrine Bailleux 	/*
737b6d330cSSandrine Bailleux 	 * Handle corner cases first.
747b6d330cSSandrine Bailleux 	 *
757b6d330cSSandrine Bailleux 	 * The order of the 2 tests is important, because if there's no space
767b6d330cSSandrine Bailleux 	 * left (i.e. free_size == 0) but we don't ask for any memory
777b6d330cSSandrine Bailleux 	 * (i.e. size == 0) then we should report that the memory is free.
787b6d330cSSandrine Bailleux 	 */
797b6d330cSSandrine Bailleux 	if (size == 0)
807b6d330cSSandrine Bailleux 		return 1;	/* A zero-byte region is always free */
817b6d330cSSandrine Bailleux 	if (free_size == 0)
827b6d330cSSandrine Bailleux 		return 0;
837b6d330cSSandrine Bailleux 
847b6d330cSSandrine Bailleux 	/*
857b6d330cSSandrine Bailleux 	 * Check that the end addresses don't overflow.
867b6d330cSSandrine Bailleux 	 * If they do, consider that this memory region is not free, as this
877b6d330cSSandrine Bailleux 	 * is an invalid scenario.
887b6d330cSSandrine Bailleux 	 */
897b6d330cSSandrine Bailleux 	if (check_uptr_overflow(free_base, free_size - 1))
907b6d330cSSandrine Bailleux 		return 0;
917b6d330cSSandrine Bailleux 	free_end = free_base + (free_size - 1);
927b6d330cSSandrine Bailleux 
937b6d330cSSandrine Bailleux 	if (check_uptr_overflow(addr, size - 1))
947b6d330cSSandrine Bailleux 		return 0;
957b6d330cSSandrine Bailleux 	requested_end = addr + (size - 1);
967b6d330cSSandrine Bailleux 
977b6d330cSSandrine Bailleux 	/*
987b6d330cSSandrine Bailleux 	 * Finally, check that the requested memory region lies within the free
997b6d330cSSandrine Bailleux 	 * region.
1007b6d330cSSandrine Bailleux 	 */
1017b6d330cSSandrine Bailleux 	return (addr >= free_base) && (requested_end <= free_end);
1024f6ad66aSAchin Gupta }
1034f6ad66aSAchin Gupta 
104ee9ad785SRyan Harkin /* Generic function to return the size of an image */
105d3775d46SDaniel Boulby size_t get_image_size(unsigned int image_id)
106ee9ad785SRyan Harkin {
107625de1d4SDan Handley 	uintptr_t dev_handle;
108625de1d4SDan Handley 	uintptr_t image_handle;
109625de1d4SDan Handley 	uintptr_t image_spec;
11081542c00SAntonio Nino Diaz 	size_t image_size = 0U;
111e098e244SJuan Castillo 	int io_result;
112ee9ad785SRyan Harkin 
113ee9ad785SRyan Harkin 	/* Obtain a reference to the image by querying the platform layer */
11416948ae1SJuan Castillo 	io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
115e098e244SJuan Castillo 	if (io_result != 0) {
11616948ae1SJuan Castillo 		WARN("Failed to obtain reference to image id=%u (%i)\n",
11716948ae1SJuan Castillo 			image_id, io_result);
118ee9ad785SRyan Harkin 		return 0;
119ee9ad785SRyan Harkin 	}
120ee9ad785SRyan Harkin 
121ee9ad785SRyan Harkin 	/* Attempt to access the image */
122ee9ad785SRyan Harkin 	io_result = io_open(dev_handle, image_spec, &image_handle);
123e098e244SJuan Castillo 	if (io_result != 0) {
12416948ae1SJuan Castillo 		WARN("Failed to access image id=%u (%i)\n",
12516948ae1SJuan Castillo 			image_id, io_result);
126ee9ad785SRyan Harkin 		return 0;
127ee9ad785SRyan Harkin 	}
128ee9ad785SRyan Harkin 
129ee9ad785SRyan Harkin 	/* Find the size of the image */
130ee9ad785SRyan Harkin 	io_result = io_size(image_handle, &image_size);
13181542c00SAntonio Nino Diaz 	if ((io_result != 0) || (image_size == 0U)) {
13216948ae1SJuan Castillo 		WARN("Failed to determine the size of the image id=%u (%i)\n",
13316948ae1SJuan Castillo 			image_id, io_result);
134ee9ad785SRyan Harkin 	}
135ee9ad785SRyan Harkin 	io_result = io_close(image_handle);
136ee9ad785SRyan Harkin 	/* Ignore improbable/unrecoverable error in 'close' */
137ee9ad785SRyan Harkin 
138ee9ad785SRyan Harkin 	/* TODO: Consider maintaining open device connection from this
139ee9ad785SRyan Harkin 	 * bootloader stage
140ee9ad785SRyan Harkin 	 */
141ee9ad785SRyan Harkin 	io_result = io_dev_close(dev_handle);
142ee9ad785SRyan Harkin 	/* Ignore improbable/unrecoverable error in 'dev_close' */
143ee9ad785SRyan Harkin 
144ee9ad785SRyan Harkin 	return image_size;
145ee9ad785SRyan Harkin }
1468f55dfb4SSandrine Bailleux 
14772600226SYatharth Kochar /*******************************************************************************
14876163b3aSSoby Mathew  * Internal function to load an image at a specific address given
14972600226SYatharth Kochar  * an image ID and extents of free memory.
15072600226SYatharth Kochar  *
15172600226SYatharth Kochar  * If the load is successful then the image information is updated.
15272600226SYatharth Kochar  *
15372600226SYatharth Kochar  * Returns 0 on success, a negative error code otherwise.
15472600226SYatharth Kochar  ******************************************************************************/
15576163b3aSSoby Mathew static int load_image(unsigned int image_id, image_info_t *image_data)
15672600226SYatharth Kochar {
15772600226SYatharth Kochar 	uintptr_t dev_handle;
15872600226SYatharth Kochar 	uintptr_t image_handle;
15972600226SYatharth Kochar 	uintptr_t image_spec;
16072600226SYatharth Kochar 	uintptr_t image_base;
16172600226SYatharth Kochar 	size_t image_size;
16272600226SYatharth Kochar 	size_t bytes_read;
16372600226SYatharth Kochar 	int io_result;
16472600226SYatharth Kochar 
16572600226SYatharth Kochar 	assert(image_data != NULL);
16672600226SYatharth Kochar 	assert(image_data->h.version >= VERSION_2);
16772600226SYatharth Kochar 
16872600226SYatharth Kochar 	image_base = image_data->image_base;
16972600226SYatharth Kochar 
17072600226SYatharth Kochar 	/* Obtain a reference to the image by querying the platform layer */
17172600226SYatharth Kochar 	io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
17272600226SYatharth Kochar 	if (io_result != 0) {
17372600226SYatharth Kochar 		WARN("Failed to obtain reference to image id=%u (%i)\n",
17472600226SYatharth Kochar 			image_id, io_result);
17572600226SYatharth Kochar 		return io_result;
17672600226SYatharth Kochar 	}
17772600226SYatharth Kochar 
17872600226SYatharth Kochar 	/* Attempt to access the image */
17972600226SYatharth Kochar 	io_result = io_open(dev_handle, image_spec, &image_handle);
18072600226SYatharth Kochar 	if (io_result != 0) {
18172600226SYatharth Kochar 		WARN("Failed to access image id=%u (%i)\n",
18272600226SYatharth Kochar 			image_id, io_result);
18372600226SYatharth Kochar 		return io_result;
18472600226SYatharth Kochar 	}
18572600226SYatharth Kochar 
18681542c00SAntonio Nino Diaz 	INFO("Loading image id=%u at address 0x%lx\n", image_id, image_base);
18772600226SYatharth Kochar 
18872600226SYatharth Kochar 	/* Find the size of the image */
18972600226SYatharth Kochar 	io_result = io_size(image_handle, &image_size);
19081542c00SAntonio Nino Diaz 	if ((io_result != 0) || (image_size == 0U)) {
19172600226SYatharth Kochar 		WARN("Failed to determine the size of the image id=%u (%i)\n",
19272600226SYatharth Kochar 			image_id, io_result);
19372600226SYatharth Kochar 		goto exit;
19472600226SYatharth Kochar 	}
19572600226SYatharth Kochar 
19672600226SYatharth Kochar 	/* Check that the image size to load is within limit */
19772600226SYatharth Kochar 	if (image_size > image_data->image_max_size) {
19872600226SYatharth Kochar 		WARN("Image id=%u size out of bounds\n", image_id);
19972600226SYatharth Kochar 		io_result = -EFBIG;
20072600226SYatharth Kochar 		goto exit;
20172600226SYatharth Kochar 	}
20272600226SYatharth Kochar 
20381542c00SAntonio Nino Diaz 	/*
20481542c00SAntonio Nino Diaz 	 * image_data->image_max_size is a uint32_t so image_size will always
20581542c00SAntonio Nino Diaz 	 * fit in image_data->image_size.
20681542c00SAntonio Nino Diaz 	 */
20781542c00SAntonio Nino Diaz 	image_data->image_size = (uint32_t)image_size;
20872600226SYatharth Kochar 
20972600226SYatharth Kochar 	/* We have enough space so load the image now */
21072600226SYatharth Kochar 	/* TODO: Consider whether to try to recover/retry a partially successful read */
21172600226SYatharth Kochar 	io_result = io_read(image_handle, image_base, image_size, &bytes_read);
21272600226SYatharth Kochar 	if ((io_result != 0) || (bytes_read < image_size)) {
21372600226SYatharth Kochar 		WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
21472600226SYatharth Kochar 		goto exit;
21572600226SYatharth Kochar 	}
21672600226SYatharth Kochar 
21781542c00SAntonio Nino Diaz 	INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base,
21881542c00SAntonio Nino Diaz 	     (uintptr_t)(image_base + image_size));
21972600226SYatharth Kochar 
22072600226SYatharth Kochar exit:
22181542c00SAntonio Nino Diaz 	(void)io_close(image_handle);
22272600226SYatharth Kochar 	/* Ignore improbable/unrecoverable error in 'close' */
22372600226SYatharth Kochar 
22472600226SYatharth Kochar 	/* TODO: Consider maintaining open device connection from this bootloader stage */
22581542c00SAntonio Nino Diaz 	(void)io_dev_close(dev_handle);
22672600226SYatharth Kochar 	/* Ignore improbable/unrecoverable error in 'dev_close' */
22772600226SYatharth Kochar 
22872600226SYatharth Kochar 	return io_result;
22972600226SYatharth Kochar }
23072600226SYatharth Kochar 
2310f325c67SAntonio Nino Diaz static int load_auth_image_internal(unsigned int image_id,
2320f325c67SAntonio Nino Diaz 				    image_info_t *image_data,
2330f325c67SAntonio Nino Diaz 				    int is_parent_image)
23472600226SYatharth Kochar {
23572600226SYatharth Kochar 	int rc;
23672600226SYatharth Kochar 
23772600226SYatharth Kochar #if TRUSTED_BOARD_BOOT
238209a60ccSSoby Mathew 	if (dyn_is_auth_disabled() == 0) {
23972600226SYatharth Kochar 		unsigned int parent_id;
24072600226SYatharth Kochar 
24172600226SYatharth Kochar 		/* Use recursion to authenticate parent images */
24272600226SYatharth Kochar 		rc = auth_mod_get_parent_id(image_id, &parent_id);
24372600226SYatharth Kochar 		if (rc == 0) {
2440f325c67SAntonio Nino Diaz 			rc = load_auth_image_internal(parent_id, image_data, 1);
24572600226SYatharth Kochar 			if (rc != 0) {
24672600226SYatharth Kochar 				return rc;
24772600226SYatharth Kochar 			}
24872600226SYatharth Kochar 		}
249209a60ccSSoby Mathew 	}
25072600226SYatharth Kochar #endif /* TRUSTED_BOARD_BOOT */
25172600226SYatharth Kochar 
25272600226SYatharth Kochar 	/* Load the image */
25372600226SYatharth Kochar 	rc = load_image(image_id, image_data);
25472600226SYatharth Kochar 	if (rc != 0) {
25572600226SYatharth Kochar 		return rc;
25672600226SYatharth Kochar 	}
25772600226SYatharth Kochar 
25872600226SYatharth Kochar #if TRUSTED_BOARD_BOOT
259209a60ccSSoby Mathew 	if (dyn_is_auth_disabled() == 0) {
26072600226SYatharth Kochar 		/* Authenticate it */
26172600226SYatharth Kochar 		rc = auth_mod_verify_img(image_id,
26272600226SYatharth Kochar 					 (void *)image_data->image_base,
26372600226SYatharth Kochar 					 image_data->image_size);
26472600226SYatharth Kochar 		if (rc != 0) {
2650f325c67SAntonio Nino Diaz 			/* Authentication error, zero memory and flush it right away. */
266308d359bSDouglas Raillard 			zero_normalmem((void *)image_data->image_base,
26772600226SYatharth Kochar 			       image_data->image_size);
26872600226SYatharth Kochar 			flush_dcache_range(image_data->image_base,
26972600226SYatharth Kochar 					   image_data->image_size);
27072600226SYatharth Kochar 			return -EAUTH;
27172600226SYatharth Kochar 		}
272209a60ccSSoby Mathew 	}
27376163b3aSSoby Mathew #endif /* TRUSTED_BOARD_BOOT */
27472600226SYatharth Kochar 
27572600226SYatharth Kochar 	/*
27672600226SYatharth Kochar 	 * Flush the image to main memory so that it can be executed later by
27776163b3aSSoby Mathew 	 * any CPU, regardless of cache and MMU state. If TBB is enabled, then
27876163b3aSSoby Mathew 	 * the file has been successfully loaded and authenticated and flush
27976163b3aSSoby Mathew 	 * only for child images, not for the parents (certificates).
28072600226SYatharth Kochar 	 */
28181542c00SAntonio Nino Diaz 	if (is_parent_image == 0) {
2820f325c67SAntonio Nino Diaz 		flush_dcache_range(image_data->image_base,
2830f325c67SAntonio Nino Diaz 				   image_data->image_size);
2840f325c67SAntonio Nino Diaz 	}
28576163b3aSSoby Mathew 
28672600226SYatharth Kochar 
28772600226SYatharth Kochar 	return 0;
28872600226SYatharth Kochar }
28972600226SYatharth Kochar 
2900f325c67SAntonio Nino Diaz /*******************************************************************************
2910f325c67SAntonio Nino Diaz  * Generic function to load and authenticate an image. The image is actually
2920f325c67SAntonio Nino Diaz  * loaded by calling the 'load_image()' function. Therefore, it returns the
2930f325c67SAntonio Nino Diaz  * same error codes if the loading operation failed, or -EAUTH if the
2940f325c67SAntonio Nino Diaz  * authentication failed. In addition, this function uses recursion to
2950f325c67SAntonio Nino Diaz  * authenticate the parent images up to the root of trust.
2960f325c67SAntonio Nino Diaz  ******************************************************************************/
2970f325c67SAntonio Nino Diaz int load_auth_image(unsigned int image_id, image_info_t *image_data)
2980f325c67SAntonio Nino Diaz {
29901f62b6dSRoberto Vargas 	int err;
30001f62b6dSRoberto Vargas 
30101f62b6dSRoberto Vargas 	do {
30201f62b6dSRoberto Vargas 		err = load_auth_image_internal(image_id, image_data, 0);
30381542c00SAntonio Nino Diaz 	} while ((err != 0) && (plat_try_next_boot_source() != 0));
30401f62b6dSRoberto Vargas 
30501f62b6dSRoberto Vargas 	return err;
3060f325c67SAntonio Nino Diaz }
3070f325c67SAntonio Nino Diaz 
30868a68c92SSandrine Bailleux /*******************************************************************************
30968a68c92SSandrine Bailleux  * Print the content of an entry_point_info_t structure.
31068a68c92SSandrine Bailleux  ******************************************************************************/
31168a68c92SSandrine Bailleux void print_entry_point_info(const entry_point_info_t *ep_info)
31268a68c92SSandrine Bailleux {
31381542c00SAntonio Nino Diaz 	INFO("Entry point address = 0x%lx\n", ep_info->pc);
3144c0d0390SSoby Mathew 	INFO("SPSR = 0x%x\n", ep_info->spsr);
31568a68c92SSandrine Bailleux 
31668a68c92SSandrine Bailleux #define PRINT_IMAGE_ARG(n)					\
31768a68c92SSandrine Bailleux 	VERBOSE("Argument #" #n " = 0x%llx\n",			\
31868a68c92SSandrine Bailleux 		(unsigned long long) ep_info->args.arg##n)
31968a68c92SSandrine Bailleux 
32068a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(0);
32168a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(1);
32268a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(2);
32368a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(3);
32451c79b73SSoby Mathew #ifndef AARCH32
32568a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(4);
32668a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(5);
32768a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(6);
32868a68c92SSandrine Bailleux 	PRINT_IMAGE_ARG(7);
32951c79b73SSoby Mathew #endif
33068a68c92SSandrine Bailleux #undef PRINT_IMAGE_ARG
33168a68c92SSandrine Bailleux }
332