a09cd7171d3e0dc44cc76dfc5942bfd4939777a8
2 * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
12 #include <arch_features.h>
13 #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>
22 #if TRUSTED_BOARD_BOOT
23 # ifdef DYN_DISABLE_AUTH
24 static int disable_auth
;
26 /******************************************************************************
27 * API to dynamically disable authentication. Only meant for development
28 * systems. This is only invoked if DYN_DISABLE_AUTH is defined.
29 *****************************************************************************/
30 void dyn_disable_auth(void)
32 INFO("Disabling authentication of images dynamically\n");
35 # endif /* DYN_DISABLE_AUTH */
37 /******************************************************************************
38 * Function to determine whether the authentication is disabled dynamically.
39 *****************************************************************************/
40 static int dyn_is_auth_disabled(void)
42 # ifdef DYN_DISABLE_AUTH
48 #endif /* TRUSTED_BOARD_BOOT */
50 uintptr_t page_align(uintptr_t value
, unsigned dir
)
52 /* Round up the limit to the next page boundary */
53 if ((value
& (PAGE_SIZE
- 1U)) != 0U) {
54 value
&= ~(PAGE_SIZE
- 1U);
62 /*******************************************************************************
63 * Internal function to load an image at a specific address given
64 * an image ID and extents of free memory.
66 * If the load is successful then the image information is updated.
68 * Returns 0 on success, a negative error code otherwise.
69 ******************************************************************************/
70 static int load_image(unsigned int image_id
, image_info_t
*image_data
)
73 uintptr_t image_handle
;
80 assert(image_data
!= NULL
);
81 assert(image_data
->h
.version
>= VERSION_2
);
83 image_base
= image_data
->image_base
;
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
);
88 WARN("Failed to obtain reference to image id=%u (%i)\n",
93 /* Attempt to access the image */
94 io_result
= io_open(dev_handle
, image_spec
, &image_handle
);
96 WARN("Failed to access image id=%u (%i)\n",
101 INFO("Loading image id=%u at address 0x%lx\n", image_id
, image_base
);
103 /* Find the size of the image */
104 io_result
= io_size(image_handle
, &image_size
);
105 if ((io_result
!= 0) || (image_size
== 0U)) {
106 WARN("Failed to determine the size of the image id=%u (%i)\n",
107 image_id
, io_result
);
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
);
119 * image_data->image_max_size is a uint32_t so image_size will always
120 * fit in image_data->image_size.
122 image_data
->image_size
= (uint32_t)image_size
;
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
);
132 INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id
, image_base
,
133 (uintptr_t)(image_base
+ image_size
));
136 (void)io_close(image_handle
);
137 /* Ignore improbable/unrecoverable error in 'close' */
139 /* TODO: Consider maintaining open device connection from this bootloader stage */
140 (void)io_dev_close(dev_handle
);
141 /* Ignore improbable/unrecoverable error in 'dev_close' */
146 static int load_auth_image_internal(unsigned int image_id
,
147 image_info_t
*image_data
,
152 #if TRUSTED_BOARD_BOOT
153 if (dyn_is_auth_disabled() == 0) {
154 unsigned int parent_id
;
156 /* Use recursion to authenticate parent images */
157 rc
= auth_mod_get_parent_id(image_id
, &parent_id
);
159 rc
= load_auth_image_internal(parent_id
, image_data
, 1);
165 #endif /* TRUSTED_BOARD_BOOT */
168 rc
= load_image(image_id
, image_data
);
173 #if TRUSTED_BOARD_BOOT
174 if (dyn_is_auth_disabled() == 0) {
175 /* Authenticate it */
176 rc
= auth_mod_verify_img(image_id
,
177 (void *)image_data
->image_base
,
178 image_data
->image_size
);
180 /* Authentication error, zero memory and flush it right away. */
181 zero_normalmem((void *)image_data
->image_base
,
182 image_data
->image_size
);
183 flush_dcache_range(image_data
->image_base
,
184 image_data
->image_size
);
188 #endif /* TRUSTED_BOARD_BOOT */
191 * Flush the image to main memory so that it can be executed later by
192 * any CPU, regardless of cache and MMU state. If TBB is enabled, then
193 * the file has been successfully loaded and authenticated and flush
194 * only for child images, not for the parents (certificates).
196 if (is_parent_image
== 0) {
197 flush_dcache_range(image_data
->image_base
,
198 image_data
->image_size
);
205 /*******************************************************************************
206 * Generic function to load and authenticate an image. The image is actually
207 * loaded by calling the 'load_image()' function. Therefore, it returns the
208 * same error codes if the loading operation failed, or -EAUTH if the
209 * authentication failed. In addition, this function uses recursion to
210 * authenticate the parent images up to the root of trust.
211 ******************************************************************************/
212 int load_auth_image(unsigned int image_id
, image_info_t
*image_data
)
217 err
= load_auth_image_internal(image_id
, image_data
, 0);
218 } while ((err
!= 0) && (plat_try_next_boot_source() != 0));
223 /*******************************************************************************
224 * Print the content of an entry_point_info_t structure.
225 ******************************************************************************/
226 void print_entry_point_info(const entry_point_info_t
*ep_info
)
228 INFO("Entry point address = 0x%lx\n", ep_info
->pc
);
229 INFO("SPSR = 0x%x\n", ep_info
->spsr
);
231 #define PRINT_IMAGE_ARG(n) \
232 VERBOSE("Argument #" #n " = 0x%llx\n", \
233 (unsigned long long) ep_info->args.arg##n)
245 #undef PRINT_IMAGE_ARG
249 /*******************************************************************************
250 * Handle all possible cases regarding ARMv8.3-PAuth.
251 ******************************************************************************/
252 void bl_handle_pauth(void)
256 * ENABLE_PAUTH = 1 && CTX_INCLUDE_PAUTH_REGS = 1
258 * Check that the system supports address authentication to avoid
259 * getting an access fault when accessing the registers. This is all
260 * that is needed to check. If any of the authentication mechanisms is
261 * supported, the system knows about ARMv8.3-PAuth, so all the registers
262 * are available and accessing them won't generate a fault.
264 * Obtain 128-bit instruction key A from the platform and save it to the
265 * system registers. Pointer authentication can't be enabled here or the
266 * authentication will fail when returning from this function.
268 assert(is_armv8_3_pauth_apa_api_present());
270 uint64_t *apiakey
= plat_init_apiakey();
272 write_apiakeylo_el1(apiakey
[0]);
273 write_apiakeyhi_el1(apiakey
[1]);
274 #else /* if !ENABLE_PAUTH */
276 # if CTX_INCLUDE_PAUTH_REGS
278 * ENABLE_PAUTH = 0 && CTX_INCLUDE_PAUTH_REGS = 1
280 * Assert that the ARMv8.3-PAuth registers are present or an access
281 * fault will be triggered when they are being saved or restored.
283 assert(is_armv8_3_pauth_present());
286 * ENABLE_PAUTH = 0 && CTX_INCLUDE_PAUTH_REGS = 0
288 * Pointer authentication is allowed in the Non-secure world, but
289 * prohibited in the Secure world. The Trusted Firmware doesn't save the
290 * registers during a world switch. No check needed.
292 # endif /* CTX_INCLUDE_PAUTH_REGS */
294 #endif /* ENABLE_PAUTH */
296 #endif /* __aarch64__ */