1 /* 2 * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <errno.h> 9 #include <string.h> 10 11 #include <arch.h> 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> 21 22 #if TRUSTED_BOARD_BOOT 23 # ifdef DYN_DISABLE_AUTH 24 static int disable_auth; 25 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) 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 *****************************************************************************/ 40 static 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 50 uintptr_t page_align(uintptr_t value, unsigned dir) 51 { 52 /* Round up the limit to the next page boundary */ 53 if ((value & PAGE_SIZE_MASK) != 0U) { 54 value &= ~PAGE_SIZE_MASK; 55 if (dir == UP) 56 value += PAGE_SIZE; 57 } 58 59 return value; 60 } 61 62 /******************************************************************************* 63 * Internal function to load an image at a specific address given 64 * 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 ******************************************************************************/ 70 static int load_image(unsigned int image_id, image_info_t *image_data) 71 { 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 101 INFO("Loading image id=%u at address 0x%lx\n", image_id, image_base); 102 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); 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 118 /* 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; 123 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 132 INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base, 133 (uintptr_t)(image_base + image_size)); 134 135 exit: 136 (void)io_close(image_handle); 137 /* Ignore improbable/unrecoverable error in 'close' */ 138 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' */ 142 143 return io_result; 144 } 145 146 /* 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 */ 150 static int load_image_flush(unsigned int image_id, 151 image_info_t *image_data) 152 { 153 int rc; 154 155 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 165 #if TRUSTED_BOARD_BOOT 166 /* 167 * This function uses recursion to authenticate the parent images up to the root 168 * of trust. 169 */ 170 static 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; 176 177 /* 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; 183 } 184 } 185 186 /* Load the image */ 187 rc = load_image(image_id, image_data); 188 if (rc != 0) { 189 return rc; 190 } 191 192 /* 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, 199 image_data->image_size); 200 flush_dcache_range(image_data->image_base, 201 image_data->image_size); 202 return -EAUTH; 203 } 204 205 /* 206 * Flush the image to main memory so that it can be executed later by 207 * any CPU, regardless of cache and MMU state. This is only needed for 208 * child images, not for the parents (certificates). 209 */ 210 if (is_parent_image == 0) { 211 flush_dcache_range(image_data->image_base, 212 image_data->image_size); 213 } 214 215 return 0; 216 } 217 #endif /* TRUSTED_BOARD_BOOT */ 218 219 static int load_auth_image_internal(unsigned int image_id, 220 image_info_t *image_data) 221 { 222 #if TRUSTED_BOARD_BOOT 223 if (dyn_is_auth_disabled() == 0) { 224 return load_auth_image_recursive(image_id, image_data, 0); 225 } 226 #endif 227 228 return load_image_flush(image_id, image_data); 229 } 230 231 /******************************************************************************* 232 * Generic function to load and authenticate an image. The image is actually 233 * loaded by calling the 'load_image()' function. Therefore, it returns the 234 * same error codes if the loading operation failed, or -EAUTH if the 235 * authentication failed. In addition, this function uses recursion to 236 * authenticate the parent images up to the root of trust (if TBB is enabled). 237 ******************************************************************************/ 238 int load_auth_image(unsigned int image_id, image_info_t *image_data) 239 { 240 int err; 241 242 do { 243 err = load_auth_image_internal(image_id, image_data); 244 } while ((err != 0) && (plat_try_next_boot_source() != 0)); 245 246 return err; 247 } 248 249 /******************************************************************************* 250 * Print the content of an entry_point_info_t structure. 251 ******************************************************************************/ 252 void print_entry_point_info(const entry_point_info_t *ep_info) 253 { 254 INFO("Entry point address = 0x%lx\n", ep_info->pc); 255 INFO("SPSR = 0x%x\n", ep_info->spsr); 256 257 #define PRINT_IMAGE_ARG(n) \ 258 VERBOSE("Argument #" #n " = 0x%llx\n", \ 259 (unsigned long long) ep_info->args.arg##n) 260 261 PRINT_IMAGE_ARG(0); 262 PRINT_IMAGE_ARG(1); 263 PRINT_IMAGE_ARG(2); 264 PRINT_IMAGE_ARG(3); 265 #ifdef __aarch64__ 266 PRINT_IMAGE_ARG(4); 267 PRINT_IMAGE_ARG(5); 268 PRINT_IMAGE_ARG(6); 269 PRINT_IMAGE_ARG(7); 270 #endif 271 #undef PRINT_IMAGE_ARG 272 } 273