xref: /rk3399_ARM-atf/common/bl_common.c (revision c3cf06f1a3a9b9ee8ac7a0ae505f95c45f7dca84)
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 - 1U)) != 0U) {
52 		value &= ~(PAGE_SIZE - 1U);
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 = 0U;
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 == 0U)) {
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 0x%lx\n", image_id, image_base);
186 
187 	/* Find the size of the image */
188 	io_result = io_size(image_handle, &image_size);
189 	if ((io_result != 0) || (image_size == 0U)) {
190 		WARN("Failed to determine the size of the image id=%u (%i)\n",
191 			image_id, io_result);
192 		goto exit;
193 	}
194 
195 	/* Check that the image size to load is within limit */
196 	if (image_size > image_data->image_max_size) {
197 		WARN("Image id=%u size out of bounds\n", image_id);
198 		io_result = -EFBIG;
199 		goto exit;
200 	}
201 
202 	/*
203 	 * image_data->image_max_size is a uint32_t so image_size will always
204 	 * fit in image_data->image_size.
205 	 */
206 	image_data->image_size = (uint32_t)image_size;
207 
208 	/* We have enough space so load the image now */
209 	/* TODO: Consider whether to try to recover/retry a partially successful read */
210 	io_result = io_read(image_handle, image_base, image_size, &bytes_read);
211 	if ((io_result != 0) || (bytes_read < image_size)) {
212 		WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
213 		goto exit;
214 	}
215 
216 	INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base,
217 	     (uintptr_t)(image_base + image_size));
218 
219 exit:
220 	(void)io_close(image_handle);
221 	/* Ignore improbable/unrecoverable error in 'close' */
222 
223 	/* TODO: Consider maintaining open device connection from this bootloader stage */
224 	(void)io_dev_close(dev_handle);
225 	/* Ignore improbable/unrecoverable error in 'dev_close' */
226 
227 	return io_result;
228 }
229 
230 static int load_auth_image_internal(unsigned int image_id,
231 				    image_info_t *image_data,
232 				    int is_parent_image)
233 {
234 	int rc;
235 
236 #if TRUSTED_BOARD_BOOT
237 	if (dyn_is_auth_disabled() == 0) {
238 		unsigned int parent_id;
239 
240 		/* Use recursion to authenticate parent images */
241 		rc = auth_mod_get_parent_id(image_id, &parent_id);
242 		if (rc == 0) {
243 			rc = load_auth_image_internal(parent_id, image_data, 1);
244 			if (rc != 0) {
245 				return rc;
246 			}
247 		}
248 	}
249 #endif /* TRUSTED_BOARD_BOOT */
250 
251 	/* Load the image */
252 	rc = load_image(image_id, image_data);
253 	if (rc != 0) {
254 		return rc;
255 	}
256 
257 #if TRUSTED_BOARD_BOOT
258 	if (dyn_is_auth_disabled() == 0) {
259 		/* Authenticate it */
260 		rc = auth_mod_verify_img(image_id,
261 					 (void *)image_data->image_base,
262 					 image_data->image_size);
263 		if (rc != 0) {
264 			/* Authentication error, zero memory and flush it right away. */
265 			zero_normalmem((void *)image_data->image_base,
266 			       image_data->image_size);
267 			flush_dcache_range(image_data->image_base,
268 					   image_data->image_size);
269 			return -EAUTH;
270 		}
271 	}
272 #endif /* TRUSTED_BOARD_BOOT */
273 
274 	/*
275 	 * Flush the image to main memory so that it can be executed later by
276 	 * any CPU, regardless of cache and MMU state. If TBB is enabled, then
277 	 * the file has been successfully loaded and authenticated and flush
278 	 * only for child images, not for the parents (certificates).
279 	 */
280 	if (is_parent_image == 0) {
281 		flush_dcache_range(image_data->image_base,
282 				   image_data->image_size);
283 	}
284 
285 
286 	return 0;
287 }
288 
289 /*******************************************************************************
290  * Generic function to load and authenticate an image. The image is actually
291  * loaded by calling the 'load_image()' function. Therefore, it returns the
292  * same error codes if the loading operation failed, or -EAUTH if the
293  * authentication failed. In addition, this function uses recursion to
294  * authenticate the parent images up to the root of trust.
295  ******************************************************************************/
296 int load_auth_image(unsigned int image_id, image_info_t *image_data)
297 {
298 	int err;
299 
300 	do {
301 		err = load_auth_image_internal(image_id, image_data, 0);
302 	} while ((err != 0) && (plat_try_next_boot_source() != 0));
303 
304 	return err;
305 }
306 
307 /*******************************************************************************
308  * Print the content of an entry_point_info_t structure.
309  ******************************************************************************/
310 void print_entry_point_info(const entry_point_info_t *ep_info)
311 {
312 	INFO("Entry point address = 0x%lx\n", ep_info->pc);
313 	INFO("SPSR = 0x%x\n", ep_info->spsr);
314 
315 #define PRINT_IMAGE_ARG(n)					\
316 	VERBOSE("Argument #" #n " = 0x%llx\n",			\
317 		(unsigned long long) ep_info->args.arg##n)
318 
319 	PRINT_IMAGE_ARG(0);
320 	PRINT_IMAGE_ARG(1);
321 	PRINT_IMAGE_ARG(2);
322 	PRINT_IMAGE_ARG(3);
323 #ifndef AARCH32
324 	PRINT_IMAGE_ARG(4);
325 	PRINT_IMAGE_ARG(5);
326 	PRINT_IMAGE_ARG(6);
327 	PRINT_IMAGE_ARG(7);
328 #endif
329 #undef PRINT_IMAGE_ARG
330 }
331