blob: eb2352a7735102f6a5b9e3e3abfa498df4329ca0 [file] [log] [blame]
Achin Gupta4f6ad662013-10-25 09:08:21 +01001/*
Manish V Badarkhe57b669f2021-09-20 09:06:02 +01002 * Copyright (c) 2013-2021, 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>
Antonio Nino Diaz25cda672019-02-19 11:53:51 +000012#include <arch_features.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000013#include <arch_helpers.h>
14#include <common/bl_common.h>
15#include <common/debug.h>
16#include <drivers/auth/auth_mod.h>
17#include <drivers/io/io_storage.h>
18#include <lib/utils.h>
19#include <lib/xlat_tables/xlat_tables_defs.h>
20#include <plat/common/platform.h>
Achin Gupta4f6ad662013-10-25 09:08:21 +010021
Soby Mathew9fe88042018-03-26 12:43:37 +010022#if TRUSTED_BOARD_BOOT
23# ifdef DYN_DISABLE_AUTH
24static int disable_auth;
25
26/******************************************************************************
27 * API to dynamically disable authentication. Only meant for development
Roberto Vargas025946a2018-09-24 17:20:48 +010028 * systems. This is only invoked if DYN_DISABLE_AUTH is defined.
Soby Mathew9fe88042018-03-26 12:43:37 +010029 *****************************************************************************/
30void dyn_disable_auth(void)
31{
32 INFO("Disabling authentication of images dynamically\n");
33 disable_auth = 1;
34}
35# endif /* DYN_DISABLE_AUTH */
36
37/******************************************************************************
38 * Function to determine whether the authentication is disabled dynamically.
39 *****************************************************************************/
40static int dyn_is_auth_disabled(void)
41{
42# ifdef DYN_DISABLE_AUTH
43 return disable_auth;
44# else
45 return 0;
46# endif
47}
48#endif /* TRUSTED_BOARD_BOOT */
49
Soby Mathewa0fedc42016-06-16 14:52:04 +010050uintptr_t page_align(uintptr_t value, unsigned dir)
Achin Gupta4f6ad662013-10-25 09:08:21 +010051{
Achin Gupta4f6ad662013-10-25 09:08:21 +010052 /* Round up the limit to the next page boundary */
Jimmy Brissoned202072020-08-04 16:18:52 -050053 if ((value & PAGE_SIZE_MASK) != 0U) {
54 value &= ~PAGE_SIZE_MASK;
Achin Gupta4f6ad662013-10-25 09:08:21 +010055 if (dir == UP)
Soby Mathewa0fedc42016-06-16 14:52:04 +010056 value += PAGE_SIZE;
Achin Gupta4f6ad662013-10-25 09:08:21 +010057 }
58
59 return value;
60}
61
Yatharth Kochar3345a8d2016-09-12 16:08:41 +010062/*******************************************************************************
Soby Mathew7c8af062017-11-10 13:14:40 +000063 * Internal function to load an image at a specific address given
Yatharth Kochar3345a8d2016-09-12 16:08:41 +010064 * an image ID and extents of free memory.
65 *
66 * If the load is successful then the image information is updated.
67 *
68 * Returns 0 on success, a negative error code otherwise.
69 ******************************************************************************/
Soby Mathew7c8af062017-11-10 13:14:40 +000070static int load_image(unsigned int image_id, image_info_t *image_data)
Yatharth Kochar3345a8d2016-09-12 16:08:41 +010071{
72 uintptr_t dev_handle;
73 uintptr_t image_handle;
74 uintptr_t image_spec;
75 uintptr_t image_base;
76 size_t image_size;
77 size_t bytes_read;
78 int io_result;
79
80 assert(image_data != NULL);
81 assert(image_data->h.version >= VERSION_2);
82
83 image_base = image_data->image_base;
84
85 /* Obtain a reference to the image by querying the platform layer */
86 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec);
87 if (io_result != 0) {
88 WARN("Failed to obtain reference to image id=%u (%i)\n",
89 image_id, io_result);
90 return io_result;
91 }
92
93 /* Attempt to access the image */
94 io_result = io_open(dev_handle, image_spec, &image_handle);
95 if (io_result != 0) {
96 WARN("Failed to access image id=%u (%i)\n",
97 image_id, io_result);
98 return io_result;
99 }
100
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100101 INFO("Loading image id=%u at address 0x%lx\n", image_id, image_base);
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100102
103 /* Find the size of the image */
104 io_result = io_size(image_handle, &image_size);
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100105 if ((io_result != 0) || (image_size == 0U)) {
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100106 WARN("Failed to determine the size of the image id=%u (%i)\n",
107 image_id, io_result);
108 goto exit;
109 }
110
111 /* Check that the image size to load is within limit */
112 if (image_size > image_data->image_max_size) {
113 WARN("Image id=%u size out of bounds\n", image_id);
114 io_result = -EFBIG;
115 goto exit;
116 }
117
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100118 /*
119 * image_data->image_max_size is a uint32_t so image_size will always
120 * fit in image_data->image_size.
121 */
122 image_data->image_size = (uint32_t)image_size;
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100123
124 /* We have enough space so load the image now */
125 /* TODO: Consider whether to try to recover/retry a partially successful read */
126 io_result = io_read(image_handle, image_base, image_size, &bytes_read);
127 if ((io_result != 0) || (bytes_read < image_size)) {
128 WARN("Failed to load image id=%u (%i)\n", image_id, io_result);
129 goto exit;
130 }
131
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100132 INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base,
133 (uintptr_t)(image_base + image_size));
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100134
135exit:
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100136 (void)io_close(image_handle);
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100137 /* Ignore improbable/unrecoverable error in 'close' */
138
139 /* TODO: Consider maintaining open device connection from this bootloader stage */
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100140 (void)io_dev_close(dev_handle);
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100141 /* Ignore improbable/unrecoverable error in 'dev_close' */
142
143 return io_result;
144}
145
Sandrine Bailleux2cce8032019-10-14 13:47:21 +0200146/*
147 * Load an image and flush it out to main memory so that it can be executed
148 * later by any CPU, regardless of cache and MMU state.
149 */
150static int load_image_flush(unsigned int image_id,
151 image_info_t *image_data)
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100152{
153 int rc;
154
Sandrine Bailleux2cce8032019-10-14 13:47:21 +0200155 rc = load_image(image_id, image_data);
156 if (rc == 0) {
157 flush_dcache_range(image_data->image_base,
158 image_data->image_size);
159 }
160
161 return rc;
162}
163
164
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100165#if TRUSTED_BOARD_BOOT
Sandrine Bailleux2cce8032019-10-14 13:47:21 +0200166/*
167 * This function uses recursion to authenticate the parent images up to the root
168 * of trust.
169 */
170static int load_auth_image_recursive(unsigned int image_id,
171 image_info_t *image_data,
172 int is_parent_image)
173{
174 int rc;
175 unsigned int parent_id;
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100176
Sandrine Bailleux2cce8032019-10-14 13:47:21 +0200177 /* Use recursion to authenticate parent images */
178 rc = auth_mod_get_parent_id(image_id, &parent_id);
179 if (rc == 0) {
180 rc = load_auth_image_recursive(parent_id, image_data, 1);
181 if (rc != 0) {
182 return rc;
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100183 }
184 }
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100185
186 /* Load the image */
187 rc = load_image(image_id, image_data);
188 if (rc != 0) {
189 return rc;
190 }
191
Sandrine Bailleux2cce8032019-10-14 13:47:21 +0200192 /* Authenticate it */
193 rc = auth_mod_verify_img(image_id,
194 (void *)image_data->image_base,
195 image_data->image_size);
196 if (rc != 0) {
197 /* Authentication error, zero memory and flush it right away. */
198 zero_normalmem((void *)image_data->image_base,
Soby Mathew9fe88042018-03-26 12:43:37 +0100199 image_data->image_size);
Sandrine Bailleux2cce8032019-10-14 13:47:21 +0200200 flush_dcache_range(image_data->image_base,
201 image_data->image_size);
202 return -EAUTH;
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100203 }
204
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100205 if (is_parent_image == 0) {
Manish V Badarkhe57b669f2021-09-20 09:06:02 +0100206 /*
207 * Measure the image.
208 * We do not measure its parents because these only play a role
209 * in authentication, which is orthogonal to measured boot.
210 *
211 * TODO: Change this code if we change our minds about measuring
212 * certificates.
213 */
Manish V Badarkhea74d9632021-09-14 23:12:42 +0100214 rc = plat_mboot_measure_image(image_id, image_data);
Manish V Badarkhe57b669f2021-09-20 09:06:02 +0100215 if (rc != 0) {
216 return rc;
217 }
Manish V Badarkhea74d9632021-09-14 23:12:42 +0100218
Manish V Badarkhe57b669f2021-09-20 09:06:02 +0100219 /*
220 * Flush the image to main memory so that it can be executed
221 * later by any CPU, regardless of cache and MMU state. This
222 * is only needed for child images, not for the parents
223 * (certificates).
224 */
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000225 flush_dcache_range(image_data->image_base,
226 image_data->image_size);
227 }
Soby Mathew7c8af062017-11-10 13:14:40 +0000228
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100229 return 0;
230}
Sandrine Bailleux2cce8032019-10-14 13:47:21 +0200231#endif /* TRUSTED_BOARD_BOOT */
232
233static int load_auth_image_internal(unsigned int image_id,
234 image_info_t *image_data)
235{
236#if TRUSTED_BOARD_BOOT
237 if (dyn_is_auth_disabled() == 0) {
238 return load_auth_image_recursive(image_id, image_data, 0);
239 }
240#endif
241
242 return load_image_flush(image_id, image_data);
243}
Yatharth Kochar3345a8d2016-09-12 16:08:41 +0100244
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000245/*******************************************************************************
246 * Generic function to load and authenticate an image. The image is actually
247 * loaded by calling the 'load_image()' function. Therefore, it returns the
248 * same error codes if the loading operation failed, or -EAUTH if the
249 * authentication failed. In addition, this function uses recursion to
Sandrine Bailleux2cce8032019-10-14 13:47:21 +0200250 * authenticate the parent images up to the root of trust (if TBB is enabled).
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000251 ******************************************************************************/
252int load_auth_image(unsigned int image_id, image_info_t *image_data)
253{
Roberto Vargasbc1ae1f2017-09-26 12:53:01 +0100254 int err;
255
Manish V Badarkheb59bf9f2021-07-01 21:32:31 +0100256/*
257 * All firmware banks should be part of the same non-volatile storage as per
258 * PSA FWU specification, hence don't check for any alternate boot source
259 * when PSA FWU is enabled.
260 */
261#if PSA_FWU_SUPPORT
262 err = load_auth_image_internal(image_id, image_data);
263#else
Roberto Vargasbc1ae1f2017-09-26 12:53:01 +0100264 do {
Sandrine Bailleux2cce8032019-10-14 13:47:21 +0200265 err = load_auth_image_internal(image_id, image_data);
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100266 } while ((err != 0) && (plat_try_next_boot_source() != 0));
Manish V Badarkheb59bf9f2021-07-01 21:32:31 +0100267#endif /* PSA_FWU_SUPPORT */
Roberto Vargasbc1ae1f2017-09-26 12:53:01 +0100268
269 return err;
Antonio Nino Diazd7db8702016-11-22 10:58:30 +0000270}
271
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100272/*******************************************************************************
273 * Print the content of an entry_point_info_t structure.
274 ******************************************************************************/
275void print_entry_point_info(const entry_point_info_t *ep_info)
276{
Antonio Nino Diazf0b14cf2018-10-04 09:55:23 +0100277 INFO("Entry point address = 0x%lx\n", ep_info->pc);
Soby Mathewa0fedc42016-06-16 14:52:04 +0100278 INFO("SPSR = 0x%x\n", ep_info->spsr);
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100279
280#define PRINT_IMAGE_ARG(n) \
281 VERBOSE("Argument #" #n " = 0x%llx\n", \
282 (unsigned long long) ep_info->args.arg##n)
283
284 PRINT_IMAGE_ARG(0);
285 PRINT_IMAGE_ARG(1);
286 PRINT_IMAGE_ARG(2);
287 PRINT_IMAGE_ARG(3);
Julius Werner8e0ef0f2019-07-09 14:02:43 -0700288#ifdef __aarch64__
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100289 PRINT_IMAGE_ARG(4);
290 PRINT_IMAGE_ARG(5);
291 PRINT_IMAGE_ARG(6);
292 PRINT_IMAGE_ARG(7);
Soby Mathewcdf58cb2016-08-30 13:07:31 +0100293#endif
Sandrine Bailleuxb2e224c2015-09-28 17:03:06 +0100294#undef PRINT_IMAGE_ARG
295}