1 /* 2 * Copyright (c) 2013-2015, 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 unsigned long page_align(unsigned long value, unsigned dir) 44 { 45 unsigned long page_size = 1 << FOUR_KB_SHIFT; 46 47 /* Round up the limit to the next page boundary */ 48 if (value & (page_size - 1)) { 49 value &= ~(page_size - 1); 50 if (dir == UP) 51 value += page_size; 52 } 53 54 return value; 55 } 56 57 static inline unsigned int is_page_aligned (unsigned long addr) { 58 const unsigned long page_size = 1 << FOUR_KB_SHIFT; 59 60 return (addr & (page_size - 1)) == 0; 61 } 62 63 /****************************************************************************** 64 * Determine whether the memory region delimited by 'addr' and 'size' is free, 65 * given the extents of free memory. 66 * Return 1 if it is free, 0 otherwise. 67 *****************************************************************************/ 68 static int is_mem_free(uint64_t free_base, size_t free_size, 69 uint64_t addr, size_t size) 70 { 71 return (addr >= free_base) && (addr + size <= free_base + free_size); 72 } 73 74 /****************************************************************************** 75 * Inside a given memory region, determine whether a sub-region of memory is 76 * closer from the top or the bottom of the encompassing region. Return the 77 * size of the smallest chunk of free memory surrounding the sub-region in 78 * 'small_chunk_size'. 79 *****************************************************************************/ 80 static unsigned int choose_mem_pos(uint64_t mem_start, uint64_t mem_end, 81 uint64_t submem_start, uint64_t submem_end, 82 size_t *small_chunk_size) 83 { 84 size_t top_chunk_size, bottom_chunk_size; 85 86 assert(mem_start <= submem_start); 87 assert(submem_start <= submem_end); 88 assert(submem_end <= mem_end); 89 assert(small_chunk_size != NULL); 90 91 top_chunk_size = mem_end - submem_end; 92 bottom_chunk_size = submem_start - mem_start; 93 94 if (top_chunk_size < bottom_chunk_size) { 95 *small_chunk_size = top_chunk_size; 96 return TOP; 97 } else { 98 *small_chunk_size = bottom_chunk_size; 99 return BOTTOM; 100 } 101 } 102 103 /****************************************************************************** 104 * Reserve the memory region delimited by 'addr' and 'size'. The extents of free 105 * memory are passed in 'free_base' and 'free_size' and they will be updated to 106 * reflect the memory usage. 107 * The caller must ensure the memory to reserve is free. 108 *****************************************************************************/ 109 void reserve_mem(uint64_t *free_base, size_t *free_size, 110 uint64_t addr, size_t size) 111 { 112 size_t discard_size; 113 size_t reserved_size; 114 unsigned int pos; 115 116 assert(free_base != NULL); 117 assert(free_size != NULL); 118 assert(is_mem_free(*free_base, *free_size, addr, size)); 119 120 pos = choose_mem_pos(*free_base, *free_base + *free_size, 121 addr, addr + size, 122 &discard_size); 123 124 reserved_size = size + discard_size; 125 *free_size -= reserved_size; 126 127 if (pos == BOTTOM) 128 *free_base = addr + size; 129 130 VERBOSE("Reserved 0x%lx bytes (discarded 0x%lx bytes %s)\n", 131 reserved_size, discard_size, 132 pos == TOP ? "above" : "below"); 133 } 134 135 static void dump_load_info(unsigned long image_load_addr, 136 unsigned long image_size, 137 const meminfo_t *mem_layout) 138 { 139 INFO("Trying to load image at address 0x%lx, size = 0x%lx\n", 140 image_load_addr, image_size); 141 INFO("Current memory layout:\n"); 142 INFO(" total region = [0x%lx, 0x%lx]\n", mem_layout->total_base, 143 mem_layout->total_base + mem_layout->total_size); 144 INFO(" free region = [0x%lx, 0x%lx]\n", mem_layout->free_base, 145 mem_layout->free_base + mem_layout->free_size); 146 } 147 148 /* Generic function to return the size of an image */ 149 unsigned long image_size(unsigned int image_id) 150 { 151 uintptr_t dev_handle; 152 uintptr_t image_handle; 153 uintptr_t image_spec; 154 size_t image_size = 0; 155 int io_result; 156 157 /* Obtain a reference to the image by querying the platform layer */ 158 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec); 159 if (io_result != 0) { 160 WARN("Failed to obtain reference to image id=%u (%i)\n", 161 image_id, io_result); 162 return 0; 163 } 164 165 /* Attempt to access the image */ 166 io_result = io_open(dev_handle, image_spec, &image_handle); 167 if (io_result != 0) { 168 WARN("Failed to access image id=%u (%i)\n", 169 image_id, io_result); 170 return 0; 171 } 172 173 /* Find the size of the image */ 174 io_result = io_size(image_handle, &image_size); 175 if ((io_result != 0) || (image_size == 0)) { 176 WARN("Failed to determine the size of the image id=%u (%i)\n", 177 image_id, io_result); 178 } 179 io_result = io_close(image_handle); 180 /* Ignore improbable/unrecoverable error in 'close' */ 181 182 /* TODO: Consider maintaining open device connection from this 183 * bootloader stage 184 */ 185 io_result = io_dev_close(dev_handle); 186 /* Ignore improbable/unrecoverable error in 'dev_close' */ 187 188 return image_size; 189 } 190 191 /******************************************************************************* 192 * Generic function to load an image at a specific address given an image ID and 193 * extents of free memory. 194 * 195 * If the load is successful then the image information is updated. 196 * 197 * If the entry_point_info argument is not NULL then this function also updates: 198 * - the memory layout to mark the memory as reserved; 199 * - the entry point information. 200 * 201 * The caller might pass a NULL pointer for the entry point if they are not 202 * interested in this information. This is typically the case for non-executable 203 * images (e.g. certificates) and executable images that won't ever be executed 204 * on the application processor (e.g. additional microcontroller firmware). 205 * 206 * Returns 0 on success, a negative error code otherwise. 207 ******************************************************************************/ 208 int load_image(meminfo_t *mem_layout, 209 unsigned int image_id, 210 uintptr_t image_base, 211 image_info_t *image_data, 212 entry_point_info_t *entry_point_info) 213 { 214 uintptr_t dev_handle; 215 uintptr_t image_handle; 216 uintptr_t image_spec; 217 size_t image_size; 218 size_t bytes_read; 219 int io_result; 220 221 assert(mem_layout != NULL); 222 assert(image_data != NULL); 223 assert(image_data->h.version >= VERSION_1); 224 225 /* Obtain a reference to the image by querying the platform layer */ 226 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec); 227 if (io_result != 0) { 228 WARN("Failed to obtain reference to image id=%u (%i)\n", 229 image_id, io_result); 230 return io_result; 231 } 232 233 /* Attempt to access the image */ 234 io_result = io_open(dev_handle, image_spec, &image_handle); 235 if (io_result != 0) { 236 WARN("Failed to access image id=%u (%i)\n", 237 image_id, io_result); 238 return io_result; 239 } 240 241 INFO("Loading image id=%u at address %p\n", image_id, 242 (void *) image_base); 243 244 /* Find the size of the image */ 245 io_result = io_size(image_handle, &image_size); 246 if ((io_result != 0) || (image_size == 0)) { 247 WARN("Failed to determine the size of the image id=%u (%i)\n", 248 image_id, io_result); 249 goto exit; 250 } 251 252 /* Check that the memory where the image will be loaded is free */ 253 if (!is_mem_free(mem_layout->free_base, mem_layout->free_size, 254 image_base, image_size)) { 255 WARN("Failed to reserve memory: %p - %p\n", (void *) image_base, 256 (void *) (image_base + image_size)); 257 dump_load_info(image_base, image_size, mem_layout); 258 io_result = -ENOMEM; 259 goto exit; 260 } 261 262 /* We have enough space so load the image now */ 263 /* TODO: Consider whether to try to recover/retry a partially successful read */ 264 io_result = io_read(image_handle, image_base, image_size, &bytes_read); 265 if ((io_result != 0) || (bytes_read < image_size)) { 266 WARN("Failed to load image id=%u (%i)\n", image_id, io_result); 267 goto exit; 268 } 269 270 image_data->image_base = image_base; 271 image_data->image_size = image_size; 272 273 /* 274 * Update the memory usage info. 275 * This is done after the actual loading so that it is not updated when 276 * the load is unsuccessful. 277 * If the caller does not provide an entry point, bypass the memory 278 * reservation. 279 */ 280 if (entry_point_info != NULL) { 281 reserve_mem(&mem_layout->free_base, &mem_layout->free_size, 282 image_base, image_size); 283 entry_point_info->pc = image_base; 284 } else { 285 INFO("Skip reserving memory: %p - %p\n", (void *) image_base, 286 (void *) (image_base + image_size)); 287 } 288 289 /* 290 * File has been successfully loaded. 291 * Flush the image in Trusted SRAM so that the next exception level can 292 * see it. 293 */ 294 flush_dcache_range(image_base, image_size); 295 296 INFO("Image id=%u loaded: %p - %p\n", image_id, (void *) image_base, 297 (void *) (image_base + image_size)); 298 299 exit: 300 io_close(image_handle); 301 /* Ignore improbable/unrecoverable error in 'close' */ 302 303 /* TODO: Consider maintaining open device connection from this bootloader stage */ 304 io_dev_close(dev_handle); 305 /* Ignore improbable/unrecoverable error in 'dev_close' */ 306 307 return io_result; 308 } 309 310 /******************************************************************************* 311 * Generic function to load and authenticate an image. The image is actually 312 * loaded by calling the 'load_image()' function. In addition, this function 313 * uses recursion to authenticate the parent images up to the root of trust. 314 ******************************************************************************/ 315 int load_auth_image(meminfo_t *mem_layout, 316 unsigned int image_id, 317 uintptr_t image_base, 318 image_info_t *image_data, 319 entry_point_info_t *entry_point_info) 320 { 321 int rc; 322 323 #if TRUSTED_BOARD_BOOT 324 unsigned int parent_id; 325 326 /* Use recursion to authenticate parent images */ 327 rc = auth_mod_get_parent_id(image_id, &parent_id); 328 if (rc == 0) { 329 rc = load_auth_image(mem_layout, parent_id, image_base, 330 image_data, NULL); 331 if (rc != 0) { 332 return rc; 333 } 334 } 335 #endif /* TRUSTED_BOARD_BOOT */ 336 337 /* Load the image */ 338 rc = load_image(mem_layout, image_id, image_base, image_data, 339 entry_point_info); 340 if (rc != 0) { 341 return rc; 342 } 343 344 #if TRUSTED_BOARD_BOOT 345 /* Authenticate it */ 346 rc = auth_mod_verify_img(image_id, 347 (void *)image_data->image_base, 348 image_data->image_size); 349 if (rc != 0) { 350 memset((void *)image_data->image_base, 0x00, 351 image_data->image_size); 352 flush_dcache_range(image_data->image_base, 353 image_data->image_size); 354 return -EAUTH; 355 } 356 357 /* After working with data, invalidate the data cache */ 358 inv_dcache_range(image_data->image_base, 359 (size_t)image_data->image_size); 360 #endif /* TRUSTED_BOARD_BOOT */ 361 362 return 0; 363 } 364 365 /******************************************************************************* 366 * Print the content of an entry_point_info_t structure. 367 ******************************************************************************/ 368 void print_entry_point_info(const entry_point_info_t *ep_info) 369 { 370 INFO("Entry point address = 0x%llx\n", 371 (unsigned long long) ep_info->pc); 372 INFO("SPSR = 0x%lx\n", (unsigned long) ep_info->spsr); 373 374 #define PRINT_IMAGE_ARG(n) \ 375 VERBOSE("Argument #" #n " = 0x%llx\n", \ 376 (unsigned long long) ep_info->args.arg##n) 377 378 PRINT_IMAGE_ARG(0); 379 PRINT_IMAGE_ARG(1); 380 PRINT_IMAGE_ARG(2); 381 PRINT_IMAGE_ARG(3); 382 PRINT_IMAGE_ARG(4); 383 PRINT_IMAGE_ARG(5); 384 PRINT_IMAGE_ARG(6); 385 PRINT_IMAGE_ARG(7); 386 #undef PRINT_IMAGE_ARG 387 } 388