blob: be56256bd2f3f70b4ab9fc7b704c2a75bea7edbc [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
Soby Mathewa0fedc42016-06-16 14:52:04 +010056static inline unsigned int is_page_aligned (uintptr_t addr) {
57 return (addr & (PAGE_SIZE - 1)) == 0;
Achin Gupta4f6ad662013-10-25 09:08:21 +010058}
59
Sandrine Bailleux467d0572014-06-24 14:02:34 +010060/******************************************************************************
61 * Determine whether the memory region delimited by 'addr' and 'size' is free,
62 * given the extents of free memory.
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +010063 * Return 1 if it is free, 0 if it is not free or if the input values are
64 * invalid.
Sandrine Bailleux467d0572014-06-24 14:02:34 +010065 *****************************************************************************/
Soby Mathewa0fedc42016-06-16 14:52:04 +010066static int is_mem_free(uintptr_t free_base, size_t free_size,
67 uintptr_t addr, size_t size)
Sandrine Bailleux467d0572014-06-24 14:02:34 +010068{
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +010069 uintptr_t free_end, requested_end;
70
71 /*
72 * Handle corner cases first.
73 *
74 * The order of the 2 tests is important, because if there's no space
75 * left (i.e. free_size == 0) but we don't ask for any memory
76 * (i.e. size == 0) then we should report that the memory is free.
77 */
78 if (size == 0)
79 return 1; /* A zero-byte region is always free */
80 if (free_size == 0)
81 return 0;
82
83 /*
84 * Check that the end addresses don't overflow.
85 * If they do, consider that this memory region is not free, as this
86 * is an invalid scenario.
87 */
88 if (check_uptr_overflow(free_base, free_size - 1))
89 return 0;
90 free_end = free_base + (free_size - 1);
91
92 if (check_uptr_overflow(addr, size - 1))
93 return 0;
94 requested_end = addr + (size - 1);
95
96 /*
97 * Finally, check that the requested memory region lies within the free
98 * region.
99 */
100 return (addr >= free_base) && (requested_end <= free_end);
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100101}
Achin Gupta4f6ad662013-10-25 09:08:21 +0100102
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100103/******************************************************************************
104 * Inside a given memory region, determine whether a sub-region of memory is
105 * closer from the top or the bottom of the encompassing region. Return the
106 * size of the smallest chunk of free memory surrounding the sub-region in
107 * 'small_chunk_size'.
108 *****************************************************************************/
Soby Mathewa0fedc42016-06-16 14:52:04 +0100109static unsigned int choose_mem_pos(uintptr_t mem_start, uintptr_t mem_end,
110 uintptr_t submem_start, uintptr_t submem_end,
111 size_t *small_chunk_size)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100112{
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100113 size_t top_chunk_size, bottom_chunk_size;
114
115 assert(mem_start <= submem_start);
116 assert(submem_start <= submem_end);
117 assert(submem_end <= mem_end);
118 assert(small_chunk_size != NULL);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100119
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100120 top_chunk_size = mem_end - submem_end;
121 bottom_chunk_size = submem_start - mem_start;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100122
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100123 if (top_chunk_size < bottom_chunk_size) {
124 *small_chunk_size = top_chunk_size;
125 return TOP;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100126 } else {
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100127 *small_chunk_size = bottom_chunk_size;
128 return BOTTOM;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100129 }
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100130}
131
132/******************************************************************************
133 * Reserve the memory region delimited by 'addr' and 'size'. The extents of free
134 * memory are passed in 'free_base' and 'free_size' and they will be updated to
135 * reflect the memory usage.
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100136 * The caller must ensure the memory to reserve is free and that the addresses
137 * and sizes passed in arguments are sane.
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100138 *****************************************************************************/
Soby Mathewa0fedc42016-06-16 14:52:04 +0100139void reserve_mem(uintptr_t *free_base, size_t *free_size,
140 uintptr_t addr, size_t size)
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100141{
142 size_t discard_size;
143 size_t reserved_size;
144 unsigned int pos;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100145
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100146 assert(free_base != NULL);
147 assert(free_size != NULL);
148 assert(is_mem_free(*free_base, *free_size, addr, size));
Achin Gupta4f6ad662013-10-25 09:08:21 +0100149
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100150 if (size == 0) {
151 WARN("Nothing to allocate, requested size is zero\n");
152 return;
153 }
154
155 pos = choose_mem_pos(*free_base, *free_base + (*free_size - 1),
156 addr, addr + (size - 1),
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100157 &discard_size);
158
159 reserved_size = size + discard_size;
160 *free_size -= reserved_size;
161
162 if (pos == BOTTOM)
163 *free_base = addr + size;
164
Soby Mathewa0fedc42016-06-16 14:52:04 +0100165 VERBOSE("Reserved 0x%zx bytes (discarded 0x%zx bytes %s)\n",
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100166 reserved_size, discard_size,
167 pos == TOP ? "above" : "below");
Achin Gupta4f6ad662013-10-25 09:08:21 +0100168}
169
Soby Mathewa0fedc42016-06-16 14:52:04 +0100170static void dump_load_info(uintptr_t image_load_addr,
171 size_t image_size,
Dan Handleye2712bc2014-04-10 15:37:22 +0100172 const meminfo_t *mem_layout)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100173{
Soby Mathewa0fedc42016-06-16 14:52:04 +0100174 INFO("Trying to load image at address %p, size = 0x%zx\n",
175 (void *)image_load_addr, image_size);
Dan Handley91b624e2014-07-29 17:14:00 +0100176 INFO("Current memory layout:\n");
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100177 INFO(" total region = [base = %p, size = 0x%zx]\n",
178 (void *) mem_layout->total_base, mem_layout->total_size);
179 INFO(" free region = [base = %p, size = 0x%zx]\n",
180 (void *) mem_layout->free_base, mem_layout->free_size);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100181}
182
Ryan Harkin87274c42014-02-04 11:43:57 +0000183/* Generic function to return the size of an image */
Soby Mathewa0fedc42016-06-16 14:52:04 +0100184size_t image_size(unsigned int image_id)
Ryan Harkin87274c42014-02-04 11:43:57 +0000185{
Dan Handleya4cb68e2014-04-23 13:47:06 +0100186 uintptr_t dev_handle;
187 uintptr_t image_handle;
188 uintptr_t image_spec;
Ryan Harkin87274c42014-02-04 11:43:57 +0000189 size_t image_size = 0;
Juan Castillo6e762062015-11-02 10:47:01 +0000190 int io_result;
Ryan Harkin87274c42014-02-04 11:43:57 +0000191
Ryan Harkin87274c42014-02-04 11:43:57 +0000192 /* Obtain a reference to the image by querying the platform layer */
Juan Castillo3a66aca2015-04-13 17:36:19 +0100193 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
Juan Castillo6e762062015-11-02 10:47:01 +0000194 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100195 WARN("Failed to obtain reference to image id=%u (%i)\n",
196 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000197 return 0;
198 }
199
200 /* Attempt to access the image */
201 io_result = io_open(dev_handle, image_spec, &image_handle);
Juan Castillo6e762062015-11-02 10:47:01 +0000202 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100203 WARN("Failed to access image id=%u (%i)\n",
204 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000205 return 0;
206 }
207
208 /* Find the size of the image */
209 io_result = io_size(image_handle, &image_size);
Juan Castillo6e762062015-11-02 10:47:01 +0000210 if ((io_result != 0) || (image_size == 0)) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100211 WARN("Failed to determine the size of the image id=%u (%i)\n",
212 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000213 }
214 io_result = io_close(image_handle);
215 /* Ignore improbable/unrecoverable error in 'close' */
216
217 /* TODO: Consider maintaining open device connection from this
218 * bootloader stage
219 */
220 io_result = io_dev_close(dev_handle);
221 /* Ignore improbable/unrecoverable error in 'dev_close' */
222
223 return image_size;
224}
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100225
Achin Gupta4f6ad662013-10-25 09:08:21 +0100226/*******************************************************************************
Sandrine Bailleux8eaf46e2016-05-27 14:08:10 +0100227 * Generic function to load an image at a specific address given an image ID and
228 * extents of free memory.
229 *
230 * If the load is successful then the image information is updated.
231 *
232 * If the entry_point_info argument is not NULL then this function also updates:
233 * - the memory layout to mark the memory as reserved;
234 * - the entry point information.
235 *
236 * The caller might pass a NULL pointer for the entry point if they are not
237 * interested in this information. This is typically the case for non-executable
238 * images (e.g. certificates) and executable images that won't ever be executed
239 * on the application processor (e.g. additional microcontroller firmware).
240 *
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100241 * Returns 0 on success, a negative error code otherwise.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100242 ******************************************************************************/
Vikram Kanigirida567432014-04-15 18:08:08 +0100243int load_image(meminfo_t *mem_layout,
Juan Castillo3a66aca2015-04-13 17:36:19 +0100244 unsigned int image_id,
Juan Castilloa08a5e72015-05-19 11:54:12 +0100245 uintptr_t image_base,
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100246 image_info_t *image_data,
247 entry_point_info_t *entry_point_info)
Achin Gupta4f6ad662013-10-25 09:08:21 +0100248{
Dan Handleya4cb68e2014-04-23 13:47:06 +0100249 uintptr_t dev_handle;
250 uintptr_t image_handle;
251 uintptr_t image_spec;
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100252 size_t image_size;
253 size_t bytes_read;
Juan Castilloec813f52015-10-01 18:37:40 +0100254 int io_result;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100255
James Morrissey9d72b4e2014-02-10 17:04:32 +0000256 assert(mem_layout != NULL);
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100257 assert(image_data != NULL);
Vikram Kanigirida567432014-04-15 18:08:08 +0100258 assert(image_data->h.version >= VERSION_1);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000259
260 /* Obtain a reference to the image by querying the platform layer */
Juan Castillo3a66aca2015-04-13 17:36:19 +0100261 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
Juan Castilloec813f52015-10-01 18:37:40 +0100262 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100263 WARN("Failed to obtain reference to image id=%u (%i)\n",
264 image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100265 return io_result;
James Morrissey9d72b4e2014-02-10 17:04:32 +0000266 }
267
268 /* Attempt to access the image */
269 io_result = io_open(dev_handle, image_spec, &image_handle);
Juan Castilloec813f52015-10-01 18:37:40 +0100270 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100271 WARN("Failed to access image id=%u (%i)\n",
272 image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100273 return io_result;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100274 }
275
Antonio Nino Diazb3a0a7b2016-02-02 12:03:38 +0000276 INFO("Loading image id=%u at address %p\n", image_id,
277 (void *) image_base);
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100278
James Morrissey9d72b4e2014-02-10 17:04:32 +0000279 /* Find the size of the image */
280 io_result = io_size(image_handle, &image_size);
Juan Castilloec813f52015-10-01 18:37:40 +0100281 if ((io_result != 0) || (image_size == 0)) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100282 WARN("Failed to determine the size of the image id=%u (%i)\n",
283 image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100284 goto exit;
James Morrissey9d72b4e2014-02-10 17:04:32 +0000285 }
286
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100287 /* Check that the memory where the image will be loaded is free */
288 if (!is_mem_free(mem_layout->free_base, mem_layout->free_size,
289 image_base, image_size)) {
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100290 WARN("Failed to reserve region [base = %p, size = 0x%zx]\n",
291 (void *) image_base, image_size);
Vikram Kanigirida567432014-04-15 18:08:08 +0100292 dump_load_info(image_base, image_size, mem_layout);
293 io_result = -ENOMEM;
294 goto exit;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100295 }
296
297 /* We have enough space so load the image now */
James Morrissey9d72b4e2014-02-10 17:04:32 +0000298 /* TODO: Consider whether to try to recover/retry a partially successful read */
Dan Handleya4cb68e2014-04-23 13:47:06 +0100299 io_result = io_read(image_handle, image_base, image_size, &bytes_read);
Juan Castilloec813f52015-10-01 18:37:40 +0100300 if ((io_result != 0) || (bytes_read < image_size)) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100301 WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
Vikram Kanigirida567432014-04-15 18:08:08 +0100302 goto exit;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100303 }
304
Sandrine Bailleux8eaf46e2016-05-27 14:08:10 +0100305 image_data->image_base = image_base;
306 image_data->image_size = image_size;
307
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100308 /*
309 * Update the memory usage info.
310 * This is done after the actual loading so that it is not updated when
311 * the load is unsuccessful.
Juan Castillo09a55a82015-01-19 16:51:21 +0000312 * If the caller does not provide an entry point, bypass the memory
313 * reservation.
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100314 */
Juan Castillo09a55a82015-01-19 16:51:21 +0000315 if (entry_point_info != NULL) {
316 reserve_mem(&mem_layout->free_base, &mem_layout->free_size,
317 image_base, image_size);
Sandrine Bailleux8eaf46e2016-05-27 14:08:10 +0100318 entry_point_info->pc = image_base;
Juan Castillo09a55a82015-01-19 16:51:21 +0000319 } else {
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100320 INFO("Skip reserving region [base = %p, size = 0x%zx]\n",
321 (void *) image_base, image_size);
Juan Castillo09a55a82015-01-19 16:51:21 +0000322 }
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100323
Achin Gupta4f6ad662013-10-25 09:08:21 +0100324 /*
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100325 * File has been successfully loaded.
Sandrine Bailleux8eaf46e2016-05-27 14:08:10 +0100326 * Flush the image in Trusted SRAM so that the next exception level can
327 * see it.
Achin Gupta4f6ad662013-10-25 09:08:21 +0100328 */
James Morrissey9d72b4e2014-02-10 17:04:32 +0000329 flush_dcache_range(image_base, image_size);
Achin Gupta4f6ad662013-10-25 09:08:21 +0100330
Sandrine Bailleux4ec7e2d2016-07-12 09:12:24 +0100331 INFO("Image id=%u loaded at address %p, size = 0x%zx\n", image_id,
332 (void *) image_base, image_size);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000333
334exit:
Vikram Kanigirida567432014-04-15 18:08:08 +0100335 io_close(image_handle);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000336 /* Ignore improbable/unrecoverable error in 'close' */
337
338 /* TODO: Consider maintaining open device connection from this bootloader stage */
Vikram Kanigirida567432014-04-15 18:08:08 +0100339 io_dev_close(dev_handle);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000340 /* Ignore improbable/unrecoverable error in 'dev_close' */
Achin Gupta4f6ad662013-10-25 09:08:21 +0100341
Vikram Kanigirida567432014-04-15 18:08:08 +0100342 return io_result;
Achin Gupta4f6ad662013-10-25 09:08:21 +0100343}
Juan Castilloa08a5e72015-05-19 11:54:12 +0100344
345/*******************************************************************************
346 * Generic function to load and authenticate an image. The image is actually
347 * loaded by calling the 'load_image()' function. In addition, this function
348 * uses recursion to authenticate the parent images up to the root of trust.
349 ******************************************************************************/
350int load_auth_image(meminfo_t *mem_layout,
351 unsigned int image_id,
352 uintptr_t image_base,
353 image_info_t *image_data,
354 entry_point_info_t *entry_point_info)
355{
356 int rc;
357
358#if TRUSTED_BOARD_BOOT
359 unsigned int parent_id;
360
361 /* Use recursion to authenticate parent images */
362 rc = auth_mod_get_parent_id(image_id, &parent_id);
363 if (rc == 0) {
364 rc = load_auth_image(mem_layout, parent_id, image_base,
365 image_data, NULL);
Juan Castilloec813f52015-10-01 18:37:40 +0100366 if (rc != 0) {
Juan Castilloa08a5e72015-05-19 11:54:12 +0100367 return rc;
368 }
369 }
370#endif /* TRUSTED_BOARD_BOOT */
371
372 /* Load the image */
373 rc = load_image(mem_layout, image_id, image_base, image_data,
374 entry_point_info);
Juan Castilloec813f52015-10-01 18:37:40 +0100375 if (rc != 0) {
376 return rc;
Juan Castilloa08a5e72015-05-19 11:54:12 +0100377 }
378
379#if TRUSTED_BOARD_BOOT
380 /* Authenticate it */
381 rc = auth_mod_verify_img(image_id,
382 (void *)image_data->image_base,
383 image_data->image_size);
384 if (rc != 0) {
Juan Castillo97dbcf12015-08-17 10:43:27 +0100385 memset((void *)image_data->image_base, 0x00,
386 image_data->image_size);
387 flush_dcache_range(image_data->image_base,
388 image_data->image_size);
Juan Castilloec813f52015-10-01 18:37:40 +0100389 return -EAUTH;
Juan Castilloa08a5e72015-05-19 11:54:12 +0100390 }
391
392 /* After working with data, invalidate the data cache */
393 inv_dcache_range(image_data->image_base,
394 (size_t)image_data->image_size);
395#endif /* TRUSTED_BOARD_BOOT */
396
Juan Castilloec813f52015-10-01 18:37:40 +0100397 return 0;
Juan Castilloa08a5e72015-05-19 11:54:12 +0100398}
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100399
400/*******************************************************************************
401 * Print the content of an entry_point_info_t structure.
402 ******************************************************************************/
403void print_entry_point_info(const entry_point_info_t *ep_info)
404{
Soby Mathewa0fedc42016-06-16 14:52:04 +0100405 INFO("Entry point address = %p\n", (void *)ep_info->pc);
406 INFO("SPSR = 0x%x\n", ep_info->spsr);
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100407
408#define PRINT_IMAGE_ARG(n) \
409 VERBOSE("Argument #" #n " = 0x%llx\n", \
410 (unsigned long long) ep_info->args.arg##n)
411
412 PRINT_IMAGE_ARG(0);
413 PRINT_IMAGE_ARG(1);
414 PRINT_IMAGE_ARG(2);
415 PRINT_IMAGE_ARG(3);
416 PRINT_IMAGE_ARG(4);
417 PRINT_IMAGE_ARG(5);
418 PRINT_IMAGE_ARG(6);
419 PRINT_IMAGE_ARG(7);
420#undef PRINT_IMAGE_ARG
421}