blob: 47bdad5a85036c9d949f9cb74dcb219538e466ca [file] [log] [blame]
Achin Gupta4f6ad662013-10-25 09:08:21 +01001/*
Soby Mathewa0fedc42016-06-16 14:52:04 +01002 * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
Achin Gupta4f6ad662013-10-25 09:08:21 +01003 *
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
Dan Handley2bd4ef22014-04-09 13:14:54 +010031#include <arch.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010032#include <arch_helpers.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010033#include <assert.h>
Juan Castilloa08a5e72015-05-19 11:54:12 +010034#include <auth_mod.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010035#include <bl_common.h>
Dan Handley714a0d22014-04-09 13:13:04 +010036#include <debug.h>
Sandrine Bailleux467d0572014-06-24 14:02:34 +010037#include <errno.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010038#include <io_storage.h>
39#include <platform.h>
Juan Castillo97dbcf12015-08-17 10:43:27 +010040#include <string.h>
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +010041#include <utils.h>
Soby Mathew44170c42016-03-22 15:51:08 +000042#include <xlat_tables.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010043
Soby Mathewa0fedc42016-06-16 14:52:04 +010044uintptr_t page_align(uintptr_t value, unsigned dir)
Achin Gupta4f6ad662013-10-25 09:08:21 +010045{
Achin Gupta4f6ad662013-10-25 09:08:21 +010046 /* Round up the limit to the next page boundary */
Soby Mathewa0fedc42016-06-16 14:52:04 +010047 if (value & (PAGE_SIZE - 1)) {
48 value &= ~(PAGE_SIZE - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +010049 if (dir == UP)
Soby Mathewa0fedc42016-06-16 14:52:04 +010050 value += PAGE_SIZE;
Achin Gupta4f6ad662013-10-25 09:08:21 +010051 }
52
53 return value;
54}
55
Sandrine Bailleux467d0572014-06-24 14:02:34 +010056/******************************************************************************
57 * Determine whether the memory region delimited by 'addr' and 'size' is free,
58 * given the extents of free memory.
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +010059 * Return 1 if it is free, 0 if it is not free or if the input values are
60 * invalid.
Sandrine Bailleux467d0572014-06-24 14:02:34 +010061 *****************************************************************************/
Sandrine Bailleuxb0e529b2016-11-08 14:27:10 +000062int is_mem_free(uintptr_t free_base, size_t free_size,
Soby Mathewa0fedc42016-06-16 14:52:04 +010063 uintptr_t addr, size_t size)
Sandrine Bailleux467d0572014-06-24 14:02:34 +010064{
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +010065 uintptr_t free_end, requested_end;
66
67 /*
68 * Handle corner cases first.
69 *
70 * The order of the 2 tests is important, because if there's no space
71 * left (i.e. free_size == 0) but we don't ask for any memory
72 * (i.e. size == 0) then we should report that the memory is free.
73 */
74 if (size == 0)
75 return 1; /* A zero-byte region is always free */
76 if (free_size == 0)
77 return 0;
78
79 /*
80 * Check that the end addresses don't overflow.
81 * If they do, consider that this memory region is not free, as this
82 * is an invalid scenario.
83 */
84 if (check_uptr_overflow(free_base, free_size - 1))
85 return 0;
86 free_end = free_base + (free_size - 1);
87
88 if (check_uptr_overflow(addr, size - 1))
89 return 0;
90 requested_end = addr + (size - 1);
91
92 /*
93 * Finally, check that the requested memory region lies within the free
94 * region.
95 */
96 return (addr >= free_base) && (requested_end <= free_end);
Sandrine Bailleux467d0572014-06-24 14:02:34 +010097}
Achin Gupta4f6ad662013-10-25 09:08:21 +010098
Sandrine Bailleuxb0e529b2016-11-08 14:27:10 +000099#if !LOAD_IMAGE_V2
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100100/******************************************************************************
101 * Inside a given memory region, determine whether a sub-region of memory is
102 * closer from the top or the bottom of the encompassing region. Return the
103 * size of the smallest chunk of free memory surrounding the sub-region in
104 * 'small_chunk_size'.
105 *****************************************************************************/
Soby Mathewa0fedc42016-06-16 14:52:04 +0100106static unsigned int choose_mem_pos(uintptr_t mem_start, uintptr_t mem_end,
107 uintptr_t submem_start, uintptr_t submem_end,
108 size_t *small_chunk_size)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100109{
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100110 size_t top_chunk_size, bottom_chunk_size;
111
112 assert(mem_start <= submem_start);
113 assert(submem_start <= submem_end);
114 assert(submem_end <= mem_end);
115 assert(small_chunk_size != NULL);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100116
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100117 top_chunk_size = mem_end - submem_end;
118 bottom_chunk_size = submem_start - mem_start;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100119
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100120 if (top_chunk_size < bottom_chunk_size) {
121 *small_chunk_size = top_chunk_size;
122 return TOP;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100123 } else {
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100124 *small_chunk_size = bottom_chunk_size;
125 return BOTTOM;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100126 }
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100127}
128
129/******************************************************************************
130 * Reserve the memory region delimited by 'addr' and 'size'. The extents of free
131 * memory are passed in 'free_base' and 'free_size' and they will be updated to
132 * reflect the memory usage.
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100133 * The caller must ensure the memory to reserve is free and that the addresses
134 * and sizes passed in arguments are sane.
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100135 *****************************************************************************/
Soby Mathewa0fedc42016-06-16 14:52:04 +0100136void reserve_mem(uintptr_t *free_base, size_t *free_size,
137 uintptr_t addr, size_t size)
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100138{
139 size_t discard_size;
140 size_t reserved_size;
141 unsigned int pos;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100142
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100143 assert(free_base != NULL);
144 assert(free_size != NULL);
145 assert(is_mem_free(*free_base, *free_size, addr, size));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100146
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100147 if (size == 0) {
148 WARN("Nothing to allocate, requested size is zero\n");
149 return;
150 }
151
152 pos = choose_mem_pos(*free_base, *free_base + (*free_size - 1),
153 addr, addr + (size - 1),
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100154 &discard_size);
155
156 reserved_size = size + discard_size;
157 *free_size -= reserved_size;
158
159 if (pos == BOTTOM)
160 *free_base = addr + size;
161
Soby Mathewa0fedc42016-06-16 14:52:04 +0100162 VERBOSE("Reserved 0x%zx bytes (discarded 0x%zx bytes %s)\n",
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100163 reserved_size, discard_size,
164 pos == TOP ? "above" : "below");
Achin Gupta4f6ad662013-10-25 09:08:21 +0100165}
166
Soby Mathewa0fedc42016-06-16 14:52:04 +0100167static void dump_load_info(uintptr_t image_load_addr,
168 size_t image_size,
Dan Handleye2712bc2014-04-10 15:37:22 +0100169 const meminfo_t *mem_layout)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100170{
Soby Mathewa0fedc42016-06-16 14:52:04 +0100171 INFO("Trying to load image at address %p, size = 0x%zx\n",
172 (void *)image_load_addr, image_size);
Dan Handley91b624e2014-07-29 17:14:00 +0100173 INFO("Current memory layout:\n");
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100174 INFO(" total region = [base = %p, size = 0x%zx]\n",
175 (void *) mem_layout->total_base, mem_layout->total_size);
176 INFO(" free region = [base = %p, size = 0x%zx]\n",
177 (void *) mem_layout->free_base, mem_layout->free_size);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100178}
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100179#endif /* LOAD_IMAGE_V2 */
Achin Gupta4f6ad662013-10-25 09:08:21 +0100180
Ryan Harkin87274c42014-02-04 11:43:57 +0000181/* Generic function to return the size of an image */
Soby Mathewa0fedc42016-06-16 14:52:04 +0100182size_t image_size(unsigned int image_id)
Ryan Harkin87274c42014-02-04 11:43:57 +0000183{
Dan Handleya4cb68e2014-04-23 13:47:06 +0100184 uintptr_t dev_handle;
185 uintptr_t image_handle;
186 uintptr_t image_spec;
Ryan Harkin87274c42014-02-04 11:43:57 +0000187 size_t image_size = 0;
Juan Castillo6e762062015-11-02 10:47:01 +0000188 int io_result;
Ryan Harkin87274c42014-02-04 11:43:57 +0000189
Ryan Harkin87274c42014-02-04 11:43:57 +0000190 /* Obtain a reference to the image by querying the platform layer */
Juan Castillo3a66aca2015-04-13 17:36:19 +0100191 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
Juan Castillo6e762062015-11-02 10:47:01 +0000192 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100193 WARN("Failed to obtain reference to image id=%u (%i)\n",
194 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000195 return 0;
196 }
197
198 /* Attempt to access the image */
199 io_result = io_open(dev_handle, image_spec, &image_handle);
Juan Castillo6e762062015-11-02 10:47:01 +0000200 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100201 WARN("Failed to access image id=%u (%i)\n",
202 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000203 return 0;
204 }
205
206 /* Find the size of the image */
207 io_result = io_size(image_handle, &image_size);
Juan Castillo6e762062015-11-02 10:47:01 +0000208 if ((io_result != 0) || (image_size == 0)) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100209 WARN("Failed to determine the size of the image id=%u (%i)\n",
210 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000211 }
212 io_result = io_close(image_handle);
213 /* Ignore improbable/unrecoverable error in 'close' */
214
215 /* TODO: Consider maintaining open device connection from this
216 * bootloader stage
217 */
218 io_result = io_dev_close(dev_handle);
219 /* Ignore improbable/unrecoverable error in 'dev_close' */
220
221 return image_size;
222}
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100223
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100224#if LOAD_IMAGE_V2
225
226/*******************************************************************************
227 * Generic function to load an image at a specific address given
228 * an image ID and extents of free memory.
229 *
230 * If the load is successful then the image information is updated.
231 *
232 * Returns 0 on success, a negative error code otherwise.
233 ******************************************************************************/
234int load_image(unsigned int image_id, image_info_t *image_data)
235{
236 uintptr_t dev_handle;
237 uintptr_t image_handle;
238 uintptr_t image_spec;
239 uintptr_t image_base;
240 size_t image_size;
241 size_t bytes_read;
242 int io_result;
243
244 assert(image_data != NULL);
245 assert(image_data->h.version >= VERSION_2);
246
247 image_base = image_data->image_base;
248
249 /* Obtain a reference to the image by querying the platform layer */
250 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
251 if (io_result != 0) {
252 WARN("Failed to obtain reference to image id=%u (%i)\n",
253 image_id, io_result);
254 return io_result;
255 }
256
257 /* Attempt to access the image */
258 io_result = io_open(dev_handle, image_spec, &image_handle);
259 if (io_result != 0) {
260 WARN("Failed to access image id=%u (%i)\n",
261 image_id, io_result);
262 return io_result;
263 }
264
265 INFO("Loading image id=%u at address %p\n", image_id,
266 (void *) image_base);
267
268 /* Find the size of the image */
269 io_result = io_size(image_handle, &image_size);
270 if ((io_result != 0) || (image_size == 0)) {
271 WARN("Failed to determine the size of the image id=%u (%i)\n",
272 image_id, io_result);
273 goto exit;
274 }
275
276 /* Check that the image size to load is within limit */
277 if (image_size > image_data->image_max_size) {
278 WARN("Image id=%u size out of bounds\n", image_id);
279 io_result = -EFBIG;
280 goto exit;
281 }
282
283 image_data->image_size = image_size;
284
285 /* We have enough space so load the image now */
286 /* TODO: Consider whether to try to recover/retry a partially successful read */
287 io_result = io_read(image_handle, image_base, image_size, &bytes_read);
288 if ((io_result != 0) || (bytes_read < image_size)) {
289 WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
290 goto exit;
291 }
292
293#if !TRUSTED_BOARD_BOOT
294 /*
295 * File has been successfully loaded.
296 * Flush the image to main memory so that it can be executed later by
297 * any CPU, regardless of cache and MMU state.
298 * When TBB is enabled the image is flushed later, after image
299 * authentication.
300 */
301 flush_dcache_range(image_base, image_size);
302#endif /* TRUSTED_BOARD_BOOT */
303
304 INFO("Image id=%u loaded: %p - %p\n", image_id, (void *) image_base,
305 (void *) (image_base + image_size));
306
307exit:
308 io_close(image_handle);
309 /* Ignore improbable/unrecoverable error in 'close' */
310
311 /* TODO: Consider maintaining open device connection from this bootloader stage */
312 io_dev_close(dev_handle);
313 /* Ignore improbable/unrecoverable error in 'dev_close' */
314
315 return io_result;
316}
317
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000318static int load_auth_image_internal(unsigned int image_id,
319 image_info_t *image_data,
320 int is_parent_image)
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100321{
322 int rc;
323
324#if TRUSTED_BOARD_BOOT
325 unsigned int parent_id;
326
327 /* Use recursion to authenticate parent images */
328 rc = auth_mod_get_parent_id(image_id, &parent_id);
329 if (rc == 0) {
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000330 rc = load_auth_image_internal(parent_id, image_data, 1);
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100331 if (rc != 0) {
332 return rc;
333 }
334 }
335#endif /* TRUSTED_BOARD_BOOT */
336
337 /* Load the image */
338 rc = load_image(image_id, image_data);
339 if (rc != 0) {
340 return rc;
341 }
342
343#if TRUSTED_BOARD_BOOT
344 /* Authenticate it */
345 rc = auth_mod_verify_img(image_id,
346 (void *)image_data->image_base,
347 image_data->image_size);
348 if (rc != 0) {
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000349 /* Authentication error, zero memory and flush it right away. */
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100350 memset((void *)image_data->image_base, 0x00,
351 image_data->image_size);
352 flush_dcache_range(image_data->image_base,
353 image_data->image_size);
354 return -EAUTH;
355 }
356
357 /*
358 * File has been successfully loaded and authenticated.
359 * Flush the image to main memory so that it can be executed later by
360 * any CPU, regardless of cache and MMU state.
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000361 * Do it only for child images, not for the parents (certificates).
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100362 */
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000363 if (!is_parent_image) {
364 flush_dcache_range(image_data->image_base,
365 image_data->image_size);
366 }
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100367#endif /* TRUSTED_BOARD_BOOT */
368
369 return 0;
370}
371
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000372/*******************************************************************************
373 * Generic function to load and authenticate an image. The image is actually
374 * loaded by calling the 'load_image()' function. Therefore, it returns the
375 * same error codes if the loading operation failed, or -EAUTH if the
376 * authentication failed. In addition, this function uses recursion to
377 * authenticate the parent images up to the root of trust.
378 ******************************************************************************/
379int load_auth_image(unsigned int image_id, image_info_t *image_data)
380{
381 return load_auth_image_internal(image_id, image_data, 0);
382}
383
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100384#else /* LOAD_IMAGE_V2 */
385
Achin Gupta4f6ad662013-10-25 09:08:21 +0100386/*******************************************************************************
Sandrine Bailleux8eaf46e2016-05-27 14:08:10 +0100387 * Generic function to load an image at a specific address given an image ID and
388 * extents of free memory.
389 *
390 * If the load is successful then the image information is updated.
391 *
392 * If the entry_point_info argument is not NULL then this function also updates:
393 * - the memory layout to mark the memory as reserved;
394 * - the entry point information.
395 *
396 * The caller might pass a NULL pointer for the entry point if they are not
397 * interested in this information. This is typically the case for non-executable
398 * images (e.g. certificates) and executable images that won't ever be executed
399 * on the application processor (e.g. additional microcontroller firmware).
400 *
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100401 * Returns 0 on success, a negative error code otherwise.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100402 ******************************************************************************/
Vikram Kanigirida567432014-04-15 18:08:08 +0100403int load_image(meminfo_t *mem_layout,
Juan Castillo3a66aca2015-04-13 17:36:19 +0100404 unsigned int image_id,
Juan Castilloa08a5e72015-05-19 11:54:12 +0100405 uintptr_t image_base,
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100406 image_info_t *image_data,
407 entry_point_info_t *entry_point_info)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100408{
Dan Handleya4cb68e2014-04-23 13:47:06 +0100409 uintptr_t dev_handle;
410 uintptr_t image_handle;
411 uintptr_t image_spec;
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100412 size_t image_size;
413 size_t bytes_read;
Juan Castilloec813f52015-10-01 18:37:40 +0100414 int io_result;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100415
James Morrissey9d72b4e2014-02-10 17:04:32 +0000416 assert(mem_layout != NULL);
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100417 assert(image_data != NULL);
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100418 assert(image_data->h.version == VERSION_1);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000419
420 /* Obtain a reference to the image by querying the platform layer */
Juan Castillo3a66aca2015-04-13 17:36:19 +0100421 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
Juan Castilloec813f52015-10-01 18:37:40 +0100422 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100423 WARN("Failed to obtain reference to image id=%u (%i)\n",
424 image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100425 return io_result;
James Morrissey9d72b4e2014-02-10 17:04:32 +0000426 }
427
428 /* Attempt to access the image */
429 io_result = io_open(dev_handle, image_spec, &image_handle);
Juan Castilloec813f52015-10-01 18:37:40 +0100430 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100431 WARN("Failed to access image id=%u (%i)\n",
432 image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100433 return io_result;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100434 }
435
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000436 INFO("Loading image id=%u at address %p\n", image_id,
437 (void *) image_base);
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100438
James Morrissey9d72b4e2014-02-10 17:04:32 +0000439 /* Find the size of the image */
440 io_result = io_size(image_handle, &image_size);
Juan Castilloec813f52015-10-01 18:37:40 +0100441 if ((io_result != 0) || (image_size == 0)) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100442 WARN("Failed to determine the size of the image id=%u (%i)\n",
443 image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100444 goto exit;
James Morrissey9d72b4e2014-02-10 17:04:32 +0000445 }
446
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100447 /* Check that the memory where the image will be loaded is free */
448 if (!is_mem_free(mem_layout->free_base, mem_layout->free_size,
449 image_base, image_size)) {
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100450 WARN("Failed to reserve region [base = %p, size = 0x%zx]\n",
451 (void *) image_base, image_size);
Vikram Kanigirida567432014-04-15 18:08:08 +0100452 dump_load_info(image_base, image_size, mem_layout);
453 io_result = -ENOMEM;
454 goto exit;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100455 }
456
457 /* We have enough space so load the image now */
James Morrissey9d72b4e2014-02-10 17:04:32 +0000458 /* TODO: Consider whether to try to recover/retry a partially successful read */
Dan Handleya4cb68e2014-04-23 13:47:06 +0100459 io_result = io_read(image_handle, image_base, image_size, &bytes_read);
Juan Castilloec813f52015-10-01 18:37:40 +0100460 if ((io_result != 0) || (bytes_read < image_size)) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100461 WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100462 goto exit;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100463 }
464
Sandrine Bailleux8eaf46e2016-05-27 14:08:10 +0100465 image_data->image_base = image_base;
466 image_data->image_size = image_size;
467
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100468 /*
469 * Update the memory usage info.
470 * This is done after the actual loading so that it is not updated when
471 * the load is unsuccessful.
Juan Castillo09a55a82015-01-19 16:51:21 +0000472 * If the caller does not provide an entry point, bypass the memory
473 * reservation.
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100474 */
Juan Castillo09a55a82015-01-19 16:51:21 +0000475 if (entry_point_info != NULL) {
476 reserve_mem(&mem_layout->free_base, &mem_layout->free_size,
477 image_base, image_size);
Sandrine Bailleux8eaf46e2016-05-27 14:08:10 +0100478 entry_point_info->pc = image_base;
Juan Castillo09a55a82015-01-19 16:51:21 +0000479 } else {
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100480 INFO("Skip reserving region [base = %p, size = 0x%zx]\n",
481 (void *) image_base, image_size);
Juan Castillo09a55a82015-01-19 16:51:21 +0000482 }
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100483
Dan Handley9c96ed52016-07-28 14:38:03 +0100484#if !TRUSTED_BOARD_BOOT
Achin Gupta4f6ad662013-10-25 09:08:21 +0100485 /*
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100486 * File has been successfully loaded.
Dan Handley9c96ed52016-07-28 14:38:03 +0100487 * Flush the image to main memory so that it can be executed later by
488 * any CPU, regardless of cache and MMU state.
489 * When TBB is enabled the image is flushed later, after image
490 * authentication.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100491 */
James Morrissey9d72b4e2014-02-10 17:04:32 +0000492 flush_dcache_range(image_base, image_size);
Dan Handley9c96ed52016-07-28 14:38:03 +0100493#endif /* TRUSTED_BOARD_BOOT */
Achin Gupta4f6ad662013-10-25 09:08:21 +0100494
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100495 INFO("Image id=%u loaded at address %p, size = 0x%zx\n", image_id,
496 (void *) image_base, image_size);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000497
498exit:
Vikram Kanigirida567432014-04-15 18:08:08 +0100499 io_close(image_handle);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000500 /* Ignore improbable/unrecoverable error in 'close' */
501
502 /* TODO: Consider maintaining open device connection from this bootloader stage */
Vikram Kanigirida567432014-04-15 18:08:08 +0100503 io_dev_close(dev_handle);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000504 /* Ignore improbable/unrecoverable error in 'dev_close' */
Achin Gupta4f6ad662013-10-25 09:08:21 +0100505
Vikram Kanigirida567432014-04-15 18:08:08 +0100506 return io_result;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100507}
Juan Castilloa08a5e72015-05-19 11:54:12 +0100508
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000509static int load_auth_image_internal(meminfo_t *mem_layout,
510 unsigned int image_id,
511 uintptr_t image_base,
512 image_info_t *image_data,
513 entry_point_info_t *entry_point_info,
514 int is_parent_image)
Juan Castilloa08a5e72015-05-19 11:54:12 +0100515{
516 int rc;
517
518#if TRUSTED_BOARD_BOOT
519 unsigned int parent_id;
520
521 /* Use recursion to authenticate parent images */
522 rc = auth_mod_get_parent_id(image_id, &parent_id);
523 if (rc == 0) {
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000524 rc = load_auth_image_internal(mem_layout, parent_id, image_base,
525 image_data, NULL, 1);
Juan Castilloec813f52015-10-01 18:37:40 +0100526 if (rc != 0) {
Juan Castilloa08a5e72015-05-19 11:54:12 +0100527 return rc;
528 }
529 }
530#endif /* TRUSTED_BOARD_BOOT */
531
532 /* Load the image */
533 rc = load_image(mem_layout, image_id, image_base, image_data,
534 entry_point_info);
Juan Castilloec813f52015-10-01 18:37:40 +0100535 if (rc != 0) {
536 return rc;
Juan Castilloa08a5e72015-05-19 11:54:12 +0100537 }
538
539#if TRUSTED_BOARD_BOOT
540 /* Authenticate it */
541 rc = auth_mod_verify_img(image_id,
542 (void *)image_data->image_base,
543 image_data->image_size);
544 if (rc != 0) {
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000545 /* Authentication error, zero memory and flush it right away. */
Juan Castillo97dbcf12015-08-17 10:43:27 +0100546 memset((void *)image_data->image_base, 0x00,
547 image_data->image_size);
548 flush_dcache_range(image_data->image_base,
549 image_data->image_size);
Juan Castilloec813f52015-10-01 18:37:40 +0100550 return -EAUTH;
Juan Castilloa08a5e72015-05-19 11:54:12 +0100551 }
Dan Handley9c96ed52016-07-28 14:38:03 +0100552 /*
553 * File has been successfully loaded and authenticated.
554 * Flush the image to main memory so that it can be executed later by
555 * any CPU, regardless of cache and MMU state.
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000556 * Do it only for child images, not for the parents (certificates).
Dan Handley9c96ed52016-07-28 14:38:03 +0100557 */
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000558 if (!is_parent_image) {
559 flush_dcache_range(image_data->image_base,
560 image_data->image_size);
561 }
Juan Castilloa08a5e72015-05-19 11:54:12 +0100562#endif /* TRUSTED_BOARD_BOOT */
563
Juan Castilloec813f52015-10-01 18:37:40 +0100564 return 0;
Juan Castilloa08a5e72015-05-19 11:54:12 +0100565}
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100566
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000567/*******************************************************************************
568 * Generic function to load and authenticate an image. The image is actually
569 * loaded by calling the 'load_image()' function. Therefore, it returns the
570 * same error codes if the loading operation failed, or -EAUTH if the
571 * authentication failed. In addition, this function uses recursion to
572 * authenticate the parent images up to the root of trust.
573 ******************************************************************************/
574int load_auth_image(meminfo_t *mem_layout,
575 unsigned int image_id,
576 uintptr_t image_base,
577 image_info_t *image_data,
578 entry_point_info_t *entry_point_info)
579{
580 return load_auth_image_internal(mem_layout, image_id, image_base,
581 image_data, entry_point_info, 0);
582}
583
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100584#endif /* LOAD_IMAGE_V2 */
585
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100586/*******************************************************************************
587 * Print the content of an entry_point_info_t structure.
588 ******************************************************************************/
589void print_entry_point_info(const entry_point_info_t *ep_info)
590{
Soby Mathewa0fedc42016-06-16 14:52:04 +0100591 INFO("Entry point address = %p\n", (void *)ep_info->pc);
592 INFO("SPSR = 0x%x\n", ep_info->spsr);
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100593
594#define PRINT_IMAGE_ARG(n) \
595 VERBOSE("Argument #" #n " = 0x%llx\n", \
596 (unsigned long long) ep_info->args.arg##n)
597
598 PRINT_IMAGE_ARG(0);
599 PRINT_IMAGE_ARG(1);
600 PRINT_IMAGE_ARG(2);
601 PRINT_IMAGE_ARG(3);
Soby Mathewcdf58cb2016-08-30 13:07:31 +0100602#ifndef AARCH32
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100603 PRINT_IMAGE_ARG(4);
604 PRINT_IMAGE_ARG(5);
605 PRINT_IMAGE_ARG(6);
606 PRINT_IMAGE_ARG(7);
Soby Mathewcdf58cb2016-08-30 13:07:31 +0100607#endif
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100608#undef PRINT_IMAGE_ARG
609}