blob: b2d22c19ddccfded8608ce6c84532a5dddeea2c1 [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 <assert.h>
Sandrine Bailleux467d0572014-06-24 14:02:34 +01008#include <errno.h>
Juan Castillo97dbcf12015-08-17 10:43:27 +01009#include <string.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010
11#include <arch.h>
12#include <arch_helpers.h>
13#include <common/bl_common.h>
14#include <common/debug.h>
15#include <drivers/auth/auth_mod.h>
16#include <drivers/io/io_storage.h>
17#include <lib/utils.h>
18#include <lib/xlat_tables/xlat_tables_defs.h>
19#include <plat/common/platform.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010020
Soby Mathew9fe88042018-03-26 12:43:37 +010021#if TRUSTED_BOARD_BOOT
22# ifdef DYN_DISABLE_AUTH
23static int disable_auth;
24
25/******************************************************************************
26 * API to dynamically disable authentication. Only meant for development
Roberto Vargas025946a2018-09-24 17:20:48 +010027 * systems. This is only invoked if DYN_DISABLE_AUTH is defined.
Soby Mathew9fe88042018-03-26 12:43:37 +010028 *****************************************************************************/
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 */
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +010052 if ((value & (PAGE_SIZE - 1U)) != 0U) {
53 value &= ~(PAGE_SIZE - 1U);
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
Ryan Harkin87274c42014-02-04 11:43:57 +0000104/* Generic function to return the size of an image */
Daniel Boulby4f3b6ed2018-05-04 11:18:26 +0100105size_t get_image_size(unsigned int image_id)
Ryan Harkin87274c42014-02-04 11:43:57 +0000106{
Dan Handleya4cb68e2014-04-23 13:47:06 +0100107 uintptr_t dev_handle;
108 uintptr_t image_handle;
109 uintptr_t image_spec;
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100110 size_t image_size = 0U;
Juan Castillo6e762062015-11-02 10:47:01 +0000111 int io_result;
Ryan Harkin87274c42014-02-04 11:43:57 +0000112
Ryan Harkin87274c42014-02-04 11:43:57 +0000113 /* Obtain a reference to the image by querying the platform layer */
Juan Castillo3a66aca2015-04-13 17:36:19 +0100114 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
Juan Castillo6e762062015-11-02 10:47:01 +0000115 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100116 WARN("Failed to obtain reference to image id=%u (%i)\n",
117 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000118 return 0;
119 }
120
121 /* Attempt to access the image */
122 io_result = io_open(dev_handle, image_spec, &image_handle);
Juan Castillo6e762062015-11-02 10:47:01 +0000123 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100124 WARN("Failed to access image id=%u (%i)\n",
125 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000126 return 0;
127 }
128
129 /* Find the size of the image */
130 io_result = io_size(image_handle, &image_size);
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100131 if ((io_result != 0) || (image_size == 0U)) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100132 WARN("Failed to determine the size of the image id=%u (%i)\n",
133 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000134 }
135 io_result = io_close(image_handle);
136 /* Ignore improbable/unrecoverable error in 'close' */
137
138 /* TODO: Consider maintaining open device connection from this
139 * bootloader stage
140 */
141 io_result = io_dev_close(dev_handle);
142 /* Ignore improbable/unrecoverable error in 'dev_close' */
143
144 return image_size;
145}
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100146
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100147/*******************************************************************************
Soby Mathew7c8af062017-11-10 13:14:40 +0000148 * Internal function to load an image at a specific address given
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100149 * an image ID and extents of free memory.
150 *
151 * If the load is successful then the image information is updated.
152 *
153 * Returns 0 on success, a negative error code otherwise.
154 ******************************************************************************/
Soby Mathew7c8af062017-11-10 13:14:40 +0000155static int load_image(unsigned int image_id, image_info_t *image_data)
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100156{
157 uintptr_t dev_handle;
158 uintptr_t image_handle;
159 uintptr_t image_spec;
160 uintptr_t image_base;
161 size_t image_size;
162 size_t bytes_read;
163 int io_result;
164
165 assert(image_data != NULL);
166 assert(image_data->h.version >= VERSION_2);
167
168 image_base = image_data->image_base;
169
170 /* Obtain a reference to the image by querying the platform layer */
171 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
172 if (io_result != 0) {
173 WARN("Failed to obtain reference to image id=%u (%i)\n",
174 image_id, io_result);
175 return io_result;
176 }
177
178 /* Attempt to access the image */
179 io_result = io_open(dev_handle, image_spec, &image_handle);
180 if (io_result != 0) {
181 WARN("Failed to access image id=%u (%i)\n",
182 image_id, io_result);
183 return io_result;
184 }
185
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100186 INFO("Loading image id=%u at address 0x%lx\n", image_id, image_base);
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100187
188 /* Find the size of the image */
189 io_result = io_size(image_handle, &image_size);
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100190 if ((io_result != 0) || (image_size == 0U)) {
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100191 WARN("Failed to determine the size of the image id=%u (%i)\n",
192 image_id, io_result);
193 goto exit;
194 }
195
196 /* Check that the image size to load is within limit */
197 if (image_size > image_data->image_max_size) {
198 WARN("Image id=%u size out of bounds\n", image_id);
199 io_result = -EFBIG;
200 goto exit;
201 }
202
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100203 /*
204 * image_data->image_max_size is a uint32_t so image_size will always
205 * fit in image_data->image_size.
206 */
207 image_data->image_size = (uint32_t)image_size;
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100208
209 /* We have enough space so load the image now */
210 /* TODO: Consider whether to try to recover/retry a partially successful read */
211 io_result = io_read(image_handle, image_base, image_size, &bytes_read);
212 if ((io_result != 0) || (bytes_read < image_size)) {
213 WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
214 goto exit;
215 }
216
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100217 INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base,
218 (uintptr_t)(image_base + image_size));
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100219
220exit:
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100221 (void)io_close(image_handle);
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100222 /* Ignore improbable/unrecoverable error in 'close' */
223
224 /* TODO: Consider maintaining open device connection from this bootloader stage */
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100225 (void)io_dev_close(dev_handle);
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100226 /* Ignore improbable/unrecoverable error in 'dev_close' */
227
228 return io_result;
229}
230
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000231static int load_auth_image_internal(unsigned int image_id,
232 image_info_t *image_data,
233 int is_parent_image)
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100234{
235 int rc;
236
237#if TRUSTED_BOARD_BOOT
Soby Mathew9fe88042018-03-26 12:43:37 +0100238 if (dyn_is_auth_disabled() == 0) {
239 unsigned int parent_id;
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100240
Soby Mathew9fe88042018-03-26 12:43:37 +0100241 /* Use recursion to authenticate parent images */
242 rc = auth_mod_get_parent_id(image_id, &parent_id);
243 if (rc == 0) {
244 rc = load_auth_image_internal(parent_id, image_data, 1);
245 if (rc != 0) {
246 return rc;
247 }
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100248 }
249 }
250#endif /* TRUSTED_BOARD_BOOT */
251
252 /* Load the image */
253 rc = load_image(image_id, image_data);
254 if (rc != 0) {
255 return rc;
256 }
257
258#if TRUSTED_BOARD_BOOT
Soby Mathew9fe88042018-03-26 12:43:37 +0100259 if (dyn_is_auth_disabled() == 0) {
260 /* Authenticate it */
261 rc = auth_mod_verify_img(image_id,
262 (void *)image_data->image_base,
263 image_data->image_size);
264 if (rc != 0) {
265 /* Authentication error, zero memory and flush it right away. */
266 zero_normalmem((void *)image_data->image_base,
267 image_data->image_size);
268 flush_dcache_range(image_data->image_base,
269 image_data->image_size);
270 return -EAUTH;
271 }
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100272 }
Soby Mathew7c8af062017-11-10 13:14:40 +0000273#endif /* TRUSTED_BOARD_BOOT */
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100274
275 /*
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100276 * Flush the image to main memory so that it can be executed later by
Soby Mathew7c8af062017-11-10 13:14:40 +0000277 * any CPU, regardless of cache and MMU state. If TBB is enabled, then
278 * the file has been successfully loaded and authenticated and flush
279 * only for child images, not for the parents (certificates).
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100280 */
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100281 if (is_parent_image == 0) {
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000282 flush_dcache_range(image_data->image_base,
283 image_data->image_size);
284 }
Soby Mathew7c8af062017-11-10 13:14:40 +0000285
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100286
287 return 0;
288}
289
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000290/*******************************************************************************
291 * Generic function to load and authenticate an image. The image is actually
292 * loaded by calling the 'load_image()' function. Therefore, it returns the
293 * same error codes if the loading operation failed, or -EAUTH if the
294 * authentication failed. In addition, this function uses recursion to
295 * authenticate the parent images up to the root of trust.
296 ******************************************************************************/
297int load_auth_image(unsigned int image_id, image_info_t *image_data)
298{
Roberto Vargasbc1ae1f2017-09-26 12:53:01 +0100299 int err;
300
301 do {
302 err = load_auth_image_internal(image_id, image_data, 0);
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100303 } while ((err != 0) && (plat_try_next_boot_source() != 0));
Roberto Vargasbc1ae1f2017-09-26 12:53:01 +0100304
305 return err;
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000306}
307
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100308/*******************************************************************************
309 * Print the content of an entry_point_info_t structure.
310 ******************************************************************************/
311void print_entry_point_info(const entry_point_info_t *ep_info)
312{
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100313 INFO("Entry point address = 0x%lx\n", ep_info->pc);
Soby Mathewa0fedc42016-06-16 14:52:04 +0100314 INFO("SPSR = 0x%x\n", ep_info->spsr);
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100315
316#define PRINT_IMAGE_ARG(n) \
317 VERBOSE("Argument #" #n " = 0x%llx\n", \
318 (unsigned long long) ep_info->args.arg##n)
319
320 PRINT_IMAGE_ARG(0);
321 PRINT_IMAGE_ARG(1);
322 PRINT_IMAGE_ARG(2);
323 PRINT_IMAGE_ARG(3);
Soby Mathewcdf58cb2016-08-30 13:07:31 +0100324#ifndef AARCH32
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100325 PRINT_IMAGE_ARG(4);
326 PRINT_IMAGE_ARG(5);
327 PRINT_IMAGE_ARG(6);
328 PRINT_IMAGE_ARG(7);
Soby Mathewcdf58cb2016-08-30 13:07:31 +0100329#endif
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100330#undef PRINT_IMAGE_ARG
331}