1 /* 2 * Copyright (c) 2013-2018, 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_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> 20 21 #if TRUSTED_BOARD_BOOT 22 # ifdef DYN_DISABLE_AUTH 23 static int disable_auth; 24 25 /****************************************************************************** 26 * API to dynamically disable authentication. Only meant for development 27 * systems. This is only invoked if DYN_DISABLE_AUTH is defined. 28 *****************************************************************************/ 29 void 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 *****************************************************************************/ 39 static 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 49 uintptr_t page_align(uintptr_t value, unsigned dir) 50 { 51 /* Round up the limit to the next page boundary */ 52 if ((value & (PAGE_SIZE - 1U)) != 0U) { 53 value &= ~(PAGE_SIZE - 1U); 54 if (dir == UP) 55 value += PAGE_SIZE; 56 } 57 58 return value; 59 } 60 61 /******************************************************************************* 62 * Internal function to load an image at a specific address given 63 * an image ID and extents of free memory. 64 * 65 * If the load is successful then the image information is updated. 66 * 67 * Returns 0 on success, a negative error code otherwise. 68 ******************************************************************************/ 69 static int load_image(unsigned int image_id, image_info_t *image_data) 70 { 71 uintptr_t dev_handle; 72 uintptr_t image_handle; 73 uintptr_t image_spec; 74 uintptr_t image_base; 75 size_t image_size; 76 size_t bytes_read; 77 int io_result; 78 79 assert(image_data != NULL); 80 assert(image_data->h.version >= VERSION_2); 81 82 image_base = image_data->image_base; 83 84 /* Obtain a reference to the image by querying the platform layer */ 85 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec); 86 if (io_result != 0) { 87 WARN("Failed to obtain reference to image id=%u (%i)\n", 88 image_id, io_result); 89 return io_result; 90 } 91 92 /* Attempt to access the image */ 93 io_result = io_open(dev_handle, image_spec, &image_handle); 94 if (io_result != 0) { 95 WARN("Failed to access image id=%u (%i)\n", 96 image_id, io_result); 97 return io_result; 98 } 99 100 INFO("Loading image id=%u at address 0x%lx\n", image_id, image_base); 101 102 /* Find the size of the image */ 103 io_result = io_size(image_handle, &image_size); 104 if ((io_result != 0) || (image_size == 0U)) { 105 WARN("Failed to determine the size of the image id=%u (%i)\n", 106 image_id, io_result); 107 goto exit; 108 } 109 110 /* Check that the image size to load is within limit */ 111 if (image_size > image_data->image_max_size) { 112 WARN("Image id=%u size out of bounds\n", image_id); 113 io_result = -EFBIG; 114 goto exit; 115 } 116 117 /* 118 * image_data->image_max_size is a uint32_t so image_size will always 119 * fit in image_data->image_size. 120 */ 121 image_data->image_size = (uint32_t)image_size; 122 123 /* We have enough space so load the image now */ 124 /* TODO: Consider whether to try to recover/retry a partially successful read */ 125 io_result = io_read(image_handle, image_base, image_size, &bytes_read); 126 if ((io_result != 0) || (bytes_read < image_size)) { 127 WARN("Failed to load image id=%u (%i)\n", image_id, io_result); 128 goto exit; 129 } 130 131 INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base, 132 (uintptr_t)(image_base + image_size)); 133 134 exit: 135 (void)io_close(image_handle); 136 /* Ignore improbable/unrecoverable error in 'close' */ 137 138 /* TODO: Consider maintaining open device connection from this bootloader stage */ 139 (void)io_dev_close(dev_handle); 140 /* Ignore improbable/unrecoverable error in 'dev_close' */ 141 142 return io_result; 143 } 144 145 static int load_auth_image_internal(unsigned int image_id, 146 image_info_t *image_data, 147 int is_parent_image) 148 { 149 int rc; 150 151 #if TRUSTED_BOARD_BOOT 152 if (dyn_is_auth_disabled() == 0) { 153 unsigned int parent_id; 154 155 /* Use recursion to authenticate parent images */ 156 rc = auth_mod_get_parent_id(image_id, &parent_id); 157 if (rc == 0) { 158 rc = load_auth_image_internal(parent_id, image_data, 1); 159 if (rc != 0) { 160 return rc; 161 } 162 } 163 } 164 #endif /* TRUSTED_BOARD_BOOT */ 165 166 /* Load the image */ 167 rc = load_image(image_id, image_data); 168 if (rc != 0) { 169 return rc; 170 } 171 172 #if TRUSTED_BOARD_BOOT 173 if (dyn_is_auth_disabled() == 0) { 174 /* Authenticate it */ 175 rc = auth_mod_verify_img(image_id, 176 (void *)image_data->image_base, 177 image_data->image_size); 178 if (rc != 0) { 179 /* Authentication error, zero memory and flush it right away. */ 180 zero_normalmem((void *)image_data->image_base, 181 image_data->image_size); 182 flush_dcache_range(image_data->image_base, 183 image_data->image_size); 184 return -EAUTH; 185 } 186 } 187 #endif /* TRUSTED_BOARD_BOOT */ 188 189 /* 190 * Flush the image to main memory so that it can be executed later by 191 * any CPU, regardless of cache and MMU state. If TBB is enabled, then 192 * the file has been successfully loaded and authenticated and flush 193 * only for child images, not for the parents (certificates). 194 */ 195 if (is_parent_image == 0) { 196 flush_dcache_range(image_data->image_base, 197 image_data->image_size); 198 } 199 200 201 return 0; 202 } 203 204 /******************************************************************************* 205 * Generic function to load and authenticate an image. The image is actually 206 * loaded by calling the 'load_image()' function. Therefore, it returns the 207 * same error codes if the loading operation failed, or -EAUTH if the 208 * authentication failed. In addition, this function uses recursion to 209 * authenticate the parent images up to the root of trust. 210 ******************************************************************************/ 211 int load_auth_image(unsigned int image_id, image_info_t *image_data) 212 { 213 int err; 214 215 do { 216 err = load_auth_image_internal(image_id, image_data, 0); 217 } while ((err != 0) && (plat_try_next_boot_source() != 0)); 218 219 return err; 220 } 221 222 /******************************************************************************* 223 * Print the content of an entry_point_info_t structure. 224 ******************************************************************************/ 225 void print_entry_point_info(const entry_point_info_t *ep_info) 226 { 227 INFO("Entry point address = 0x%lx\n", ep_info->pc); 228 INFO("SPSR = 0x%x\n", ep_info->spsr); 229 230 #define PRINT_IMAGE_ARG(n) \ 231 VERBOSE("Argument #" #n " = 0x%llx\n", \ 232 (unsigned long long) ep_info->args.arg##n) 233 234 PRINT_IMAGE_ARG(0); 235 PRINT_IMAGE_ARG(1); 236 PRINT_IMAGE_ARG(2); 237 PRINT_IMAGE_ARG(3); 238 #ifndef AARCH32 239 PRINT_IMAGE_ARG(4); 240 PRINT_IMAGE_ARG(5); 241 PRINT_IMAGE_ARG(6); 242 PRINT_IMAGE_ARG(7); 243 #endif 244 #undef PRINT_IMAGE_ARG 245 } 246