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