1 /* 2 * Copyright (c) 2013-2024, 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/build_message.h> 16 #include <common/debug.h> 17 #include <drivers/auth/auth_mod.h> 18 #include <drivers/io/io_storage.h> 19 #include <lib/utils.h> 20 #include <lib/xlat_tables/xlat_tables_defs.h> 21 #include <plat/common/platform.h> 22 23 #if TRUSTED_BOARD_BOOT 24 # ifdef DYN_DISABLE_AUTH 25 static int disable_auth; 26 27 /****************************************************************************** 28 * API to dynamically disable authentication. Only meant for development 29 * systems. This is only invoked if DYN_DISABLE_AUTH is defined. 30 *****************************************************************************/ 31 void dyn_disable_auth(void) 32 { 33 INFO("Disabling authentication of images dynamically\n"); 34 disable_auth = 1; 35 } 36 # endif /* DYN_DISABLE_AUTH */ 37 38 /****************************************************************************** 39 * Function to determine whether the authentication is disabled dynamically. 40 *****************************************************************************/ 41 static int dyn_is_auth_disabled(void) 42 { 43 # ifdef DYN_DISABLE_AUTH 44 return disable_auth; 45 # else 46 return 0; 47 # endif 48 } 49 #endif /* TRUSTED_BOARD_BOOT */ 50 51 uintptr_t page_align(uintptr_t value, unsigned dir) 52 { 53 /* Round up the limit to the next page boundary */ 54 if ((value & PAGE_SIZE_MASK) != 0U) { 55 value &= ~PAGE_SIZE_MASK; 56 if (dir == UP) { 57 value += PAGE_SIZE; 58 } 59 } 60 61 return value; 62 } 63 64 /******************************************************************************* 65 * Internal function to load an image at a specific address given 66 * an image ID and extents of free memory. 67 * 68 * If the load is successful then the image information is updated. 69 * 70 * Returns 0 on success, a negative error code otherwise. 71 ******************************************************************************/ 72 static int load_image(unsigned int image_id, image_info_t *image_data) 73 { 74 uintptr_t dev_handle = 0ULL; 75 uintptr_t image_handle = 0ULL; 76 uintptr_t image_spec = 0ULL; 77 uintptr_t image_base; 78 size_t image_size = 0ULL; 79 size_t bytes_read = 0ULL; 80 int io_result; 81 82 assert(image_data != NULL); 83 assert(image_data->h.version >= VERSION_2); 84 85 image_base = image_data->image_base; 86 87 /* Obtain a reference to the image by querying the platform layer */ 88 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec); 89 if (io_result != 0) { 90 WARN("Failed to obtain reference to image id=%u (%i)\n", 91 image_id, io_result); 92 return io_result; 93 } 94 95 /* Attempt to access the image */ 96 io_result = io_open(dev_handle, image_spec, &image_handle); 97 if (io_result != 0) { 98 WARN("Failed to access image id=%u (%i)\n", 99 image_id, io_result); 100 return io_result; 101 } 102 103 INFO("Loading image id=%u at address 0x%lx\n", image_id, image_base); 104 105 /* Find the size of the image */ 106 io_result = io_size(image_handle, &image_size); 107 if ((io_result != 0) || (image_size == 0U)) { 108 WARN("Failed to determine the size of the image id=%u (%i)\n", 109 image_id, io_result); 110 goto exit_load_image; 111 } 112 113 /* Check that the image size to load is within limit */ 114 if (image_size > image_data->image_max_size) { 115 WARN("Image id=%u size out of bounds\n", image_id); 116 io_result = -EFBIG; 117 goto exit_load_image; 118 } 119 120 /* 121 * image_data->image_max_size is a uint32_t so image_size will always 122 * fit in image_data->image_size. 123 */ 124 image_data->image_size = (uint32_t)image_size; 125 126 /* We have enough space so load the image now */ 127 /* TODO: Consider whether to try to recover/retry a partially successful read */ 128 io_result = io_read(image_handle, image_base, image_size, &bytes_read); 129 if ((io_result != 0) || (bytes_read < image_size)) { 130 WARN("Failed to load image id=%u (%i)\n", image_id, io_result); 131 goto exit_load_image; 132 } 133 134 INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base, 135 (uintptr_t)(image_base + image_size)); 136 137 exit_load_image: 138 (void)io_close(image_handle); 139 /* Ignore improbable/unrecoverable error in 'close' */ 140 141 /* TODO: Consider maintaining open device connection from this bootloader stage */ 142 (void)io_dev_close(dev_handle); 143 /* Ignore improbable/unrecoverable error in 'dev_close' */ 144 145 return io_result; 146 } 147 148 #if TRUSTED_BOARD_BOOT 149 /* 150 * This function uses recursion to authenticate the parent images up to the root 151 * of trust. 152 */ 153 static int load_auth_image_recursive(unsigned int image_id, 154 image_info_t *image_data) 155 { 156 int rc; 157 unsigned int parent_id; 158 159 /* Use recursion to authenticate parent images */ 160 rc = auth_mod_get_parent_id(image_id, &parent_id); 161 if (rc == 0) { 162 rc = load_auth_image_recursive(parent_id, image_data); 163 if (rc != 0) { 164 return rc; 165 } 166 } 167 168 /* Load the image */ 169 rc = load_image(image_id, image_data); 170 if (rc != 0) { 171 return rc; 172 } 173 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 return 0; 188 } 189 #endif /* TRUSTED_BOARD_BOOT */ 190 191 static int load_auth_image_internal(unsigned int image_id, 192 image_info_t *image_data) 193 { 194 #if TRUSTED_BOARD_BOOT 195 if (dyn_is_auth_disabled() == 0) { 196 return load_auth_image_recursive(image_id, image_data); 197 } 198 #endif 199 200 return load_image(image_id, image_data); 201 } 202 203 /******************************************************************************* 204 * Generic function to load and authenticate an image. The image is actually 205 * loaded by calling the 'load_image()' function. Therefore, it returns the 206 * same error codes if the loading operation failed, or -EAUTH if the 207 * authentication failed. In addition, this function uses recursion to 208 * authenticate the parent images up to the root of trust (if TBB is enabled). 209 ******************************************************************************/ 210 int load_auth_image(unsigned int image_id, image_info_t *image_data) 211 { 212 int err; 213 214 if ((plat_try_img_ops == NULL) || (plat_try_img_ops->next_instance == NULL)) { 215 err = load_auth_image_internal(image_id, image_data); 216 } else { 217 do { 218 err = load_auth_image_internal(image_id, image_data); 219 if (err != 0) { 220 if (plat_try_img_ops->next_instance(image_id) != 0) { 221 return err; 222 } 223 } 224 } while (err != 0); 225 } 226 227 if (err == 0) { 228 /* 229 * If loading of the image gets passed (along with its 230 * authentication in case of Trusted-Boot flow) then measure 231 * it (if MEASURED_BOOT flag is enabled). 232 */ 233 err = plat_mboot_measure_image(image_id, image_data); 234 if (err != 0) { 235 return err; 236 } 237 238 /* 239 * Flush the image to main memory so that it can be executed 240 * later by any CPU, regardless of cache and MMU state. 241 */ 242 flush_dcache_range(image_data->image_base, 243 image_data->image_size); 244 } 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 274 /* 275 * This function is for returning the TF-A version 276 */ 277 const char *get_version(void) 278 { 279 return build_version; 280 } 281