xref: /rk3399_ARM-atf/common/bl_common.c (revision c9263e62a749610c880bdc693e4e644bd9091611)
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 <arch.h>
8 #include <arch_helpers.h>
9 #include <assert.h>
10 #include <auth_mod.h>
11 #include <bl_common.h>
12 #include <debug.h>
13 #include <errno.h>
14 #include <io_storage.h>
15 #include <platform.h>
16 #include <string.h>
17 #include <utils.h>
18 #include <xlat_tables_defs.h>
19 
20 #if TRUSTED_BOARD_BOOT
21 # ifdef DYN_DISABLE_AUTH
22 static int disable_auth;
23 
24 /******************************************************************************
25  * API to dynamically disable authentication. Only meant for development
26  * systems. This is only invoked if DYN_DISABLE_AUTH is defined.
27  *****************************************************************************/
28 void dyn_disable_auth(void)
29 {
30 	INFO("Disabling authentication of images dynamically\n");
31 	disable_auth = 1;
32 }
33 # endif /* DYN_DISABLE_AUTH */
34 
35 /******************************************************************************
36  * Function to determine whether the authentication is disabled dynamically.
37  *****************************************************************************/
38 static int dyn_is_auth_disabled(void)
39 {
40 # ifdef DYN_DISABLE_AUTH
41 	return disable_auth;
42 # else
43 	return 0;
44 # endif
45 }
46 #endif /* TRUSTED_BOARD_BOOT */
47 
48 uintptr_t page_align(uintptr_t value, unsigned dir)
49 {
50 	/* Round up the limit to the next page boundary */
51 	if (value & (PAGE_SIZE - 1)) {
52 		value &= ~(PAGE_SIZE - 1);
53 		if (dir == UP)
54 			value += PAGE_SIZE;
55 	}
56 
57 	return value;
58 }
59 
60 /******************************************************************************
61  * Determine whether the memory region delimited by 'addr' and 'size' is free,
62  * given the extents of free memory.
63  * Return 1 if it is free, 0 if it is not free or if the input values are
64  * invalid.
65  *****************************************************************************/
66 int is_mem_free(uintptr_t free_base, size_t free_size,
67 		uintptr_t addr, size_t size)
68 {
69 	uintptr_t free_end, requested_end;
70 
71 	/*
72 	 * Handle corner cases first.
73 	 *
74 	 * The order of the 2 tests is important, because if there's no space
75 	 * left (i.e. free_size == 0) but we don't ask for any memory
76 	 * (i.e. size == 0) then we should report that the memory is free.
77 	 */
78 	if (size == 0)
79 		return 1;	/* A zero-byte region is always free */
80 	if (free_size == 0)
81 		return 0;
82 
83 	/*
84 	 * Check that the end addresses don't overflow.
85 	 * If they do, consider that this memory region is not free, as this
86 	 * is an invalid scenario.
87 	 */
88 	if (check_uptr_overflow(free_base, free_size - 1))
89 		return 0;
90 	free_end = free_base + (free_size - 1);
91 
92 	if (check_uptr_overflow(addr, size - 1))
93 		return 0;
94 	requested_end = addr + (size - 1);
95 
96 	/*
97 	 * Finally, check that the requested memory region lies within the free
98 	 * region.
99 	 */
100 	return (addr >= free_base) && (requested_end <= free_end);
101 }
102 
103 /* Generic function to return the size of an image */
104 size_t get_image_size(unsigned int image_id)
105 {
106 	uintptr_t dev_handle;
107 	uintptr_t image_handle;
108 	uintptr_t image_spec;
109 	size_t image_size = 0;
110 	int io_result;
111 
112 	/* Obtain a reference to the image by querying the platform layer */
113 	io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
114 	if (io_result != 0) {
115 		WARN("Failed to obtain reference to image id=%u (%i)\n",
116 			image_id, io_result);
117 		return 0;
118 	}
119 
120 	/* Attempt to access the image */
121 	io_result = io_open(dev_handle, image_spec, &image_handle);
122 	if (io_result != 0) {
123 		WARN("Failed to access image id=%u (%i)\n",
124 			image_id, io_result);
125 		return 0;
126 	}
127 
128 	/* Find the size of the image */
129 	io_result = io_size(image_handle, &image_size);
130 	if ((io_result != 0) || (image_size == 0)) {
131 		WARN("Failed to determine the size of the image id=%u (%i)\n",
132 			image_id, io_result);
133 	}
134 	io_result = io_close(image_handle);
135 	/* Ignore improbable/unrecoverable error in 'close' */
136 
137 	/* TODO: Consider maintaining open device connection from this
138 	 * bootloader stage
139 	 */
140 	io_result = io_dev_close(dev_handle);
141 	/* Ignore improbable/unrecoverable error in 'dev_close' */
142 
143 	return image_size;
144 }
145 
146 /*******************************************************************************
147  * Internal function to load an image at a specific address given
148  * an image ID and extents of free memory.
149  *
150  * If the load is successful then the image information is updated.
151  *
152  * Returns 0 on success, a negative error code otherwise.
153  ******************************************************************************/
154 static int load_image(unsigned int image_id, image_info_t *image_data)
155 {
156 	uintptr_t dev_handle;
157 	uintptr_t image_handle;
158 	uintptr_t image_spec;
159 	uintptr_t image_base;
160 	size_t image_size;
161 	size_t bytes_read;
162 	int io_result;
163 
164 	assert(image_data != NULL);
165 	assert(image_data->h.version >= VERSION_2);
166 
167 	image_base = image_data->image_base;
168 
169 	/* Obtain a reference to the image by querying the platform layer */
170 	io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
171 	if (io_result != 0) {
172 		WARN("Failed to obtain reference to image id=%u (%i)\n",
173 			image_id, io_result);
174 		return io_result;
175 	}
176 
177 	/* Attempt to access the image */
178 	io_result = io_open(dev_handle, image_spec, &image_handle);
179 	if (io_result != 0) {
180 		WARN("Failed to access image id=%u (%i)\n",
181 			image_id, io_result);
182 		return io_result;
183 	}
184 
185 	INFO("Loading image id=%u at address %p\n", image_id,
186 		(void *) image_base);
187 
188 	/* Find the size of the image */
189 	io_result = io_size(image_handle, &image_size);
190 	if ((io_result != 0) || (image_size == 0)) {
191 		WARN("Failed to determine the size of the image id=%u (%i)\n",
192 			image_id, io_result);
193 		goto exit;
194 	}
195 
196 	/* Check that the image size to load is within limit */
197 	if (image_size > image_data->image_max_size) {
198 		WARN("Image id=%u size out of bounds\n", image_id);
199 		io_result = -EFBIG;
200 		goto exit;
201 	}
202 
203 	image_data->image_size = image_size;
204 
205 	/* We have enough space so load the image now */
206 	/* TODO: Consider whether to try to recover/retry a partially successful read */
207 	io_result = io_read(image_handle, image_base, image_size, &bytes_read);
208 	if ((io_result != 0) || (bytes_read < image_size)) {
209 		WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
210 		goto exit;
211 	}
212 
213 	INFO("Image id=%u loaded: %p - %p\n", image_id, (void *) image_base,
214 	     (void *) (image_base + image_size));
215 
216 exit:
217 	io_close(image_handle);
218 	/* Ignore improbable/unrecoverable error in 'close' */
219 
220 	/* TODO: Consider maintaining open device connection from this bootloader stage */
221 	io_dev_close(dev_handle);
222 	/* Ignore improbable/unrecoverable error in 'dev_close' */
223 
224 	return io_result;
225 }
226 
227 static int load_auth_image_internal(unsigned int image_id,
228 				    image_info_t *image_data,
229 				    int is_parent_image)
230 {
231 	int rc;
232 
233 #if TRUSTED_BOARD_BOOT
234 	if (dyn_is_auth_disabled() == 0) {
235 		unsigned int parent_id;
236 
237 		/* Use recursion to authenticate parent images */
238 		rc = auth_mod_get_parent_id(image_id, &parent_id);
239 		if (rc == 0) {
240 			rc = load_auth_image_internal(parent_id, image_data, 1);
241 			if (rc != 0) {
242 				return rc;
243 			}
244 		}
245 	}
246 #endif /* TRUSTED_BOARD_BOOT */
247 
248 	/* Load the image */
249 	rc = load_image(image_id, image_data);
250 	if (rc != 0) {
251 		return rc;
252 	}
253 
254 #if TRUSTED_BOARD_BOOT
255 	if (dyn_is_auth_disabled() == 0) {
256 		/* Authenticate it */
257 		rc = auth_mod_verify_img(image_id,
258 					 (void *)image_data->image_base,
259 					 image_data->image_size);
260 		if (rc != 0) {
261 			/* Authentication error, zero memory and flush it right away. */
262 			zero_normalmem((void *)image_data->image_base,
263 			       image_data->image_size);
264 			flush_dcache_range(image_data->image_base,
265 					   image_data->image_size);
266 			return -EAUTH;
267 		}
268 	}
269 #endif /* TRUSTED_BOARD_BOOT */
270 
271 	/*
272 	 * Flush the image to main memory so that it can be executed later by
273 	 * any CPU, regardless of cache and MMU state. If TBB is enabled, then
274 	 * the file has been successfully loaded and authenticated and flush
275 	 * only for child images, not for the parents (certificates).
276 	 */
277 	if (!is_parent_image) {
278 		flush_dcache_range(image_data->image_base,
279 				   image_data->image_size);
280 	}
281 
282 
283 	return 0;
284 }
285 
286 /*******************************************************************************
287  * Generic function to load and authenticate an image. The image is actually
288  * loaded by calling the 'load_image()' function. Therefore, it returns the
289  * same error codes if the loading operation failed, or -EAUTH if the
290  * authentication failed. In addition, this function uses recursion to
291  * authenticate the parent images up to the root of trust.
292  ******************************************************************************/
293 int load_auth_image(unsigned int image_id, image_info_t *image_data)
294 {
295 	int err;
296 
297 	do {
298 		err = load_auth_image_internal(image_id, image_data, 0);
299 	} while (err != 0 && plat_try_next_boot_source());
300 
301 	return err;
302 }
303 
304 /*******************************************************************************
305  * Print the content of an entry_point_info_t structure.
306  ******************************************************************************/
307 void print_entry_point_info(const entry_point_info_t *ep_info)
308 {
309 	INFO("Entry point address = %p\n", (void *)ep_info->pc);
310 	INFO("SPSR = 0x%x\n", ep_info->spsr);
311 
312 #define PRINT_IMAGE_ARG(n)					\
313 	VERBOSE("Argument #" #n " = 0x%llx\n",			\
314 		(unsigned long long) ep_info->args.arg##n)
315 
316 	PRINT_IMAGE_ARG(0);
317 	PRINT_IMAGE_ARG(1);
318 	PRINT_IMAGE_ARG(2);
319 	PRINT_IMAGE_ARG(3);
320 #ifndef AARCH32
321 	PRINT_IMAGE_ARG(4);
322 	PRINT_IMAGE_ARG(5);
323 	PRINT_IMAGE_ARG(6);
324 	PRINT_IMAGE_ARG(7);
325 #endif
326 #undef PRINT_IMAGE_ARG
327 }
328