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