blob: 6b979f64ae520755e08318ea5433679df351afbc [file] [log] [blame]
Achin Gupta4f6ad662013-10-25 09:08:21 +01001/*
Soby Mathew9fe88042018-03-26 12:43:37 +01002 * Copyright (c) 2013-2018, 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 Mathew9fe88042018-03-26 12:43:37 +010020#if TRUSTED_BOARD_BOOT
21# ifdef DYN_DISABLE_AUTH
22static int disable_auth;
23
24/******************************************************************************
25 * API to dynamically disable authentication. Only meant for development
26 * systems. This is only invoked if DYN_DISABLE_AUTH is defined. This
27 * capability is restricted to LOAD_IMAGE_V2.
28 *****************************************************************************/
29void dyn_disable_auth(void)
30{
31 INFO("Disabling authentication of images dynamically\n");
32 disable_auth = 1;
33}
34# endif /* DYN_DISABLE_AUTH */
35
36/******************************************************************************
37 * Function to determine whether the authentication is disabled dynamically.
38 *****************************************************************************/
39static int dyn_is_auth_disabled(void)
40{
41# ifdef DYN_DISABLE_AUTH
42 return disable_auth;
43# else
44 return 0;
45# endif
46}
47#endif /* TRUSTED_BOARD_BOOT */
48
Soby Mathewa0fedc42016-06-16 14:52:04 +010049uintptr_t page_align(uintptr_t value, unsigned dir)
Achin Gupta4f6ad662013-10-25 09:08:21 +010050{
Achin Gupta4f6ad662013-10-25 09:08:21 +010051 /* Round up the limit to the next page boundary */
Soby Mathewa0fedc42016-06-16 14:52:04 +010052 if (value & (PAGE_SIZE - 1)) {
53 value &= ~(PAGE_SIZE - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +010054 if (dir == UP)
Soby Mathewa0fedc42016-06-16 14:52:04 +010055 value += PAGE_SIZE;
Achin Gupta4f6ad662013-10-25 09:08:21 +010056 }
57
58 return value;
59}
60
Sandrine Bailleux467d0572014-06-24 14:02:34 +010061/******************************************************************************
62 * Determine whether the memory region delimited by 'addr' and 'size' is free,
63 * given the extents of free memory.
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +010064 * Return 1 if it is free, 0 if it is not free or if the input values are
65 * invalid.
Sandrine Bailleux467d0572014-06-24 14:02:34 +010066 *****************************************************************************/
Sandrine Bailleuxb0e529b2016-11-08 14:27:10 +000067int is_mem_free(uintptr_t free_base, size_t free_size,
Soby Mathewa0fedc42016-06-16 14:52:04 +010068 uintptr_t addr, size_t size)
Sandrine Bailleux467d0572014-06-24 14:02:34 +010069{
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +010070 uintptr_t free_end, requested_end;
71
72 /*
73 * Handle corner cases first.
74 *
75 * The order of the 2 tests is important, because if there's no space
76 * left (i.e. free_size == 0) but we don't ask for any memory
77 * (i.e. size == 0) then we should report that the memory is free.
78 */
79 if (size == 0)
80 return 1; /* A zero-byte region is always free */
81 if (free_size == 0)
82 return 0;
83
84 /*
85 * Check that the end addresses don't overflow.
86 * If they do, consider that this memory region is not free, as this
87 * is an invalid scenario.
88 */
89 if (check_uptr_overflow(free_base, free_size - 1))
90 return 0;
91 free_end = free_base + (free_size - 1);
92
93 if (check_uptr_overflow(addr, size - 1))
94 return 0;
95 requested_end = addr + (size - 1);
96
97 /*
98 * Finally, check that the requested memory region lies within the free
99 * region.
100 */
101 return (addr >= free_base) && (requested_end <= free_end);
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100102}
Achin Gupta4f6ad662013-10-25 09:08:21 +0100103
Sandrine Bailleuxb0e529b2016-11-08 14:27:10 +0000104#if !LOAD_IMAGE_V2
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100105/******************************************************************************
106 * Inside a given memory region, determine whether a sub-region of memory is
107 * closer from the top or the bottom of the encompassing region. Return the
108 * size of the smallest chunk of free memory surrounding the sub-region in
109 * 'small_chunk_size'.
110 *****************************************************************************/
Soby Mathewa0fedc42016-06-16 14:52:04 +0100111static unsigned int choose_mem_pos(uintptr_t mem_start, uintptr_t mem_end,
112 uintptr_t submem_start, uintptr_t submem_end,
113 size_t *small_chunk_size)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100114{
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100115 size_t top_chunk_size, bottom_chunk_size;
116
117 assert(mem_start <= submem_start);
118 assert(submem_start <= submem_end);
119 assert(submem_end <= mem_end);
120 assert(small_chunk_size != NULL);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100121
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100122 top_chunk_size = mem_end - submem_end;
123 bottom_chunk_size = submem_start - mem_start;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100124
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100125 if (top_chunk_size < bottom_chunk_size) {
126 *small_chunk_size = top_chunk_size;
127 return TOP;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100128 } else {
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100129 *small_chunk_size = bottom_chunk_size;
130 return BOTTOM;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100131 }
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100132}
133
134/******************************************************************************
135 * Reserve the memory region delimited by 'addr' and 'size'. The extents of free
136 * memory are passed in 'free_base' and 'free_size' and they will be updated to
137 * reflect the memory usage.
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100138 * The caller must ensure the memory to reserve is free and that the addresses
139 * and sizes passed in arguments are sane.
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100140 *****************************************************************************/
Soby Mathewa0fedc42016-06-16 14:52:04 +0100141void reserve_mem(uintptr_t *free_base, size_t *free_size,
142 uintptr_t addr, size_t size)
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100143{
144 size_t discard_size;
145 size_t reserved_size;
146 unsigned int pos;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100147
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100148 assert(free_base != NULL);
149 assert(free_size != NULL);
150 assert(is_mem_free(*free_base, *free_size, addr, size));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100151
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100152 if (size == 0) {
153 WARN("Nothing to allocate, requested size is zero\n");
154 return;
155 }
156
157 pos = choose_mem_pos(*free_base, *free_base + (*free_size - 1),
158 addr, addr + (size - 1),
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100159 &discard_size);
160
161 reserved_size = size + discard_size;
162 *free_size -= reserved_size;
163
164 if (pos == BOTTOM)
165 *free_base = addr + size;
166
Soby Mathewa0fedc42016-06-16 14:52:04 +0100167 VERBOSE("Reserved 0x%zx bytes (discarded 0x%zx bytes %s)\n",
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100168 reserved_size, discard_size,
169 pos == TOP ? "above" : "below");
Achin Gupta4f6ad662013-10-25 09:08:21 +0100170}
171
Soby Mathewa0fedc42016-06-16 14:52:04 +0100172static void dump_load_info(uintptr_t image_load_addr,
173 size_t image_size,
Dan Handleye2712bc2014-04-10 15:37:22 +0100174 const meminfo_t *mem_layout)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100175{
Soby Mathewa0fedc42016-06-16 14:52:04 +0100176 INFO("Trying to load image at address %p, size = 0x%zx\n",
177 (void *)image_load_addr, image_size);
Dan Handley91b624e2014-07-29 17:14:00 +0100178 INFO("Current memory layout:\n");
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100179 INFO(" total region = [base = %p, size = 0x%zx]\n",
180 (void *) mem_layout->total_base, mem_layout->total_size);
181 INFO(" free region = [base = %p, size = 0x%zx]\n",
182 (void *) mem_layout->free_base, mem_layout->free_size);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100183}
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100184#endif /* LOAD_IMAGE_V2 */
Achin Gupta4f6ad662013-10-25 09:08:21 +0100185
Ryan Harkin87274c42014-02-04 11:43:57 +0000186/* Generic function to return the size of an image */
Soby Mathewa0fedc42016-06-16 14:52:04 +0100187size_t image_size(unsigned int image_id)
Ryan Harkin87274c42014-02-04 11:43:57 +0000188{
Dan Handleya4cb68e2014-04-23 13:47:06 +0100189 uintptr_t dev_handle;
190 uintptr_t image_handle;
191 uintptr_t image_spec;
Ryan Harkin87274c42014-02-04 11:43:57 +0000192 size_t image_size = 0;
Juan Castillo6e762062015-11-02 10:47:01 +0000193 int io_result;
Ryan Harkin87274c42014-02-04 11:43:57 +0000194
Ryan Harkin87274c42014-02-04 11:43:57 +0000195 /* Obtain a reference to the image by querying the platform layer */
Juan Castillo3a66aca2015-04-13 17:36:19 +0100196 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
Juan Castillo6e762062015-11-02 10:47:01 +0000197 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100198 WARN("Failed to obtain reference to image id=%u (%i)\n",
199 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000200 return 0;
201 }
202
203 /* Attempt to access the image */
204 io_result = io_open(dev_handle, image_spec, &image_handle);
Juan Castillo6e762062015-11-02 10:47:01 +0000205 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100206 WARN("Failed to access image id=%u (%i)\n",
207 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000208 return 0;
209 }
210
211 /* Find the size of the image */
212 io_result = io_size(image_handle, &image_size);
Juan Castillo6e762062015-11-02 10:47:01 +0000213 if ((io_result != 0) || (image_size == 0)) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100214 WARN("Failed to determine the size of the image id=%u (%i)\n",
215 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000216 }
217 io_result = io_close(image_handle);
218 /* Ignore improbable/unrecoverable error in 'close' */
219
220 /* TODO: Consider maintaining open device connection from this
221 * bootloader stage
222 */
223 io_result = io_dev_close(dev_handle);
224 /* Ignore improbable/unrecoverable error in 'dev_close' */
225
226 return image_size;
227}
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100228
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100229#if LOAD_IMAGE_V2
230
231/*******************************************************************************
Soby Mathew7c8af062017-11-10 13:14:40 +0000232 * Internal function to load an image at a specific address given
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100233 * an image ID and extents of free memory.
234 *
235 * If the load is successful then the image information is updated.
236 *
237 * Returns 0 on success, a negative error code otherwise.
238 ******************************************************************************/
Soby Mathew7c8af062017-11-10 13:14:40 +0000239static int load_image(unsigned int image_id, image_info_t *image_data)
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100240{
241 uintptr_t dev_handle;
242 uintptr_t image_handle;
243 uintptr_t image_spec;
244 uintptr_t image_base;
245 size_t image_size;
246 size_t bytes_read;
247 int io_result;
248
249 assert(image_data != NULL);
250 assert(image_data->h.version >= VERSION_2);
251
252 image_base = image_data->image_base;
253
254 /* Obtain a reference to the image by querying the platform layer */
255 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
256 if (io_result != 0) {
257 WARN("Failed to obtain reference to image id=%u (%i)\n",
258 image_id, io_result);
259 return io_result;
260 }
261
262 /* Attempt to access the image */
263 io_result = io_open(dev_handle, image_spec, &image_handle);
264 if (io_result != 0) {
265 WARN("Failed to access image id=%u (%i)\n",
266 image_id, io_result);
267 return io_result;
268 }
269
270 INFO("Loading image id=%u at address %p\n", image_id,
271 (void *) image_base);
272
273 /* Find the size of the image */
274 io_result = io_size(image_handle, &image_size);
275 if ((io_result != 0) || (image_size == 0)) {
276 WARN("Failed to determine the size of the image id=%u (%i)\n",
277 image_id, io_result);
278 goto exit;
279 }
280
281 /* Check that the image size to load is within limit */
282 if (image_size > image_data->image_max_size) {
283 WARN("Image id=%u size out of bounds\n", image_id);
284 io_result = -EFBIG;
285 goto exit;
286 }
287
288 image_data->image_size = image_size;
289
290 /* We have enough space so load the image now */
291 /* TODO: Consider whether to try to recover/retry a partially successful read */
292 io_result = io_read(image_handle, image_base, image_size, &bytes_read);
293 if ((io_result != 0) || (bytes_read < image_size)) {
294 WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
295 goto exit;
296 }
297
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100298 INFO("Image id=%u loaded: %p - %p\n", image_id, (void *) image_base,
299 (void *) (image_base + image_size));
300
301exit:
302 io_close(image_handle);
303 /* Ignore improbable/unrecoverable error in 'close' */
304
305 /* TODO: Consider maintaining open device connection from this bootloader stage */
306 io_dev_close(dev_handle);
307 /* Ignore improbable/unrecoverable error in 'dev_close' */
308
309 return io_result;
310}
311
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000312static int load_auth_image_internal(unsigned int image_id,
313 image_info_t *image_data,
314 int is_parent_image)
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100315{
316 int rc;
317
318#if TRUSTED_BOARD_BOOT
Soby Mathew9fe88042018-03-26 12:43:37 +0100319 if (dyn_is_auth_disabled() == 0) {
320 unsigned int parent_id;
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100321
Soby Mathew9fe88042018-03-26 12:43:37 +0100322 /* Use recursion to authenticate parent images */
323 rc = auth_mod_get_parent_id(image_id, &parent_id);
324 if (rc == 0) {
325 rc = load_auth_image_internal(parent_id, image_data, 1);
326 if (rc != 0) {
327 return rc;
328 }
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100329 }
330 }
331#endif /* TRUSTED_BOARD_BOOT */
332
333 /* Load the image */
334 rc = load_image(image_id, image_data);
335 if (rc != 0) {
336 return rc;
337 }
338
339#if TRUSTED_BOARD_BOOT
Soby Mathew9fe88042018-03-26 12:43:37 +0100340 if (dyn_is_auth_disabled() == 0) {
341 /* Authenticate it */
342 rc = auth_mod_verify_img(image_id,
343 (void *)image_data->image_base,
344 image_data->image_size);
345 if (rc != 0) {
346 /* Authentication error, zero memory and flush it right away. */
347 zero_normalmem((void *)image_data->image_base,
348 image_data->image_size);
349 flush_dcache_range(image_data->image_base,
350 image_data->image_size);
351 return -EAUTH;
352 }
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100353 }
Soby Mathew7c8af062017-11-10 13:14:40 +0000354#endif /* TRUSTED_BOARD_BOOT */
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100355
356 /*
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100357 * Flush the image to main memory so that it can be executed later by
Soby Mathew7c8af062017-11-10 13:14:40 +0000358 * any CPU, regardless of cache and MMU state. If TBB is enabled, then
359 * the file has been successfully loaded and authenticated and flush
360 * only for child images, not for the parents (certificates).
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100361 */
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000362 if (!is_parent_image) {
363 flush_dcache_range(image_data->image_base,
364 image_data->image_size);
365 }
Soby Mathew7c8af062017-11-10 13:14:40 +0000366
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100367
368 return 0;
369}
370
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000371/*******************************************************************************
372 * Generic function to load and authenticate an image. The image is actually
373 * loaded by calling the 'load_image()' function. Therefore, it returns the
374 * same error codes if the loading operation failed, or -EAUTH if the
375 * authentication failed. In addition, this function uses recursion to
376 * authenticate the parent images up to the root of trust.
377 ******************************************************************************/
378int load_auth_image(unsigned int image_id, image_info_t *image_data)
379{
Roberto Vargasbc1ae1f2017-09-26 12:53:01 +0100380 int err;
381
382 do {
383 err = load_auth_image_internal(image_id, image_data, 0);
384 } while (err != 0 && plat_try_next_boot_source());
385
386 return err;
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000387}
388
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100389#else /* LOAD_IMAGE_V2 */
390
Achin Gupta4f6ad662013-10-25 09:08:21 +0100391/*******************************************************************************
Sandrine Bailleux8eaf46e2016-05-27 14:08:10 +0100392 * Generic function to load an image at a specific address given an image ID and
393 * extents of free memory.
394 *
395 * If the load is successful then the image information is updated.
396 *
397 * If the entry_point_info argument is not NULL then this function also updates:
398 * - the memory layout to mark the memory as reserved;
399 * - the entry point information.
400 *
401 * The caller might pass a NULL pointer for the entry point if they are not
402 * interested in this information. This is typically the case for non-executable
403 * images (e.g. certificates) and executable images that won't ever be executed
404 * on the application processor (e.g. additional microcontroller firmware).
405 *
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100406 * Returns 0 on success, a negative error code otherwise.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100407 ******************************************************************************/
Vikram Kanigirida567432014-04-15 18:08:08 +0100408int load_image(meminfo_t *mem_layout,
Juan Castillo3a66aca2015-04-13 17:36:19 +0100409 unsigned int image_id,
Juan Castilloa08a5e72015-05-19 11:54:12 +0100410 uintptr_t image_base,
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100411 image_info_t *image_data,
412 entry_point_info_t *entry_point_info)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100413{
Dan Handleya4cb68e2014-04-23 13:47:06 +0100414 uintptr_t dev_handle;
415 uintptr_t image_handle;
416 uintptr_t image_spec;
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100417 size_t image_size;
418 size_t bytes_read;
Juan Castilloec813f52015-10-01 18:37:40 +0100419 int io_result;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100420
James Morrissey9d72b4e2014-02-10 17:04:32 +0000421 assert(mem_layout != NULL);
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100422 assert(image_data != NULL);
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100423 assert(image_data->h.version == VERSION_1);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000424
425 /* Obtain a reference to the image by querying the platform layer */
Juan Castillo3a66aca2015-04-13 17:36:19 +0100426 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
Juan Castilloec813f52015-10-01 18:37:40 +0100427 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100428 WARN("Failed to obtain reference to image id=%u (%i)\n",
429 image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100430 return io_result;
James Morrissey9d72b4e2014-02-10 17:04:32 +0000431 }
432
433 /* Attempt to access the image */
434 io_result = io_open(dev_handle, image_spec, &image_handle);
Juan Castilloec813f52015-10-01 18:37:40 +0100435 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100436 WARN("Failed to access image id=%u (%i)\n",
437 image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100438 return io_result;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100439 }
440
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000441 INFO("Loading image id=%u at address %p\n", image_id,
442 (void *) image_base);
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100443
James Morrissey9d72b4e2014-02-10 17:04:32 +0000444 /* Find the size of the image */
445 io_result = io_size(image_handle, &image_size);
Juan Castilloec813f52015-10-01 18:37:40 +0100446 if ((io_result != 0) || (image_size == 0)) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100447 WARN("Failed to determine the size of the image id=%u (%i)\n",
448 image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100449 goto exit;
James Morrissey9d72b4e2014-02-10 17:04:32 +0000450 }
451
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100452 /* Check that the memory where the image will be loaded is free */
453 if (!is_mem_free(mem_layout->free_base, mem_layout->free_size,
454 image_base, image_size)) {
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100455 WARN("Failed to reserve region [base = %p, size = 0x%zx]\n",
456 (void *) image_base, image_size);
Vikram Kanigirida567432014-04-15 18:08:08 +0100457 dump_load_info(image_base, image_size, mem_layout);
458 io_result = -ENOMEM;
459 goto exit;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100460 }
461
462 /* We have enough space so load the image now */
James Morrissey9d72b4e2014-02-10 17:04:32 +0000463 /* TODO: Consider whether to try to recover/retry a partially successful read */
Dan Handleya4cb68e2014-04-23 13:47:06 +0100464 io_result = io_read(image_handle, image_base, image_size, &bytes_read);
Juan Castilloec813f52015-10-01 18:37:40 +0100465 if ((io_result != 0) || (bytes_read < image_size)) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100466 WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100467 goto exit;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100468 }
469
Sandrine Bailleux8eaf46e2016-05-27 14:08:10 +0100470 image_data->image_base = image_base;
471 image_data->image_size = image_size;
472
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100473 /*
474 * Update the memory usage info.
475 * This is done after the actual loading so that it is not updated when
476 * the load is unsuccessful.
Juan Castillo09a55a82015-01-19 16:51:21 +0000477 * If the caller does not provide an entry point, bypass the memory
478 * reservation.
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100479 */
Juan Castillo09a55a82015-01-19 16:51:21 +0000480 if (entry_point_info != NULL) {
481 reserve_mem(&mem_layout->free_base, &mem_layout->free_size,
482 image_base, image_size);
Sandrine Bailleux8eaf46e2016-05-27 14:08:10 +0100483 entry_point_info->pc = image_base;
Juan Castillo09a55a82015-01-19 16:51:21 +0000484 } else {
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100485 INFO("Skip reserving region [base = %p, size = 0x%zx]\n",
486 (void *) image_base, image_size);
Juan Castillo09a55a82015-01-19 16:51:21 +0000487 }
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100488
Dan Handley9c96ed52016-07-28 14:38:03 +0100489#if !TRUSTED_BOARD_BOOT
Achin Gupta4f6ad662013-10-25 09:08:21 +0100490 /*
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100491 * File has been successfully loaded.
Dan Handley9c96ed52016-07-28 14:38:03 +0100492 * Flush the image to main memory so that it can be executed later by
493 * any CPU, regardless of cache and MMU state.
494 * When TBB is enabled the image is flushed later, after image
495 * authentication.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100496 */
James Morrissey9d72b4e2014-02-10 17:04:32 +0000497 flush_dcache_range(image_base, image_size);
Dan Handley9c96ed52016-07-28 14:38:03 +0100498#endif /* TRUSTED_BOARD_BOOT */
Achin Gupta4f6ad662013-10-25 09:08:21 +0100499
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100500 INFO("Image id=%u loaded at address %p, size = 0x%zx\n", image_id,
501 (void *) image_base, image_size);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000502
503exit:
Vikram Kanigirida567432014-04-15 18:08:08 +0100504 io_close(image_handle);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000505 /* Ignore improbable/unrecoverable error in 'close' */
506
507 /* TODO: Consider maintaining open device connection from this bootloader stage */
Vikram Kanigirida567432014-04-15 18:08:08 +0100508 io_dev_close(dev_handle);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000509 /* Ignore improbable/unrecoverable error in 'dev_close' */
Achin Gupta4f6ad662013-10-25 09:08:21 +0100510
Vikram Kanigirida567432014-04-15 18:08:08 +0100511 return io_result;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100512}
Juan Castilloa08a5e72015-05-19 11:54:12 +0100513
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000514static int load_auth_image_internal(meminfo_t *mem_layout,
515 unsigned int image_id,
516 uintptr_t image_base,
517 image_info_t *image_data,
518 entry_point_info_t *entry_point_info,
519 int is_parent_image)
Juan Castilloa08a5e72015-05-19 11:54:12 +0100520{
521 int rc;
522
523#if TRUSTED_BOARD_BOOT
524 unsigned int parent_id;
525
526 /* Use recursion to authenticate parent images */
527 rc = auth_mod_get_parent_id(image_id, &parent_id);
528 if (rc == 0) {
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000529 rc = load_auth_image_internal(mem_layout, parent_id, image_base,
530 image_data, NULL, 1);
Juan Castilloec813f52015-10-01 18:37:40 +0100531 if (rc != 0) {
Juan Castilloa08a5e72015-05-19 11:54:12 +0100532 return rc;
533 }
534 }
535#endif /* TRUSTED_BOARD_BOOT */
536
537 /* Load the image */
538 rc = load_image(mem_layout, image_id, image_base, image_data,
539 entry_point_info);
Juan Castilloec813f52015-10-01 18:37:40 +0100540 if (rc != 0) {
541 return rc;
Juan Castilloa08a5e72015-05-19 11:54:12 +0100542 }
543
544#if TRUSTED_BOARD_BOOT
545 /* Authenticate it */
546 rc = auth_mod_verify_img(image_id,
547 (void *)image_data->image_base,
548 image_data->image_size);
549 if (rc != 0) {
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000550 /* Authentication error, zero memory and flush it right away. */
Douglas Raillard21362a92016-12-02 13:51:54 +0000551 zero_normalmem((void *)image_data->image_base,
Juan Castillo97dbcf12015-08-17 10:43:27 +0100552 image_data->image_size);
553 flush_dcache_range(image_data->image_base,
554 image_data->image_size);
Juan Castilloec813f52015-10-01 18:37:40 +0100555 return -EAUTH;
Juan Castilloa08a5e72015-05-19 11:54:12 +0100556 }
Dan Handley9c96ed52016-07-28 14:38:03 +0100557 /*
558 * File has been successfully loaded and authenticated.
559 * Flush the image to main memory so that it can be executed later by
560 * any CPU, regardless of cache and MMU state.
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000561 * Do it only for child images, not for the parents (certificates).
Dan Handley9c96ed52016-07-28 14:38:03 +0100562 */
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000563 if (!is_parent_image) {
564 flush_dcache_range(image_data->image_base,
565 image_data->image_size);
566 }
Juan Castilloa08a5e72015-05-19 11:54:12 +0100567#endif /* TRUSTED_BOARD_BOOT */
568
Juan Castilloec813f52015-10-01 18:37:40 +0100569 return 0;
Juan Castilloa08a5e72015-05-19 11:54:12 +0100570}
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100571
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000572/*******************************************************************************
573 * Generic function to load and authenticate an image. The image is actually
574 * loaded by calling the 'load_image()' function. Therefore, it returns the
575 * same error codes if the loading operation failed, or -EAUTH if the
576 * authentication failed. In addition, this function uses recursion to
577 * authenticate the parent images up to the root of trust.
578 ******************************************************************************/
579int load_auth_image(meminfo_t *mem_layout,
580 unsigned int image_id,
581 uintptr_t image_base,
582 image_info_t *image_data,
583 entry_point_info_t *entry_point_info)
584{
Roberto Vargasbc1ae1f2017-09-26 12:53:01 +0100585 int err;
586
587 do {
588 err = load_auth_image_internal(mem_layout, image_id, image_base,
589 image_data, entry_point_info, 0);
590 } while (err != 0 && plat_try_next_boot_source());
591
592 return err;
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000593}
594
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100595#endif /* LOAD_IMAGE_V2 */
596
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100597/*******************************************************************************
598 * Print the content of an entry_point_info_t structure.
599 ******************************************************************************/
600void print_entry_point_info(const entry_point_info_t *ep_info)
601{
Soby Mathewa0fedc42016-06-16 14:52:04 +0100602 INFO("Entry point address = %p\n", (void *)ep_info->pc);
603 INFO("SPSR = 0x%x\n", ep_info->spsr);
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100604
605#define PRINT_IMAGE_ARG(n) \
606 VERBOSE("Argument #" #n " = 0x%llx\n", \
607 (unsigned long long) ep_info->args.arg##n)
608
609 PRINT_IMAGE_ARG(0);
610 PRINT_IMAGE_ARG(1);
611 PRINT_IMAGE_ARG(2);
612 PRINT_IMAGE_ARG(3);
Soby Mathewcdf58cb2016-08-30 13:07:31 +0100613#ifndef AARCH32
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100614 PRINT_IMAGE_ARG(4);
615 PRINT_IMAGE_ARG(5);
616 PRINT_IMAGE_ARG(6);
617 PRINT_IMAGE_ARG(7);
Soby Mathewcdf58cb2016-08-30 13:07:31 +0100618#endif
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100619#undef PRINT_IMAGE_ARG
620}