blob: b0d1bfa7572a22a7b4f7846a42b2c11fb0910be5 [file] [log] [blame]
Achin Gupta4f6ad662013-10-25 09:08:21 +01001/*
Douglas Raillard21362a92016-12-02 13:51:54 +00002 * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
Achin Gupta4f6ad662013-10-25 09:08:21 +01003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Achin Gupta4f6ad662013-10-25 09:08:21 +01005 */
6
Dan Handley2bd4ef22014-04-09 13:14:54 +01007#include <arch.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +01008#include <arch_helpers.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +01009#include <assert.h>
Juan Castilloa08a5e72015-05-19 11:54:12 +010010#include <auth_mod.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010011#include <bl_common.h>
Dan Handley714a0d22014-04-09 13:13:04 +010012#include <debug.h>
Sandrine Bailleux467d0572014-06-24 14:02:34 +010013#include <errno.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010014#include <io_storage.h>
15#include <platform.h>
Juan Castillo97dbcf12015-08-17 10:43:27 +010016#include <string.h>
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +010017#include <utils.h>
Antonio Nino Diaz4ef91f12017-02-20 14:22:22 +000018#include <xlat_tables_defs.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010019
Soby Mathewa0fedc42016-06-16 14:52:04 +010020uintptr_t page_align(uintptr_t value, unsigned dir)
Achin Gupta4f6ad662013-10-25 09:08:21 +010021{
Achin Gupta4f6ad662013-10-25 09:08:21 +010022 /* Round up the limit to the next page boundary */
Soby Mathewa0fedc42016-06-16 14:52:04 +010023 if (value & (PAGE_SIZE - 1)) {
24 value &= ~(PAGE_SIZE - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +010025 if (dir == UP)
Soby Mathewa0fedc42016-06-16 14:52:04 +010026 value += PAGE_SIZE;
Achin Gupta4f6ad662013-10-25 09:08:21 +010027 }
28
29 return value;
30}
31
Sandrine Bailleux467d0572014-06-24 14:02:34 +010032/******************************************************************************
33 * Determine whether the memory region delimited by 'addr' and 'size' is free,
34 * given the extents of free memory.
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +010035 * Return 1 if it is free, 0 if it is not free or if the input values are
36 * invalid.
Sandrine Bailleux467d0572014-06-24 14:02:34 +010037 *****************************************************************************/
Sandrine Bailleuxb0e529b2016-11-08 14:27:10 +000038int is_mem_free(uintptr_t free_base, size_t free_size,
Soby Mathewa0fedc42016-06-16 14:52:04 +010039 uintptr_t addr, size_t size)
Sandrine Bailleux467d0572014-06-24 14:02:34 +010040{
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +010041 uintptr_t free_end, requested_end;
42
43 /*
44 * Handle corner cases first.
45 *
46 * The order of the 2 tests is important, because if there's no space
47 * left (i.e. free_size == 0) but we don't ask for any memory
48 * (i.e. size == 0) then we should report that the memory is free.
49 */
50 if (size == 0)
51 return 1; /* A zero-byte region is always free */
52 if (free_size == 0)
53 return 0;
54
55 /*
56 * Check that the end addresses don't overflow.
57 * If they do, consider that this memory region is not free, as this
58 * is an invalid scenario.
59 */
60 if (check_uptr_overflow(free_base, free_size - 1))
61 return 0;
62 free_end = free_base + (free_size - 1);
63
64 if (check_uptr_overflow(addr, size - 1))
65 return 0;
66 requested_end = addr + (size - 1);
67
68 /*
69 * Finally, check that the requested memory region lies within the free
70 * region.
71 */
72 return (addr >= free_base) && (requested_end <= free_end);
Sandrine Bailleux467d0572014-06-24 14:02:34 +010073}
Achin Gupta4f6ad662013-10-25 09:08:21 +010074
Sandrine Bailleuxb0e529b2016-11-08 14:27:10 +000075#if !LOAD_IMAGE_V2
Sandrine Bailleux467d0572014-06-24 14:02:34 +010076/******************************************************************************
77 * Inside a given memory region, determine whether a sub-region of memory is
78 * closer from the top or the bottom of the encompassing region. Return the
79 * size of the smallest chunk of free memory surrounding the sub-region in
80 * 'small_chunk_size'.
81 *****************************************************************************/
Soby Mathewa0fedc42016-06-16 14:52:04 +010082static unsigned int choose_mem_pos(uintptr_t mem_start, uintptr_t mem_end,
83 uintptr_t submem_start, uintptr_t submem_end,
84 size_t *small_chunk_size)
Achin Gupta4f6ad662013-10-25 09:08:21 +010085{
Sandrine Bailleux467d0572014-06-24 14:02:34 +010086 size_t top_chunk_size, bottom_chunk_size;
87
88 assert(mem_start <= submem_start);
89 assert(submem_start <= submem_end);
90 assert(submem_end <= mem_end);
91 assert(small_chunk_size != NULL);
Achin Gupta4f6ad662013-10-25 09:08:21 +010092
Sandrine Bailleux467d0572014-06-24 14:02:34 +010093 top_chunk_size = mem_end - submem_end;
94 bottom_chunk_size = submem_start - mem_start;
Achin Gupta4f6ad662013-10-25 09:08:21 +010095
Sandrine Bailleux467d0572014-06-24 14:02:34 +010096 if (top_chunk_size < bottom_chunk_size) {
97 *small_chunk_size = top_chunk_size;
98 return TOP;
Achin Gupta4f6ad662013-10-25 09:08:21 +010099 } else {
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100100 *small_chunk_size = bottom_chunk_size;
101 return BOTTOM;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100102 }
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100103}
104
105/******************************************************************************
106 * Reserve the memory region delimited by 'addr' and 'size'. The extents of free
107 * memory are passed in 'free_base' and 'free_size' and they will be updated to
108 * reflect the memory usage.
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100109 * The caller must ensure the memory to reserve is free and that the addresses
110 * and sizes passed in arguments are sane.
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100111 *****************************************************************************/
Soby Mathewa0fedc42016-06-16 14:52:04 +0100112void reserve_mem(uintptr_t *free_base, size_t *free_size,
113 uintptr_t addr, size_t size)
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100114{
115 size_t discard_size;
116 size_t reserved_size;
117 unsigned int pos;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100118
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100119 assert(free_base != NULL);
120 assert(free_size != NULL);
121 assert(is_mem_free(*free_base, *free_size, addr, size));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100122
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100123 if (size == 0) {
124 WARN("Nothing to allocate, requested size is zero\n");
125 return;
126 }
127
128 pos = choose_mem_pos(*free_base, *free_base + (*free_size - 1),
129 addr, addr + (size - 1),
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100130 &discard_size);
131
132 reserved_size = size + discard_size;
133 *free_size -= reserved_size;
134
135 if (pos == BOTTOM)
136 *free_base = addr + size;
137
Soby Mathewa0fedc42016-06-16 14:52:04 +0100138 VERBOSE("Reserved 0x%zx bytes (discarded 0x%zx bytes %s)\n",
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100139 reserved_size, discard_size,
140 pos == TOP ? "above" : "below");
Achin Gupta4f6ad662013-10-25 09:08:21 +0100141}
142
Soby Mathewa0fedc42016-06-16 14:52:04 +0100143static void dump_load_info(uintptr_t image_load_addr,
144 size_t image_size,
Dan Handleye2712bc2014-04-10 15:37:22 +0100145 const meminfo_t *mem_layout)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100146{
Soby Mathewa0fedc42016-06-16 14:52:04 +0100147 INFO("Trying to load image at address %p, size = 0x%zx\n",
148 (void *)image_load_addr, image_size);
Dan Handley91b624e2014-07-29 17:14:00 +0100149 INFO("Current memory layout:\n");
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100150 INFO(" total region = [base = %p, size = 0x%zx]\n",
151 (void *) mem_layout->total_base, mem_layout->total_size);
152 INFO(" free region = [base = %p, size = 0x%zx]\n",
153 (void *) mem_layout->free_base, mem_layout->free_size);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100154}
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100155#endif /* LOAD_IMAGE_V2 */
Achin Gupta4f6ad662013-10-25 09:08:21 +0100156
Ryan Harkin87274c42014-02-04 11:43:57 +0000157/* Generic function to return the size of an image */
Soby Mathewa0fedc42016-06-16 14:52:04 +0100158size_t image_size(unsigned int image_id)
Ryan Harkin87274c42014-02-04 11:43:57 +0000159{
Dan Handleya4cb68e2014-04-23 13:47:06 +0100160 uintptr_t dev_handle;
161 uintptr_t image_handle;
162 uintptr_t image_spec;
Ryan Harkin87274c42014-02-04 11:43:57 +0000163 size_t image_size = 0;
Juan Castillo6e762062015-11-02 10:47:01 +0000164 int io_result;
Ryan Harkin87274c42014-02-04 11:43:57 +0000165
Ryan Harkin87274c42014-02-04 11:43:57 +0000166 /* Obtain a reference to the image by querying the platform layer */
Juan Castillo3a66aca2015-04-13 17:36:19 +0100167 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
Juan Castillo6e762062015-11-02 10:47:01 +0000168 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100169 WARN("Failed to obtain reference to image id=%u (%i)\n",
170 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000171 return 0;
172 }
173
174 /* Attempt to access the image */
175 io_result = io_open(dev_handle, image_spec, &image_handle);
Juan Castillo6e762062015-11-02 10:47:01 +0000176 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100177 WARN("Failed to access image id=%u (%i)\n",
178 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000179 return 0;
180 }
181
182 /* Find the size of the image */
183 io_result = io_size(image_handle, &image_size);
Juan Castillo6e762062015-11-02 10:47:01 +0000184 if ((io_result != 0) || (image_size == 0)) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100185 WARN("Failed to determine the size of the image id=%u (%i)\n",
186 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000187 }
188 io_result = io_close(image_handle);
189 /* Ignore improbable/unrecoverable error in 'close' */
190
191 /* TODO: Consider maintaining open device connection from this
192 * bootloader stage
193 */
194 io_result = io_dev_close(dev_handle);
195 /* Ignore improbable/unrecoverable error in 'dev_close' */
196
197 return image_size;
198}
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100199
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100200#if LOAD_IMAGE_V2
201
202/*******************************************************************************
Soby Mathew7c8af062017-11-10 13:14:40 +0000203 * Internal function to load an image at a specific address given
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100204 * an image ID and extents of free memory.
205 *
206 * If the load is successful then the image information is updated.
207 *
208 * Returns 0 on success, a negative error code otherwise.
209 ******************************************************************************/
Soby Mathew7c8af062017-11-10 13:14:40 +0000210static int load_image(unsigned int image_id, image_info_t *image_data)
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100211{
212 uintptr_t dev_handle;
213 uintptr_t image_handle;
214 uintptr_t image_spec;
215 uintptr_t image_base;
216 size_t image_size;
217 size_t bytes_read;
218 int io_result;
219
220 assert(image_data != NULL);
221 assert(image_data->h.version >= VERSION_2);
222
223 image_base = image_data->image_base;
224
225 /* Obtain a reference to the image by querying the platform layer */
226 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
227 if (io_result != 0) {
228 WARN("Failed to obtain reference to image id=%u (%i)\n",
229 image_id, io_result);
230 return io_result;
231 }
232
233 /* Attempt to access the image */
234 io_result = io_open(dev_handle, image_spec, &image_handle);
235 if (io_result != 0) {
236 WARN("Failed to access image id=%u (%i)\n",
237 image_id, io_result);
238 return io_result;
239 }
240
241 INFO("Loading image id=%u at address %p\n", image_id,
242 (void *) image_base);
243
244 /* Find the size of the image */
245 io_result = io_size(image_handle, &image_size);
246 if ((io_result != 0) || (image_size == 0)) {
247 WARN("Failed to determine the size of the image id=%u (%i)\n",
248 image_id, io_result);
249 goto exit;
250 }
251
252 /* Check that the image size to load is within limit */
253 if (image_size > image_data->image_max_size) {
254 WARN("Image id=%u size out of bounds\n", image_id);
255 io_result = -EFBIG;
256 goto exit;
257 }
258
259 image_data->image_size = image_size;
260
261 /* We have enough space so load the image now */
262 /* TODO: Consider whether to try to recover/retry a partially successful read */
263 io_result = io_read(image_handle, image_base, image_size, &bytes_read);
264 if ((io_result != 0) || (bytes_read < image_size)) {
265 WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
266 goto exit;
267 }
268
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100269 INFO("Image id=%u loaded: %p - %p\n", image_id, (void *) image_base,
270 (void *) (image_base + image_size));
271
272exit:
273 io_close(image_handle);
274 /* Ignore improbable/unrecoverable error in 'close' */
275
276 /* TODO: Consider maintaining open device connection from this bootloader stage */
277 io_dev_close(dev_handle);
278 /* Ignore improbable/unrecoverable error in 'dev_close' */
279
280 return io_result;
281}
282
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000283static int load_auth_image_internal(unsigned int image_id,
284 image_info_t *image_data,
285 int is_parent_image)
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100286{
287 int rc;
288
289#if TRUSTED_BOARD_BOOT
290 unsigned int parent_id;
291
292 /* Use recursion to authenticate parent images */
293 rc = auth_mod_get_parent_id(image_id, &parent_id);
294 if (rc == 0) {
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000295 rc = load_auth_image_internal(parent_id, image_data, 1);
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100296 if (rc != 0) {
297 return rc;
298 }
299 }
300#endif /* TRUSTED_BOARD_BOOT */
301
302 /* Load the image */
303 rc = load_image(image_id, image_data);
304 if (rc != 0) {
305 return rc;
306 }
307
308#if TRUSTED_BOARD_BOOT
309 /* Authenticate it */
310 rc = auth_mod_verify_img(image_id,
311 (void *)image_data->image_base,
312 image_data->image_size);
313 if (rc != 0) {
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000314 /* Authentication error, zero memory and flush it right away. */
Douglas Raillard21362a92016-12-02 13:51:54 +0000315 zero_normalmem((void *)image_data->image_base,
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100316 image_data->image_size);
317 flush_dcache_range(image_data->image_base,
318 image_data->image_size);
319 return -EAUTH;
320 }
Soby Mathew7c8af062017-11-10 13:14:40 +0000321#endif /* TRUSTED_BOARD_BOOT */
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100322
323 /*
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100324 * Flush the image to main memory so that it can be executed later by
Soby Mathew7c8af062017-11-10 13:14:40 +0000325 * any CPU, regardless of cache and MMU state. If TBB is enabled, then
326 * the file has been successfully loaded and authenticated and flush
327 * only for child images, not for the parents (certificates).
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100328 */
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000329 if (!is_parent_image) {
330 flush_dcache_range(image_data->image_base,
331 image_data->image_size);
332 }
Soby Mathew7c8af062017-11-10 13:14:40 +0000333
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100334
335 return 0;
336}
337
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000338/*******************************************************************************
339 * Generic function to load and authenticate an image. The image is actually
340 * loaded by calling the 'load_image()' function. Therefore, it returns the
341 * same error codes if the loading operation failed, or -EAUTH if the
342 * authentication failed. In addition, this function uses recursion to
343 * authenticate the parent images up to the root of trust.
344 ******************************************************************************/
345int load_auth_image(unsigned int image_id, image_info_t *image_data)
346{
Roberto Vargasbc1ae1f2017-09-26 12:53:01 +0100347 int err;
348
349 do {
350 err = load_auth_image_internal(image_id, image_data, 0);
351 } while (err != 0 && plat_try_next_boot_source());
352
353 return err;
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000354}
355
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100356#else /* LOAD_IMAGE_V2 */
357
Achin Gupta4f6ad662013-10-25 09:08:21 +0100358/*******************************************************************************
Sandrine Bailleux8eaf46e2016-05-27 14:08:10 +0100359 * Generic function to load an image at a specific address given an image ID and
360 * extents of free memory.
361 *
362 * If the load is successful then the image information is updated.
363 *
364 * If the entry_point_info argument is not NULL then this function also updates:
365 * - the memory layout to mark the memory as reserved;
366 * - the entry point information.
367 *
368 * The caller might pass a NULL pointer for the entry point if they are not
369 * interested in this information. This is typically the case for non-executable
370 * images (e.g. certificates) and executable images that won't ever be executed
371 * on the application processor (e.g. additional microcontroller firmware).
372 *
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100373 * Returns 0 on success, a negative error code otherwise.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100374 ******************************************************************************/
Vikram Kanigirida567432014-04-15 18:08:08 +0100375int load_image(meminfo_t *mem_layout,
Juan Castillo3a66aca2015-04-13 17:36:19 +0100376 unsigned int image_id,
Juan Castilloa08a5e72015-05-19 11:54:12 +0100377 uintptr_t image_base,
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100378 image_info_t *image_data,
379 entry_point_info_t *entry_point_info)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100380{
Dan Handleya4cb68e2014-04-23 13:47:06 +0100381 uintptr_t dev_handle;
382 uintptr_t image_handle;
383 uintptr_t image_spec;
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100384 size_t image_size;
385 size_t bytes_read;
Juan Castilloec813f52015-10-01 18:37:40 +0100386 int io_result;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100387
James Morrissey9d72b4e2014-02-10 17:04:32 +0000388 assert(mem_layout != NULL);
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100389 assert(image_data != NULL);
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100390 assert(image_data->h.version == VERSION_1);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000391
392 /* Obtain a reference to the image by querying the platform layer */
Juan Castillo3a66aca2015-04-13 17:36:19 +0100393 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
Juan Castilloec813f52015-10-01 18:37:40 +0100394 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100395 WARN("Failed to obtain reference to image id=%u (%i)\n",
396 image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100397 return io_result;
James Morrissey9d72b4e2014-02-10 17:04:32 +0000398 }
399
400 /* Attempt to access the image */
401 io_result = io_open(dev_handle, image_spec, &image_handle);
Juan Castilloec813f52015-10-01 18:37:40 +0100402 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100403 WARN("Failed to access image id=%u (%i)\n",
404 image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100405 return io_result;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100406 }
407
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000408 INFO("Loading image id=%u at address %p\n", image_id,
409 (void *) image_base);
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100410
James Morrissey9d72b4e2014-02-10 17:04:32 +0000411 /* Find the size of the image */
412 io_result = io_size(image_handle, &image_size);
Juan Castilloec813f52015-10-01 18:37:40 +0100413 if ((io_result != 0) || (image_size == 0)) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100414 WARN("Failed to determine the size of the image id=%u (%i)\n",
415 image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100416 goto exit;
James Morrissey9d72b4e2014-02-10 17:04:32 +0000417 }
418
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100419 /* Check that the memory where the image will be loaded is free */
420 if (!is_mem_free(mem_layout->free_base, mem_layout->free_size,
421 image_base, image_size)) {
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100422 WARN("Failed to reserve region [base = %p, size = 0x%zx]\n",
423 (void *) image_base, image_size);
Vikram Kanigirida567432014-04-15 18:08:08 +0100424 dump_load_info(image_base, image_size, mem_layout);
425 io_result = -ENOMEM;
426 goto exit;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100427 }
428
429 /* We have enough space so load the image now */
James Morrissey9d72b4e2014-02-10 17:04:32 +0000430 /* TODO: Consider whether to try to recover/retry a partially successful read */
Dan Handleya4cb68e2014-04-23 13:47:06 +0100431 io_result = io_read(image_handle, image_base, image_size, &bytes_read);
Juan Castilloec813f52015-10-01 18:37:40 +0100432 if ((io_result != 0) || (bytes_read < image_size)) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100433 WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100434 goto exit;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100435 }
436
Sandrine Bailleux8eaf46e2016-05-27 14:08:10 +0100437 image_data->image_base = image_base;
438 image_data->image_size = image_size;
439
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100440 /*
441 * Update the memory usage info.
442 * This is done after the actual loading so that it is not updated when
443 * the load is unsuccessful.
Juan Castillo09a55a82015-01-19 16:51:21 +0000444 * If the caller does not provide an entry point, bypass the memory
445 * reservation.
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100446 */
Juan Castillo09a55a82015-01-19 16:51:21 +0000447 if (entry_point_info != NULL) {
448 reserve_mem(&mem_layout->free_base, &mem_layout->free_size,
449 image_base, image_size);
Sandrine Bailleux8eaf46e2016-05-27 14:08:10 +0100450 entry_point_info->pc = image_base;
Juan Castillo09a55a82015-01-19 16:51:21 +0000451 } else {
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100452 INFO("Skip reserving region [base = %p, size = 0x%zx]\n",
453 (void *) image_base, image_size);
Juan Castillo09a55a82015-01-19 16:51:21 +0000454 }
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100455
Dan Handley9c96ed52016-07-28 14:38:03 +0100456#if !TRUSTED_BOARD_BOOT
Achin Gupta4f6ad662013-10-25 09:08:21 +0100457 /*
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100458 * File has been successfully loaded.
Dan Handley9c96ed52016-07-28 14:38:03 +0100459 * Flush the image to main memory so that it can be executed later by
460 * any CPU, regardless of cache and MMU state.
461 * When TBB is enabled the image is flushed later, after image
462 * authentication.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100463 */
James Morrissey9d72b4e2014-02-10 17:04:32 +0000464 flush_dcache_range(image_base, image_size);
Dan Handley9c96ed52016-07-28 14:38:03 +0100465#endif /* TRUSTED_BOARD_BOOT */
Achin Gupta4f6ad662013-10-25 09:08:21 +0100466
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100467 INFO("Image id=%u loaded at address %p, size = 0x%zx\n", image_id,
468 (void *) image_base, image_size);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000469
470exit:
Vikram Kanigirida567432014-04-15 18:08:08 +0100471 io_close(image_handle);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000472 /* Ignore improbable/unrecoverable error in 'close' */
473
474 /* TODO: Consider maintaining open device connection from this bootloader stage */
Vikram Kanigirida567432014-04-15 18:08:08 +0100475 io_dev_close(dev_handle);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000476 /* Ignore improbable/unrecoverable error in 'dev_close' */
Achin Gupta4f6ad662013-10-25 09:08:21 +0100477
Vikram Kanigirida567432014-04-15 18:08:08 +0100478 return io_result;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100479}
Juan Castilloa08a5e72015-05-19 11:54:12 +0100480
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000481static int load_auth_image_internal(meminfo_t *mem_layout,
482 unsigned int image_id,
483 uintptr_t image_base,
484 image_info_t *image_data,
485 entry_point_info_t *entry_point_info,
486 int is_parent_image)
Juan Castilloa08a5e72015-05-19 11:54:12 +0100487{
488 int rc;
489
490#if TRUSTED_BOARD_BOOT
491 unsigned int parent_id;
492
493 /* Use recursion to authenticate parent images */
494 rc = auth_mod_get_parent_id(image_id, &parent_id);
495 if (rc == 0) {
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000496 rc = load_auth_image_internal(mem_layout, parent_id, image_base,
497 image_data, NULL, 1);
Juan Castilloec813f52015-10-01 18:37:40 +0100498 if (rc != 0) {
Juan Castilloa08a5e72015-05-19 11:54:12 +0100499 return rc;
500 }
501 }
502#endif /* TRUSTED_BOARD_BOOT */
503
504 /* Load the image */
505 rc = load_image(mem_layout, image_id, image_base, image_data,
506 entry_point_info);
Juan Castilloec813f52015-10-01 18:37:40 +0100507 if (rc != 0) {
508 return rc;
Juan Castilloa08a5e72015-05-19 11:54:12 +0100509 }
510
511#if TRUSTED_BOARD_BOOT
512 /* Authenticate it */
513 rc = auth_mod_verify_img(image_id,
514 (void *)image_data->image_base,
515 image_data->image_size);
516 if (rc != 0) {
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000517 /* Authentication error, zero memory and flush it right away. */
Douglas Raillard21362a92016-12-02 13:51:54 +0000518 zero_normalmem((void *)image_data->image_base,
Juan Castillo97dbcf12015-08-17 10:43:27 +0100519 image_data->image_size);
520 flush_dcache_range(image_data->image_base,
521 image_data->image_size);
Juan Castilloec813f52015-10-01 18:37:40 +0100522 return -EAUTH;
Juan Castilloa08a5e72015-05-19 11:54:12 +0100523 }
Dan Handley9c96ed52016-07-28 14:38:03 +0100524 /*
525 * File has been successfully loaded and authenticated.
526 * Flush the image to main memory so that it can be executed later by
527 * any CPU, regardless of cache and MMU state.
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000528 * Do it only for child images, not for the parents (certificates).
Dan Handley9c96ed52016-07-28 14:38:03 +0100529 */
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000530 if (!is_parent_image) {
531 flush_dcache_range(image_data->image_base,
532 image_data->image_size);
533 }
Juan Castilloa08a5e72015-05-19 11:54:12 +0100534#endif /* TRUSTED_BOARD_BOOT */
535
Juan Castilloec813f52015-10-01 18:37:40 +0100536 return 0;
Juan Castilloa08a5e72015-05-19 11:54:12 +0100537}
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100538
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000539/*******************************************************************************
540 * Generic function to load and authenticate an image. The image is actually
541 * loaded by calling the 'load_image()' function. Therefore, it returns the
542 * same error codes if the loading operation failed, or -EAUTH if the
543 * authentication failed. In addition, this function uses recursion to
544 * authenticate the parent images up to the root of trust.
545 ******************************************************************************/
546int load_auth_image(meminfo_t *mem_layout,
547 unsigned int image_id,
548 uintptr_t image_base,
549 image_info_t *image_data,
550 entry_point_info_t *entry_point_info)
551{
Roberto Vargasbc1ae1f2017-09-26 12:53:01 +0100552 int err;
553
554 do {
555 err = load_auth_image_internal(mem_layout, image_id, image_base,
556 image_data, entry_point_info, 0);
557 } while (err != 0 && plat_try_next_boot_source());
558
559 return err;
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000560}
561
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100562#endif /* LOAD_IMAGE_V2 */
563
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100564/*******************************************************************************
565 * Print the content of an entry_point_info_t structure.
566 ******************************************************************************/
567void print_entry_point_info(const entry_point_info_t *ep_info)
568{
Soby Mathewa0fedc42016-06-16 14:52:04 +0100569 INFO("Entry point address = %p\n", (void *)ep_info->pc);
570 INFO("SPSR = 0x%x\n", ep_info->spsr);
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100571
572#define PRINT_IMAGE_ARG(n) \
573 VERBOSE("Argument #" #n " = 0x%llx\n", \
574 (unsigned long long) ep_info->args.arg##n)
575
576 PRINT_IMAGE_ARG(0);
577 PRINT_IMAGE_ARG(1);
578 PRINT_IMAGE_ARG(2);
579 PRINT_IMAGE_ARG(3);
Soby Mathewcdf58cb2016-08-30 13:07:31 +0100580#ifndef AARCH32
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100581 PRINT_IMAGE_ARG(4);
582 PRINT_IMAGE_ARG(5);
583 PRINT_IMAGE_ARG(6);
584 PRINT_IMAGE_ARG(7);
Soby Mathewcdf58cb2016-08-30 13:07:31 +0100585#endif
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100586#undef PRINT_IMAGE_ARG
587}