xref: /rk3399_ARM-atf/common/bl_common.c (revision fabd0a864a09ab6024db2cac0a4929b443a72640)
1 /*
2  * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of ARM nor the names of its contributors may be used
15  * to endorse or promote products derived from this software without specific
16  * prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <arch.h>
32 #include <arch_helpers.h>
33 #include <assert.h>
34 #include <auth_mod.h>
35 #include <bl_common.h>
36 #include <debug.h>
37 #include <errno.h>
38 #include <io_storage.h>
39 #include <platform.h>
40 #include <string.h>
41 #include <utils.h>
42 #include <xlat_tables.h>
43 
44 uintptr_t page_align(uintptr_t value, unsigned dir)
45 {
46 	/* Round up the limit to the next page boundary */
47 	if (value & (PAGE_SIZE - 1)) {
48 		value &= ~(PAGE_SIZE - 1);
49 		if (dir == UP)
50 			value += PAGE_SIZE;
51 	}
52 
53 	return value;
54 }
55 
56 static inline unsigned int is_page_aligned (uintptr_t addr) {
57 	return (addr & (PAGE_SIZE - 1)) == 0;
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 static 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 /******************************************************************************
104  * Inside a given memory region, determine whether a sub-region of memory is
105  * closer from the top or the bottom of the encompassing region. Return the
106  * size of the smallest chunk of free memory surrounding the sub-region in
107  * 'small_chunk_size'.
108  *****************************************************************************/
109 static unsigned int choose_mem_pos(uintptr_t mem_start, uintptr_t mem_end,
110 				  uintptr_t submem_start, uintptr_t submem_end,
111 				  size_t *small_chunk_size)
112 {
113 	size_t top_chunk_size, bottom_chunk_size;
114 
115 	assert(mem_start <= submem_start);
116 	assert(submem_start <= submem_end);
117 	assert(submem_end <= mem_end);
118 	assert(small_chunk_size != NULL);
119 
120 	top_chunk_size = mem_end - submem_end;
121 	bottom_chunk_size = submem_start - mem_start;
122 
123 	if (top_chunk_size < bottom_chunk_size) {
124 		*small_chunk_size = top_chunk_size;
125 		return TOP;
126 	} else {
127 		*small_chunk_size = bottom_chunk_size;
128 		return BOTTOM;
129 	}
130 }
131 
132 /******************************************************************************
133  * Reserve the memory region delimited by 'addr' and 'size'. The extents of free
134  * memory are passed in 'free_base' and 'free_size' and they will be updated to
135  * reflect the memory usage.
136  * The caller must ensure the memory to reserve is free and that the addresses
137  * and sizes passed in arguments are sane.
138  *****************************************************************************/
139 void reserve_mem(uintptr_t *free_base, size_t *free_size,
140 		 uintptr_t addr, size_t size)
141 {
142 	size_t discard_size;
143 	size_t reserved_size;
144 	unsigned int pos;
145 
146 	assert(free_base != NULL);
147 	assert(free_size != NULL);
148 	assert(is_mem_free(*free_base, *free_size, addr, size));
149 
150 	if (size == 0) {
151 		WARN("Nothing to allocate, requested size is zero\n");
152 		return;
153 	}
154 
155 	pos = choose_mem_pos(*free_base, *free_base + (*free_size - 1),
156 			     addr, addr + (size - 1),
157 			     &discard_size);
158 
159 	reserved_size = size + discard_size;
160 	*free_size -= reserved_size;
161 
162 	if (pos == BOTTOM)
163 		*free_base = addr + size;
164 
165 	VERBOSE("Reserved 0x%zx bytes (discarded 0x%zx bytes %s)\n",
166 	     reserved_size, discard_size,
167 	     pos == TOP ? "above" : "below");
168 }
169 
170 static void dump_load_info(uintptr_t image_load_addr,
171 			   size_t image_size,
172 			   const meminfo_t *mem_layout)
173 {
174 	INFO("Trying to load image at address %p, size = 0x%zx\n",
175 		(void *)image_load_addr, image_size);
176 	INFO("Current memory layout:\n");
177 	INFO("  total region = [base = %p, size = 0x%zx]\n",
178 		(void *) mem_layout->total_base, mem_layout->total_size);
179 	INFO("  free region = [base = %p, size = 0x%zx]\n",
180 		(void *) mem_layout->free_base, mem_layout->free_size);
181 }
182 
183 /* Generic function to return the size of an image */
184 size_t image_size(unsigned int image_id)
185 {
186 	uintptr_t dev_handle;
187 	uintptr_t image_handle;
188 	uintptr_t image_spec;
189 	size_t image_size = 0;
190 	int io_result;
191 
192 	/* Obtain a reference to the image by querying the platform layer */
193 	io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
194 	if (io_result != 0) {
195 		WARN("Failed to obtain reference to image id=%u (%i)\n",
196 			image_id, io_result);
197 		return 0;
198 	}
199 
200 	/* Attempt to access the image */
201 	io_result = io_open(dev_handle, image_spec, &image_handle);
202 	if (io_result != 0) {
203 		WARN("Failed to access image id=%u (%i)\n",
204 			image_id, io_result);
205 		return 0;
206 	}
207 
208 	/* Find the size of the image */
209 	io_result = io_size(image_handle, &image_size);
210 	if ((io_result != 0) || (image_size == 0)) {
211 		WARN("Failed to determine the size of the image id=%u (%i)\n",
212 			image_id, io_result);
213 	}
214 	io_result = io_close(image_handle);
215 	/* Ignore improbable/unrecoverable error in 'close' */
216 
217 	/* TODO: Consider maintaining open device connection from this
218 	 * bootloader stage
219 	 */
220 	io_result = io_dev_close(dev_handle);
221 	/* Ignore improbable/unrecoverable error in 'dev_close' */
222 
223 	return image_size;
224 }
225 
226 /*******************************************************************************
227  * Generic function to load an image at a specific address given an image ID and
228  * extents of free memory.
229  *
230  * If the load is successful then the image information is updated.
231  *
232  * If the entry_point_info argument is not NULL then this function also updates:
233  * - the memory layout to mark the memory as reserved;
234  * - the entry point information.
235  *
236  * The caller might pass a NULL pointer for the entry point if they are not
237  * interested in this information. This is typically the case for non-executable
238  * images (e.g. certificates) and executable images that won't ever be executed
239  * on the application processor (e.g. additional microcontroller firmware).
240  *
241  * Returns 0 on success, a negative error code otherwise.
242  ******************************************************************************/
243 int load_image(meminfo_t *mem_layout,
244 	       unsigned int image_id,
245 	       uintptr_t image_base,
246 	       image_info_t *image_data,
247 	       entry_point_info_t *entry_point_info)
248 {
249 	uintptr_t dev_handle;
250 	uintptr_t image_handle;
251 	uintptr_t image_spec;
252 	size_t image_size;
253 	size_t bytes_read;
254 	int io_result;
255 
256 	assert(mem_layout != NULL);
257 	assert(image_data != NULL);
258 	assert(image_data->h.version >= VERSION_1);
259 
260 	/* Obtain a reference to the image by querying the platform layer */
261 	io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
262 	if (io_result != 0) {
263 		WARN("Failed to obtain reference to image id=%u (%i)\n",
264 			image_id, io_result);
265 		return io_result;
266 	}
267 
268 	/* Attempt to access the image */
269 	io_result = io_open(dev_handle, image_spec, &image_handle);
270 	if (io_result != 0) {
271 		WARN("Failed to access image id=%u (%i)\n",
272 			image_id, io_result);
273 		return io_result;
274 	}
275 
276 	INFO("Loading image id=%u at address %p\n", image_id,
277 		(void *) image_base);
278 
279 	/* Find the size of the image */
280 	io_result = io_size(image_handle, &image_size);
281 	if ((io_result != 0) || (image_size == 0)) {
282 		WARN("Failed to determine the size of the image id=%u (%i)\n",
283 			image_id, io_result);
284 		goto exit;
285 	}
286 
287 	/* Check that the memory where the image will be loaded is free */
288 	if (!is_mem_free(mem_layout->free_base, mem_layout->free_size,
289 			 image_base, image_size)) {
290 		WARN("Failed to reserve region [base = %p, size = 0x%zx]\n",
291 		     (void *) image_base, image_size);
292 		dump_load_info(image_base, image_size, mem_layout);
293 		io_result = -ENOMEM;
294 		goto exit;
295 	}
296 
297 	/* We have enough space so load the image now */
298 	/* TODO: Consider whether to try to recover/retry a partially successful read */
299 	io_result = io_read(image_handle, image_base, image_size, &bytes_read);
300 	if ((io_result != 0) || (bytes_read < image_size)) {
301 		WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
302 		goto exit;
303 	}
304 
305 	image_data->image_base = image_base;
306 	image_data->image_size = image_size;
307 
308 	/*
309 	 * Update the memory usage info.
310 	 * This is done after the actual loading so that it is not updated when
311 	 * the load is unsuccessful.
312 	 * If the caller does not provide an entry point, bypass the memory
313 	 * reservation.
314 	 */
315 	if (entry_point_info != NULL) {
316 		reserve_mem(&mem_layout->free_base, &mem_layout->free_size,
317 				image_base, image_size);
318 		entry_point_info->pc = image_base;
319 	} else {
320 		INFO("Skip reserving region [base = %p, size = 0x%zx]\n",
321 		     (void *) image_base, image_size);
322 	}
323 
324 	/*
325 	 * File has been successfully loaded.
326 	 * Flush the image in Trusted SRAM so that the next exception level can
327 	 * see it.
328 	 */
329 	flush_dcache_range(image_base, image_size);
330 
331 	INFO("Image id=%u loaded at address %p, size = 0x%zx\n", image_id,
332 		(void *) image_base, image_size);
333 
334 exit:
335 	io_close(image_handle);
336 	/* Ignore improbable/unrecoverable error in 'close' */
337 
338 	/* TODO: Consider maintaining open device connection from this bootloader stage */
339 	io_dev_close(dev_handle);
340 	/* Ignore improbable/unrecoverable error in 'dev_close' */
341 
342 	return io_result;
343 }
344 
345 /*******************************************************************************
346  * Generic function to load and authenticate an image. The image is actually
347  * loaded by calling the 'load_image()' function. In addition, this function
348  * uses recursion to authenticate the parent images up to the root of trust.
349  ******************************************************************************/
350 int load_auth_image(meminfo_t *mem_layout,
351 		    unsigned int image_id,
352 		    uintptr_t image_base,
353 		    image_info_t *image_data,
354 		    entry_point_info_t *entry_point_info)
355 {
356 	int rc;
357 
358 #if TRUSTED_BOARD_BOOT
359 	unsigned int parent_id;
360 
361 	/* Use recursion to authenticate parent images */
362 	rc = auth_mod_get_parent_id(image_id, &parent_id);
363 	if (rc == 0) {
364 		rc = load_auth_image(mem_layout, parent_id, image_base,
365 				     image_data, NULL);
366 		if (rc != 0) {
367 			return rc;
368 		}
369 	}
370 #endif /* TRUSTED_BOARD_BOOT */
371 
372 	/* Load the image */
373 	rc = load_image(mem_layout, image_id, image_base, image_data,
374 			entry_point_info);
375 	if (rc != 0) {
376 		return rc;
377 	}
378 
379 #if TRUSTED_BOARD_BOOT
380 	/* Authenticate it */
381 	rc = auth_mod_verify_img(image_id,
382 				 (void *)image_data->image_base,
383 				 image_data->image_size);
384 	if (rc != 0) {
385 		memset((void *)image_data->image_base, 0x00,
386 		       image_data->image_size);
387 		flush_dcache_range(image_data->image_base,
388 				   image_data->image_size);
389 		return -EAUTH;
390 	}
391 
392 	/* After working with data, invalidate the data cache */
393 	inv_dcache_range(image_data->image_base,
394 			(size_t)image_data->image_size);
395 #endif /* TRUSTED_BOARD_BOOT */
396 
397 	return 0;
398 }
399 
400 /*******************************************************************************
401  * Print the content of an entry_point_info_t structure.
402  ******************************************************************************/
403 void print_entry_point_info(const entry_point_info_t *ep_info)
404 {
405 	INFO("Entry point address = %p\n", (void *)ep_info->pc);
406 	INFO("SPSR = 0x%x\n", ep_info->spsr);
407 
408 #define PRINT_IMAGE_ARG(n)					\
409 	VERBOSE("Argument #" #n " = 0x%llx\n",			\
410 		(unsigned long long) ep_info->args.arg##n)
411 
412 	PRINT_IMAGE_ARG(0);
413 	PRINT_IMAGE_ARG(1);
414 	PRINT_IMAGE_ARG(2);
415 	PRINT_IMAGE_ARG(3);
416 	PRINT_IMAGE_ARG(4);
417 	PRINT_IMAGE_ARG(5);
418 	PRINT_IMAGE_ARG(6);
419 	PRINT_IMAGE_ARG(7);
420 #undef PRINT_IMAGE_ARG
421 }
422