1 /* 2 * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of ARM nor the names of its contributors may be used 15 * to endorse or promote products derived from this software without specific 16 * prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <arch.h> 32 #include <arch_helpers.h> 33 #include <assert.h> 34 #include <auth_mod.h> 35 #include <bl_common.h> 36 #include <debug.h> 37 #include <errno.h> 38 #include <io_storage.h> 39 #include <platform.h> 40 #include <string.h> 41 #include <xlat_tables.h> 42 43 uintptr_t page_align(uintptr_t value, unsigned dir) 44 { 45 /* Round up the limit to the next page boundary */ 46 if (value & (PAGE_SIZE - 1)) { 47 value &= ~(PAGE_SIZE - 1); 48 if (dir == UP) 49 value += PAGE_SIZE; 50 } 51 52 return value; 53 } 54 55 static inline unsigned int is_page_aligned (uintptr_t addr) { 56 return (addr & (PAGE_SIZE - 1)) == 0; 57 } 58 59 /****************************************************************************** 60 * Determine whether the memory region delimited by 'addr' and 'size' is free, 61 * given the extents of free memory. 62 * Return 1 if it is free, 0 otherwise. 63 *****************************************************************************/ 64 static int is_mem_free(uintptr_t free_base, size_t free_size, 65 uintptr_t addr, size_t size) 66 { 67 return (addr >= free_base) && (addr + size <= free_base + free_size); 68 } 69 70 /****************************************************************************** 71 * Inside a given memory region, determine whether a sub-region of memory is 72 * closer from the top or the bottom of the encompassing region. Return the 73 * size of the smallest chunk of free memory surrounding the sub-region in 74 * 'small_chunk_size'. 75 *****************************************************************************/ 76 static unsigned int choose_mem_pos(uintptr_t mem_start, uintptr_t mem_end, 77 uintptr_t submem_start, uintptr_t submem_end, 78 size_t *small_chunk_size) 79 { 80 size_t top_chunk_size, bottom_chunk_size; 81 82 assert(mem_start <= submem_start); 83 assert(submem_start <= submem_end); 84 assert(submem_end <= mem_end); 85 assert(small_chunk_size != NULL); 86 87 top_chunk_size = mem_end - submem_end; 88 bottom_chunk_size = submem_start - mem_start; 89 90 if (top_chunk_size < bottom_chunk_size) { 91 *small_chunk_size = top_chunk_size; 92 return TOP; 93 } else { 94 *small_chunk_size = bottom_chunk_size; 95 return BOTTOM; 96 } 97 } 98 99 /****************************************************************************** 100 * Reserve the memory region delimited by 'addr' and 'size'. The extents of free 101 * memory are passed in 'free_base' and 'free_size' and they will be updated to 102 * reflect the memory usage. 103 * The caller must ensure the memory to reserve is free. 104 *****************************************************************************/ 105 void reserve_mem(uintptr_t *free_base, size_t *free_size, 106 uintptr_t addr, size_t size) 107 { 108 size_t discard_size; 109 size_t reserved_size; 110 unsigned int pos; 111 112 assert(free_base != NULL); 113 assert(free_size != NULL); 114 assert(is_mem_free(*free_base, *free_size, addr, size)); 115 116 pos = choose_mem_pos(*free_base, *free_base + *free_size, 117 addr, addr + size, 118 &discard_size); 119 120 reserved_size = size + discard_size; 121 *free_size -= reserved_size; 122 123 if (pos == BOTTOM) 124 *free_base = addr + size; 125 126 VERBOSE("Reserved 0x%zx bytes (discarded 0x%zx bytes %s)\n", 127 reserved_size, discard_size, 128 pos == TOP ? "above" : "below"); 129 } 130 131 static void dump_load_info(uintptr_t image_load_addr, 132 size_t image_size, 133 const meminfo_t *mem_layout) 134 { 135 INFO("Trying to load image at address %p, size = 0x%zx\n", 136 (void *)image_load_addr, image_size); 137 INFO("Current memory layout:\n"); 138 INFO(" total region = [%p, %p]\n", (void *)mem_layout->total_base, 139 (void *)(mem_layout->total_base + mem_layout->total_size)); 140 INFO(" free region = [%p, %p]\n", (void *)mem_layout->free_base, 141 (void *)(mem_layout->free_base + mem_layout->free_size)); 142 } 143 144 /* Generic function to return the size of an image */ 145 size_t image_size(unsigned int image_id) 146 { 147 uintptr_t dev_handle; 148 uintptr_t image_handle; 149 uintptr_t image_spec; 150 size_t image_size = 0; 151 int io_result; 152 153 /* Obtain a reference to the image by querying the platform layer */ 154 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec); 155 if (io_result != 0) { 156 WARN("Failed to obtain reference to image id=%u (%i)\n", 157 image_id, io_result); 158 return 0; 159 } 160 161 /* Attempt to access the image */ 162 io_result = io_open(dev_handle, image_spec, &image_handle); 163 if (io_result != 0) { 164 WARN("Failed to access image id=%u (%i)\n", 165 image_id, io_result); 166 return 0; 167 } 168 169 /* Find the size of the image */ 170 io_result = io_size(image_handle, &image_size); 171 if ((io_result != 0) || (image_size == 0)) { 172 WARN("Failed to determine the size of the image id=%u (%i)\n", 173 image_id, io_result); 174 } 175 io_result = io_close(image_handle); 176 /* Ignore improbable/unrecoverable error in 'close' */ 177 178 /* TODO: Consider maintaining open device connection from this 179 * bootloader stage 180 */ 181 io_result = io_dev_close(dev_handle); 182 /* Ignore improbable/unrecoverable error in 'dev_close' */ 183 184 return image_size; 185 } 186 187 /******************************************************************************* 188 * Generic function to load an image at a specific address given an image ID and 189 * extents of free memory. 190 * 191 * If the load is successful then the image information is updated. 192 * 193 * If the entry_point_info argument is not NULL then this function also updates: 194 * - the memory layout to mark the memory as reserved; 195 * - the entry point information. 196 * 197 * The caller might pass a NULL pointer for the entry point if they are not 198 * interested in this information. This is typically the case for non-executable 199 * images (e.g. certificates) and executable images that won't ever be executed 200 * on the application processor (e.g. additional microcontroller firmware). 201 * 202 * Returns 0 on success, a negative error code otherwise. 203 ******************************************************************************/ 204 int load_image(meminfo_t *mem_layout, 205 unsigned int image_id, 206 uintptr_t image_base, 207 image_info_t *image_data, 208 entry_point_info_t *entry_point_info) 209 { 210 uintptr_t dev_handle; 211 uintptr_t image_handle; 212 uintptr_t image_spec; 213 size_t image_size; 214 size_t bytes_read; 215 int io_result; 216 217 assert(mem_layout != NULL); 218 assert(image_data != NULL); 219 assert(image_data->h.version >= VERSION_1); 220 221 /* Obtain a reference to the image by querying the platform layer */ 222 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec); 223 if (io_result != 0) { 224 WARN("Failed to obtain reference to image id=%u (%i)\n", 225 image_id, io_result); 226 return io_result; 227 } 228 229 /* Attempt to access the image */ 230 io_result = io_open(dev_handle, image_spec, &image_handle); 231 if (io_result != 0) { 232 WARN("Failed to access image id=%u (%i)\n", 233 image_id, io_result); 234 return io_result; 235 } 236 237 INFO("Loading image id=%u at address %p\n", image_id, 238 (void *) image_base); 239 240 /* Find the size of the image */ 241 io_result = io_size(image_handle, &image_size); 242 if ((io_result != 0) || (image_size == 0)) { 243 WARN("Failed to determine the size of the image id=%u (%i)\n", 244 image_id, io_result); 245 goto exit; 246 } 247 248 /* Check that the memory where the image will be loaded is free */ 249 if (!is_mem_free(mem_layout->free_base, mem_layout->free_size, 250 image_base, image_size)) { 251 WARN("Failed to reserve memory: %p - %p\n", (void *) image_base, 252 (void *) (image_base + image_size)); 253 dump_load_info(image_base, image_size, mem_layout); 254 io_result = -ENOMEM; 255 goto exit; 256 } 257 258 /* We have enough space so load the image now */ 259 /* TODO: Consider whether to try to recover/retry a partially successful read */ 260 io_result = io_read(image_handle, image_base, image_size, &bytes_read); 261 if ((io_result != 0) || (bytes_read < image_size)) { 262 WARN("Failed to load image id=%u (%i)\n", image_id, io_result); 263 goto exit; 264 } 265 266 image_data->image_base = image_base; 267 image_data->image_size = image_size; 268 269 /* 270 * Update the memory usage info. 271 * This is done after the actual loading so that it is not updated when 272 * the load is unsuccessful. 273 * If the caller does not provide an entry point, bypass the memory 274 * reservation. 275 */ 276 if (entry_point_info != NULL) { 277 reserve_mem(&mem_layout->free_base, &mem_layout->free_size, 278 image_base, image_size); 279 entry_point_info->pc = image_base; 280 } else { 281 INFO("Skip reserving memory: %p - %p\n", (void *) image_base, 282 (void *) (image_base + image_size)); 283 } 284 285 /* 286 * File has been successfully loaded. 287 * Flush the image in Trusted SRAM so that the next exception level can 288 * see it. 289 */ 290 flush_dcache_range(image_base, image_size); 291 292 INFO("Image id=%u loaded: %p - %p\n", image_id, (void *) image_base, 293 (void *) (image_base + image_size)); 294 295 exit: 296 io_close(image_handle); 297 /* Ignore improbable/unrecoverable error in 'close' */ 298 299 /* TODO: Consider maintaining open device connection from this bootloader stage */ 300 io_dev_close(dev_handle); 301 /* Ignore improbable/unrecoverable error in 'dev_close' */ 302 303 return io_result; 304 } 305 306 /******************************************************************************* 307 * Generic function to load and authenticate an image. The image is actually 308 * loaded by calling the 'load_image()' function. In addition, this function 309 * uses recursion to authenticate the parent images up to the root of trust. 310 ******************************************************************************/ 311 int load_auth_image(meminfo_t *mem_layout, 312 unsigned int image_id, 313 uintptr_t image_base, 314 image_info_t *image_data, 315 entry_point_info_t *entry_point_info) 316 { 317 int rc; 318 319 #if TRUSTED_BOARD_BOOT 320 unsigned int parent_id; 321 322 /* Use recursion to authenticate parent images */ 323 rc = auth_mod_get_parent_id(image_id, &parent_id); 324 if (rc == 0) { 325 rc = load_auth_image(mem_layout, parent_id, image_base, 326 image_data, NULL); 327 if (rc != 0) { 328 return rc; 329 } 330 } 331 #endif /* TRUSTED_BOARD_BOOT */ 332 333 /* Load the image */ 334 rc = load_image(mem_layout, image_id, image_base, image_data, 335 entry_point_info); 336 if (rc != 0) { 337 return rc; 338 } 339 340 #if TRUSTED_BOARD_BOOT 341 /* Authenticate it */ 342 rc = auth_mod_verify_img(image_id, 343 (void *)image_data->image_base, 344 image_data->image_size); 345 if (rc != 0) { 346 memset((void *)image_data->image_base, 0x00, 347 image_data->image_size); 348 flush_dcache_range(image_data->image_base, 349 image_data->image_size); 350 return -EAUTH; 351 } 352 353 /* After working with data, invalidate the data cache */ 354 inv_dcache_range(image_data->image_base, 355 (size_t)image_data->image_size); 356 #endif /* TRUSTED_BOARD_BOOT */ 357 358 return 0; 359 } 360 361 /******************************************************************************* 362 * Print the content of an entry_point_info_t structure. 363 ******************************************************************************/ 364 void print_entry_point_info(const entry_point_info_t *ep_info) 365 { 366 INFO("Entry point address = %p\n", (void *)ep_info->pc); 367 INFO("SPSR = 0x%x\n", ep_info->spsr); 368 369 #define PRINT_IMAGE_ARG(n) \ 370 VERBOSE("Argument #" #n " = 0x%llx\n", \ 371 (unsigned long long) ep_info->args.arg##n) 372 373 PRINT_IMAGE_ARG(0); 374 PRINT_IMAGE_ARG(1); 375 PRINT_IMAGE_ARG(2); 376 PRINT_IMAGE_ARG(3); 377 PRINT_IMAGE_ARG(4); 378 PRINT_IMAGE_ARG(5); 379 PRINT_IMAGE_ARG(6); 380 PRINT_IMAGE_ARG(7); 381 #undef PRINT_IMAGE_ARG 382 } 383