blob: 60baa5bdfbe0d7dd4b266835ec690b5666e5de8f [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
Roberto Vargas025946a2018-09-24 17:20:48 +010026 * systems. This is only invoked if DYN_DISABLE_AUTH is defined.
Soby Mathew9fe88042018-03-26 12:43:37 +010027 *****************************************************************************/
28void dyn_disable_auth(void)
29{
30 INFO("Disabling authentication of images dynamically\n");
31 disable_auth = 1;
32}
33# endif /* DYN_DISABLE_AUTH */
34
35/******************************************************************************
36 * Function to determine whether the authentication is disabled dynamically.
37 *****************************************************************************/
38static int dyn_is_auth_disabled(void)
39{
40# ifdef DYN_DISABLE_AUTH
41 return disable_auth;
42# else
43 return 0;
44# endif
45}
46#endif /* TRUSTED_BOARD_BOOT */
47
Soby Mathewa0fedc42016-06-16 14:52:04 +010048uintptr_t page_align(uintptr_t value, unsigned dir)
Achin Gupta4f6ad662013-10-25 09:08:21 +010049{
Achin Gupta4f6ad662013-10-25 09:08:21 +010050 /* Round up the limit to the next page boundary */
Soby Mathewa0fedc42016-06-16 14:52:04 +010051 if (value & (PAGE_SIZE - 1)) {
52 value &= ~(PAGE_SIZE - 1);
Achin Gupta4f6ad662013-10-25 09:08:21 +010053 if (dir == UP)
Soby Mathewa0fedc42016-06-16 14:52:04 +010054 value += PAGE_SIZE;
Achin Gupta4f6ad662013-10-25 09:08:21 +010055 }
56
57 return value;
58}
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 *****************************************************************************/
Sandrine Bailleuxb0e529b2016-11-08 14:27:10 +000066int is_mem_free(uintptr_t free_base, size_t free_size,
Soby Mathewa0fedc42016-06-16 14:52:04 +010067 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
Ryan Harkin87274c42014-02-04 11:43:57 +0000103/* Generic function to return the size of an image */
Daniel Boulby4f3b6ed2018-05-04 11:18:26 +0100104size_t get_image_size(unsigned int image_id)
Ryan Harkin87274c42014-02-04 11:43:57 +0000105{
Dan Handleya4cb68e2014-04-23 13:47:06 +0100106 uintptr_t dev_handle;
107 uintptr_t image_handle;
108 uintptr_t image_spec;
Ryan Harkin87274c42014-02-04 11:43:57 +0000109 size_t image_size = 0;
Juan Castillo6e762062015-11-02 10:47:01 +0000110 int io_result;
Ryan Harkin87274c42014-02-04 11:43:57 +0000111
Ryan Harkin87274c42014-02-04 11:43:57 +0000112 /* Obtain a reference to the image by querying the platform layer */
Juan Castillo3a66aca2015-04-13 17:36:19 +0100113 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
Juan Castillo6e762062015-11-02 10:47:01 +0000114 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100115 WARN("Failed to obtain reference to image id=%u (%i)\n",
116 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000117 return 0;
118 }
119
120 /* Attempt to access the image */
121 io_result = io_open(dev_handle, image_spec, &image_handle);
Juan Castillo6e762062015-11-02 10:47:01 +0000122 if (io_result != 0) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100123 WARN("Failed to access image id=%u (%i)\n",
124 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000125 return 0;
126 }
127
128 /* Find the size of the image */
129 io_result = io_size(image_handle, &image_size);
Juan Castillo6e762062015-11-02 10:47:01 +0000130 if ((io_result != 0) || (image_size == 0)) {
Juan Castillo3a66aca2015-04-13 17:36:19 +0100131 WARN("Failed to determine the size of the image id=%u (%i)\n",
132 image_id, io_result);
Ryan Harkin87274c42014-02-04 11:43:57 +0000133 }
134 io_result = io_close(image_handle);
135 /* Ignore improbable/unrecoverable error in 'close' */
136
137 /* TODO: Consider maintaining open device connection from this
138 * bootloader stage
139 */
140 io_result = io_dev_close(dev_handle);
141 /* Ignore improbable/unrecoverable error in 'dev_close' */
142
143 return image_size;
144}
Sandrine Bailleux467d0572014-06-24 14:02:34 +0100145
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100146/*******************************************************************************
Soby Mathew7c8af062017-11-10 13:14:40 +0000147 * Internal function to load an image at a specific address given
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100148 * an image ID and extents of free memory.
149 *
150 * If the load is successful then the image information is updated.
151 *
152 * Returns 0 on success, a negative error code otherwise.
153 ******************************************************************************/
Soby Mathew7c8af062017-11-10 13:14:40 +0000154static int load_image(unsigned int image_id, image_info_t *image_data)
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100155{
156 uintptr_t dev_handle;
157 uintptr_t image_handle;
158 uintptr_t image_spec;
159 uintptr_t image_base;
160 size_t image_size;
161 size_t bytes_read;
162 int io_result;
163
164 assert(image_data != NULL);
165 assert(image_data->h.version >= VERSION_2);
166
167 image_base = image_data->image_base;
168
169 /* Obtain a reference to the image by querying the platform layer */
170 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
171 if (io_result != 0) {
172 WARN("Failed to obtain reference to image id=%u (%i)\n",
173 image_id, io_result);
174 return io_result;
175 }
176
177 /* Attempt to access the image */
178 io_result = io_open(dev_handle, image_spec, &image_handle);
179 if (io_result != 0) {
180 WARN("Failed to access image id=%u (%i)\n",
181 image_id, io_result);
182 return io_result;
183 }
184
185 INFO("Loading image id=%u at address %p\n", image_id,
186 (void *) image_base);
187
188 /* Find the size of the image */
189 io_result = io_size(image_handle, &image_size);
190 if ((io_result != 0) || (image_size == 0)) {
191 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
203 image_data->image_size = image_size;
204
205 /* We have enough space so load the image now */
206 /* TODO: Consider whether to try to recover/retry a partially successful read */
207 io_result = io_read(image_handle, image_base, image_size, &bytes_read);
208 if ((io_result != 0) || (bytes_read < image_size)) {
209 WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
210 goto exit;
211 }
212
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100213 INFO("Image id=%u loaded: %p - %p\n", image_id, (void *) image_base,
214 (void *) (image_base + image_size));
215
216exit:
217 io_close(image_handle);
218 /* Ignore improbable/unrecoverable error in 'close' */
219
220 /* TODO: Consider maintaining open device connection from this bootloader stage */
221 io_dev_close(dev_handle);
222 /* Ignore improbable/unrecoverable error in 'dev_close' */
223
224 return io_result;
225}
226
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000227static int load_auth_image_internal(unsigned int image_id,
228 image_info_t *image_data,
229 int is_parent_image)
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100230{
231 int rc;
232
233#if TRUSTED_BOARD_BOOT
Soby Mathew9fe88042018-03-26 12:43:37 +0100234 if (dyn_is_auth_disabled() == 0) {
235 unsigned int parent_id;
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100236
Soby Mathew9fe88042018-03-26 12:43:37 +0100237 /* Use recursion to authenticate parent images */
238 rc = auth_mod_get_parent_id(image_id, &parent_id);
239 if (rc == 0) {
240 rc = load_auth_image_internal(parent_id, image_data, 1);
241 if (rc != 0) {
242 return rc;
243 }
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100244 }
245 }
246#endif /* TRUSTED_BOARD_BOOT */
247
248 /* Load the image */
249 rc = load_image(image_id, image_data);
250 if (rc != 0) {
251 return rc;
252 }
253
254#if TRUSTED_BOARD_BOOT
Soby Mathew9fe88042018-03-26 12:43:37 +0100255 if (dyn_is_auth_disabled() == 0) {
256 /* Authenticate it */
257 rc = auth_mod_verify_img(image_id,
258 (void *)image_data->image_base,
259 image_data->image_size);
260 if (rc != 0) {
261 /* Authentication error, zero memory and flush it right away. */
262 zero_normalmem((void *)image_data->image_base,
263 image_data->image_size);
264 flush_dcache_range(image_data->image_base,
265 image_data->image_size);
266 return -EAUTH;
267 }
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100268 }
Soby Mathew7c8af062017-11-10 13:14:40 +0000269#endif /* TRUSTED_BOARD_BOOT */
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100270
271 /*
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100272 * Flush the image to main memory so that it can be executed later by
Soby Mathew7c8af062017-11-10 13:14:40 +0000273 * any CPU, regardless of cache and MMU state. If TBB is enabled, then
274 * the file has been successfully loaded and authenticated and flush
275 * only for child images, not for the parents (certificates).
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100276 */
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000277 if (!is_parent_image) {
278 flush_dcache_range(image_data->image_base,
279 image_data->image_size);
280 }
Soby Mathew7c8af062017-11-10 13:14:40 +0000281
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100282
283 return 0;
284}
285
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000286/*******************************************************************************
287 * Generic function to load and authenticate an image. The image is actually
288 * loaded by calling the 'load_image()' function. Therefore, it returns the
289 * same error codes if the loading operation failed, or -EAUTH if the
290 * authentication failed. In addition, this function uses recursion to
291 * authenticate the parent images up to the root of trust.
292 ******************************************************************************/
293int load_auth_image(unsigned int image_id, image_info_t *image_data)
294{
Roberto Vargasbc1ae1f2017-09-26 12:53:01 +0100295 int err;
296
297 do {
298 err = load_auth_image_internal(image_id, image_data, 0);
299 } while (err != 0 && plat_try_next_boot_source());
300
301 return err;
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000302}
303
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100304/*******************************************************************************
305 * Print the content of an entry_point_info_t structure.
306 ******************************************************************************/
307void print_entry_point_info(const entry_point_info_t *ep_info)
308{
Soby Mathewa0fedc42016-06-16 14:52:04 +0100309 INFO("Entry point address = %p\n", (void *)ep_info->pc);
310 INFO("SPSR = 0x%x\n", ep_info->spsr);
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100311
312#define PRINT_IMAGE_ARG(n) \
313 VERBOSE("Argument #" #n " = 0x%llx\n", \
314 (unsigned long long) ep_info->args.arg##n)
315
316 PRINT_IMAGE_ARG(0);
317 PRINT_IMAGE_ARG(1);
318 PRINT_IMAGE_ARG(2);
319 PRINT_IMAGE_ARG(3);
Soby Mathewcdf58cb2016-08-30 13:07:31 +0100320#ifndef AARCH32
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100321 PRINT_IMAGE_ARG(4);
322 PRINT_IMAGE_ARG(5);
323 PRINT_IMAGE_ARG(6);
324 PRINT_IMAGE_ARG(7);
Soby Mathewcdf58cb2016-08-30 13:07:31 +0100325#endif
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100326#undef PRINT_IMAGE_ARG
327}