blob: 193e972c3ecadba956cfb8e6b28a32f78660c277 [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
Yatharth Kochar3345a8d2016-09-12 16:08:41 +010056#if !LOAD_IMAGE_V2
Sandrine Bailleux467d0572014-06-24 14:02:34 +010057/******************************************************************************
58 * Determine whether the memory region delimited by 'addr' and 'size' is free,
59 * given the extents of free memory.
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +010060 * Return 1 if it is free, 0 if it is not free or if the input values are
61 * invalid.
Sandrine Bailleux467d0572014-06-24 14:02:34 +010062 *****************************************************************************/
Soby Mathewa0fedc42016-06-16 14:52:04 +010063static int is_mem_free(uintptr_t free_base, size_t free_size,
64 uintptr_t addr, size_t size)
Sandrine Bailleux467d0572014-06-24 14:02:34 +010065{
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +010066 uintptr_t free_end, requested_end;
67
68 /*
69 * Handle corner cases first.
70 *
71 * The order of the 2 tests is important, because if there's no space
72 * left (i.e. free_size == 0) but we don't ask for any memory
73 * (i.e. size == 0) then we should report that the memory is free.
74 */
75 if (size == 0)
76 return 1; /* A zero-byte region is always free */
77 if (free_size == 0)
78 return 0;
79
80 /*
81 * Check that the end addresses don't overflow.
82 * If they do, consider that this memory region is not free, as this
83 * is an invalid scenario.
84 */
85 if (check_uptr_overflow(free_base, free_size - 1))
86 return 0;
87 free_end = free_base + (free_size - 1);
88
89 if (check_uptr_overflow(addr, size - 1))
90 return 0;
91 requested_end = addr + (size - 1);
92
93 /*
94 * Finally, check that the requested memory region lies within the free
95 * region.
96 */
97 return (addr >= free_base) && (requested_end <= free_end);
Sandrine Bailleux467d0572014-06-24 14:02:34 +010098}
Achin Gupta4f6ad662013-10-25 09:08:21 +010099
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
318/*******************************************************************************
319 * Generic function to load and authenticate an image. The image is actually
320 * loaded by calling the 'load_image()' function. Therefore, it returns the
321 * same error codes if the loading operation failed, or -EAUTH if the
322 * authentication failed. In addition, this function uses recursion to
323 * authenticate the parent images up to the root of trust.
324 ******************************************************************************/
325int load_auth_image(unsigned int image_id, image_info_t *image_data)
326{
327 int rc;
328
329#if TRUSTED_BOARD_BOOT
330 unsigned int parent_id;
331
332 /* Use recursion to authenticate parent images */
333 rc = auth_mod_get_parent_id(image_id, &parent_id);
334 if (rc == 0) {
335 rc = load_auth_image(parent_id, image_data);
336 if (rc != 0) {
337 return rc;
338 }
339 }
340#endif /* TRUSTED_BOARD_BOOT */
341
342 /* Load the image */
343 rc = load_image(image_id, image_data);
344 if (rc != 0) {
345 return rc;
346 }
347
348#if TRUSTED_BOARD_BOOT
349 /* Authenticate it */
350 rc = auth_mod_verify_img(image_id,
351 (void *)image_data->image_base,
352 image_data->image_size);
353 if (rc != 0) {
354 memset((void *)image_data->image_base, 0x00,
355 image_data->image_size);
356 flush_dcache_range(image_data->image_base,
357 image_data->image_size);
358 return -EAUTH;
359 }
360
361 /*
362 * File has been successfully loaded and authenticated.
363 * Flush the image to main memory so that it can be executed later by
364 * any CPU, regardless of cache and MMU state.
365 */
366 flush_dcache_range(image_data->image_base, image_data->image_size);
367#endif /* TRUSTED_BOARD_BOOT */
368
369 return 0;
370}
371
372#else /* LOAD_IMAGE_V2 */
373
Achin Gupta4f6ad662013-10-25 09:08:21 +0100374/*******************************************************************************
Sandrine Bailleux8eaf46e2016-05-27 14:08:10 +0100375 * Generic function to load an image at a specific address given an image ID and
376 * extents of free memory.
377 *
378 * If the load is successful then the image information is updated.
379 *
380 * If the entry_point_info argument is not NULL then this function also updates:
381 * - the memory layout to mark the memory as reserved;
382 * - the entry point information.
383 *
384 * The caller might pass a NULL pointer for the entry point if they are not
385 * interested in this information. This is typically the case for non-executable
386 * images (e.g. certificates) and executable images that won't ever be executed
387 * on the application processor (e.g. additional microcontroller firmware).
388 *
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100389 * Returns 0 on success, a negative error code otherwise.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100390 ******************************************************************************/
Vikram Kanigirida567432014-04-15 18:08:08 +0100391int load_image(meminfo_t *mem_layout,
Juan Castillo3a66aca2015-04-13 17:36:19 +0100392 unsigned int image_id,
Juan Castilloa08a5e72015-05-19 11:54:12 +0100393 uintptr_t image_base,
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100394 image_info_t *image_data,
395 entry_point_info_t *entry_point_info)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100396{
Dan Handleya4cb68e2014-04-23 13:47:06 +0100397 uintptr_t dev_handle;
398 uintptr_t image_handle;
399 uintptr_t image_spec;
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100400 size_t image_size;
401 size_t bytes_read;
Juan Castilloec813f52015-10-01 18:37:40 +0100402 int io_result;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100403
James Morrissey9d72b4e2014-02-10 17:04:32 +0000404 assert(mem_layout != NULL);
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100405 assert(image_data != NULL);
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100406 assert(image_data->h.version == VERSION_1);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000407
408 /* Obtain a reference to the image by querying the platform layer */
Juan Castillo3a66aca2015-04-13 17:36:19 +0100409 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
Juan Castilloec813f52015-10-01 18:37:40 +0100410 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100411 WARN("Failed to obtain reference to image id=%u (%i)\n",
412 image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100413 return io_result;
James Morrissey9d72b4e2014-02-10 17:04:32 +0000414 }
415
416 /* Attempt to access the image */
417 io_result = io_open(dev_handle, image_spec, &image_handle);
Juan Castilloec813f52015-10-01 18:37:40 +0100418 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100419 WARN("Failed to access image id=%u (%i)\n",
420 image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100421 return io_result;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100422 }
423
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000424 INFO("Loading image id=%u at address %p\n", image_id,
425 (void *) image_base);
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100426
James Morrissey9d72b4e2014-02-10 17:04:32 +0000427 /* Find the size of the image */
428 io_result = io_size(image_handle, &image_size);
Juan Castilloec813f52015-10-01 18:37:40 +0100429 if ((io_result != 0) || (image_size == 0)) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100430 WARN("Failed to determine the size of the image id=%u (%i)\n",
431 image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100432 goto exit;
James Morrissey9d72b4e2014-02-10 17:04:32 +0000433 }
434
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100435 /* Check that the memory where the image will be loaded is free */
436 if (!is_mem_free(mem_layout->free_base, mem_layout->free_size,
437 image_base, image_size)) {
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100438 WARN("Failed to reserve region [base = %p, size = 0x%zx]\n",
439 (void *) image_base, image_size);
Vikram Kanigirida567432014-04-15 18:08:08 +0100440 dump_load_info(image_base, image_size, mem_layout);
441 io_result = -ENOMEM;
442 goto exit;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100443 }
444
445 /* We have enough space so load the image now */
James Morrissey9d72b4e2014-02-10 17:04:32 +0000446 /* TODO: Consider whether to try to recover/retry a partially successful read */
Dan Handleya4cb68e2014-04-23 13:47:06 +0100447 io_result = io_read(image_handle, image_base, image_size, &bytes_read);
Juan Castilloec813f52015-10-01 18:37:40 +0100448 if ((io_result != 0) || (bytes_read < image_size)) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100449 WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100450 goto exit;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100451 }
452
Sandrine Bailleux8eaf46e2016-05-27 14:08:10 +0100453 image_data->image_base = image_base;
454 image_data->image_size = image_size;
455
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100456 /*
457 * Update the memory usage info.
458 * This is done after the actual loading so that it is not updated when
459 * the load is unsuccessful.
Juan Castillo09a55a82015-01-19 16:51:21 +0000460 * If the caller does not provide an entry point, bypass the memory
461 * reservation.
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100462 */
Juan Castillo09a55a82015-01-19 16:51:21 +0000463 if (entry_point_info != NULL) {
464 reserve_mem(&mem_layout->free_base, &mem_layout->free_size,
465 image_base, image_size);
Sandrine Bailleux8eaf46e2016-05-27 14:08:10 +0100466 entry_point_info->pc = image_base;
Juan Castillo09a55a82015-01-19 16:51:21 +0000467 } else {
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100468 INFO("Skip reserving region [base = %p, size = 0x%zx]\n",
469 (void *) image_base, image_size);
Juan Castillo09a55a82015-01-19 16:51:21 +0000470 }
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100471
Dan Handley9c96ed52016-07-28 14:38:03 +0100472#if !TRUSTED_BOARD_BOOT
Achin Gupta4f6ad662013-10-25 09:08:21 +0100473 /*
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100474 * File has been successfully loaded.
Dan Handley9c96ed52016-07-28 14:38:03 +0100475 * Flush the image to main memory so that it can be executed later by
476 * any CPU, regardless of cache and MMU state.
477 * When TBB is enabled the image is flushed later, after image
478 * authentication.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100479 */
James Morrissey9d72b4e2014-02-10 17:04:32 +0000480 flush_dcache_range(image_base, image_size);
Dan Handley9c96ed52016-07-28 14:38:03 +0100481#endif /* TRUSTED_BOARD_BOOT */
Achin Gupta4f6ad662013-10-25 09:08:21 +0100482
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100483 INFO("Image id=%u loaded at address %p, size = 0x%zx\n", image_id,
484 (void *) image_base, image_size);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000485
486exit:
Vikram Kanigirida567432014-04-15 18:08:08 +0100487 io_close(image_handle);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000488 /* Ignore improbable/unrecoverable error in 'close' */
489
490 /* TODO: Consider maintaining open device connection from this bootloader stage */
Vikram Kanigirida567432014-04-15 18:08:08 +0100491 io_dev_close(dev_handle);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000492 /* Ignore improbable/unrecoverable error in 'dev_close' */
Achin Gupta4f6ad662013-10-25 09:08:21 +0100493
Vikram Kanigirida567432014-04-15 18:08:08 +0100494 return io_result;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100495}
Juan Castilloa08a5e72015-05-19 11:54:12 +0100496
497/*******************************************************************************
498 * Generic function to load and authenticate an image. The image is actually
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100499 * loaded by calling the 'load_image()' function. Therefore, it returns the
500 * same error codes if the loading operation failed, or -EAUTH if the
501 * authentication failed. In addition, this function uses recursion to
502 * authenticate the parent images up to the root of trust.
Juan Castilloa08a5e72015-05-19 11:54:12 +0100503 ******************************************************************************/
504int load_auth_image(meminfo_t *mem_layout,
505 unsigned int image_id,
506 uintptr_t image_base,
507 image_info_t *image_data,
508 entry_point_info_t *entry_point_info)
509{
510 int rc;
511
512#if TRUSTED_BOARD_BOOT
513 unsigned int parent_id;
514
515 /* Use recursion to authenticate parent images */
516 rc = auth_mod_get_parent_id(image_id, &parent_id);
517 if (rc == 0) {
518 rc = load_auth_image(mem_layout, parent_id, image_base,
519 image_data, NULL);
Juan Castilloec813f52015-10-01 18:37:40 +0100520 if (rc != 0) {
Juan Castilloa08a5e72015-05-19 11:54:12 +0100521 return rc;
522 }
523 }
524#endif /* TRUSTED_BOARD_BOOT */
525
526 /* Load the image */
527 rc = load_image(mem_layout, image_id, image_base, image_data,
528 entry_point_info);
Juan Castilloec813f52015-10-01 18:37:40 +0100529 if (rc != 0) {
530 return rc;
Juan Castilloa08a5e72015-05-19 11:54:12 +0100531 }
532
533#if TRUSTED_BOARD_BOOT
534 /* Authenticate it */
535 rc = auth_mod_verify_img(image_id,
536 (void *)image_data->image_base,
537 image_data->image_size);
538 if (rc != 0) {
Juan Castillo97dbcf12015-08-17 10:43:27 +0100539 memset((void *)image_data->image_base, 0x00,
540 image_data->image_size);
541 flush_dcache_range(image_data->image_base,
542 image_data->image_size);
Juan Castilloec813f52015-10-01 18:37:40 +0100543 return -EAUTH;
Juan Castilloa08a5e72015-05-19 11:54:12 +0100544 }
Dan Handley9c96ed52016-07-28 14:38:03 +0100545 /*
546 * File has been successfully loaded and authenticated.
547 * Flush the image to main memory so that it can be executed later by
548 * any CPU, regardless of cache and MMU state.
549 */
550 flush_dcache_range(image_data->image_base, image_data->image_size);
Juan Castilloa08a5e72015-05-19 11:54:12 +0100551#endif /* TRUSTED_BOARD_BOOT */
552
Juan Castilloec813f52015-10-01 18:37:40 +0100553 return 0;
Juan Castilloa08a5e72015-05-19 11:54:12 +0100554}
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100555
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100556#endif /* LOAD_IMAGE_V2 */
557
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100558/*******************************************************************************
559 * Print the content of an entry_point_info_t structure.
560 ******************************************************************************/
561void print_entry_point_info(const entry_point_info_t *ep_info)
562{
Soby Mathewa0fedc42016-06-16 14:52:04 +0100563 INFO("Entry point address = %p\n", (void *)ep_info->pc);
564 INFO("SPSR = 0x%x\n", ep_info->spsr);
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100565
566#define PRINT_IMAGE_ARG(n) \
567 VERBOSE("Argument #" #n " = 0x%llx\n", \
568 (unsigned long long) ep_info->args.arg##n)
569
570 PRINT_IMAGE_ARG(0);
571 PRINT_IMAGE_ARG(1);
572 PRINT_IMAGE_ARG(2);
573 PRINT_IMAGE_ARG(3);
Soby Mathewcdf58cb2016-08-30 13:07:31 +0100574#ifndef AARCH32
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100575 PRINT_IMAGE_ARG(4);
576 PRINT_IMAGE_ARG(5);
577 PRINT_IMAGE_ARG(6);
578 PRINT_IMAGE_ARG(7);
Soby Mathewcdf58cb2016-08-30 13:07:31 +0100579#endif
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100580#undef PRINT_IMAGE_ARG
581}