1 /* 2 * Copyright (c) 2013-2026, Arm Limited and Contributors. All rights reserved. 3 * Copyright (c) 2021-2025, Renesas Electronics Corporation. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #include <assert.h> 9 #include <errno.h> 10 #include <string.h> 11 12 #include <arch.h> 13 #include <arch_features.h> 14 #include <arch_helpers.h> 15 #include <common/bl_common.h> 16 #include <common/build_message.h> 17 #include <common/debug.h> 18 #include <drivers/auth/auth_mod.h> 19 #include <drivers/io/io_storage.h> 20 #include <lib/utils.h> 21 #include <lib/xlat_tables/xlat_tables_defs.h> 22 #include <plat/common/platform.h> 23 24 #if TRUSTED_BOARD_BOOT 25 # ifdef DYN_DISABLE_AUTH 26 static int disable_auth; 27 28 /****************************************************************************** 29 * API to dynamically disable authentication. Only meant for development 30 * systems. This is only invoked if DYN_DISABLE_AUTH is defined. 31 *****************************************************************************/ 32 void dyn_disable_auth(void) 33 { 34 INFO("Disabling authentication of images dynamically\n"); 35 disable_auth = 1; 36 } 37 # endif /* DYN_DISABLE_AUTH */ 38 39 /****************************************************************************** 40 * Function to determine whether the authentication is disabled dynamically. 41 *****************************************************************************/ 42 static int dyn_is_auth_disabled(void) 43 { 44 # ifdef DYN_DISABLE_AUTH 45 return disable_auth; 46 # else 47 return 0; 48 # endif 49 } 50 #endif /* TRUSTED_BOARD_BOOT */ 51 52 uintptr_t page_align(uintptr_t value, unsigned dir) 53 { 54 /* Round up the limit to the next page boundary */ 55 if ((value & PAGE_SIZE_MASK) != 0U) { 56 value &= ~PAGE_SIZE_MASK; 57 if (dir == UP) { 58 value += PAGE_SIZE; 59 } 60 } 61 62 return value; 63 } 64 65 /******************************************************************************* 66 * Internal function to load an image at a specific address given 67 * an image ID and extents of free memory. 68 * 69 * If the load is successful then the image information is updated. 70 * 71 * Returns 0 on success, a negative error code otherwise. 72 ******************************************************************************/ 73 static int load_image(unsigned int image_id, image_info_t *image_data) 74 { 75 uintptr_t dev_handle = 0ULL; 76 uintptr_t image_handle = 0ULL; 77 uintptr_t image_spec = 0ULL; 78 uintptr_t image_base; 79 size_t image_size = 0ULL; 80 size_t bytes_read = 0ULL; 81 int io_result; 82 83 assert(image_data != NULL); 84 assert(image_data->h.version >= VERSION_2); 85 86 image_base = image_data->image_base; 87 88 /* Obtain a reference to the image by querying the platform layer */ 89 io_result = plat_get_image_source(image_id, &dev_handle, &image_spec); 90 if (io_result != 0) { 91 WARN("Failed to obtain reference to image id=%u (%i)\n", 92 image_id, io_result); 93 return io_result; 94 } 95 96 /* Attempt to access the image */ 97 io_result = io_open(dev_handle, image_spec, &image_handle); 98 if (io_result != 0) { 99 WARN("Failed to access image id=%u (%i)\n", 100 image_id, io_result); 101 return io_result; 102 } 103 104 INFO("Loading image id=%u at address 0x%lx\n", image_id, image_base); 105 106 /* Find the size of the image */ 107 io_result = io_size(image_handle, &image_size); 108 if (io_result != 0) { 109 WARN("Failed to determine the size of the image id=%u (%i)\n", 110 image_id, io_result); 111 goto exit_load_image; 112 } 113 114 if (image_size == 0U) { 115 WARN("image id=%u size is zero\n", image_id); 116 io_result = -EIO; 117 goto exit_load_image; 118 } 119 120 /* Check that the image size to load is within limit */ 121 if (image_size > image_data->image_max_size) { 122 WARN("Image id=%u size out of bounds\n", image_id); 123 io_result = -EFBIG; 124 goto exit_load_image; 125 } 126 127 /* 128 * image_data->image_max_size is a uint32_t so image_size will always 129 * fit in image_data->image_size. 130 */ 131 image_data->image_size = (uint32_t)image_size; 132 133 /* We have enough space so load the image now */ 134 io_result = io_read(image_handle, image_base, image_size, &bytes_read); 135 if (io_result != 0) { 136 WARN("Failed to load image id=%u (%i)\n", image_id, io_result); 137 goto exit_load_image; 138 } 139 140 /* 141 * For testing purposes only. Simulate a short read to hit the partial 142 * read error handling path. 143 */ 144 #if TEST_IO_SHORT_READ_FI 145 if (image_id == TEST_IO_SHORT_READ_FI_IMAGE_ID) { 146 INFO("Artificially shorten read operation for image_id=%u bytes\n", 147 TEST_IO_SHORT_READ_FI_IMAGE_ID); 148 bytes_read = image_size - 1U; 149 } 150 #endif 151 152 /* TODO: Consider whether to try to recover/retry a partially successful read */ 153 if (bytes_read < image_size) { 154 WARN("Image id=%u read too short (%zu of %zu Bytes)\n", 155 image_id, bytes_read, image_size); 156 io_result = -EIO; 157 goto exit_load_image; 158 } 159 160 INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base, 161 (uintptr_t)(image_base + image_size)); 162 163 exit_load_image: 164 (void)io_close(image_handle); 165 /* Ignore improbable/unrecoverable error in 'close' */ 166 167 /* TODO: Consider maintaining open device connection from this bootloader stage */ 168 (void)io_dev_close(dev_handle); 169 /* Ignore improbable/unrecoverable error in 'dev_close' */ 170 171 return io_result; 172 } 173 174 #if TRUSTED_BOARD_BOOT 175 /* 176 * This function uses recursion to authenticate the parent images up to the root 177 * of trust. 178 */ 179 static int load_auth_image_recursive(unsigned int image_id, 180 image_info_t *image_data) 181 { 182 int rc; 183 unsigned int parent_id; 184 185 /* Use recursion to authenticate parent images */ 186 rc = auth_mod_get_parent_id(image_id, &parent_id); 187 if (rc == 0) { 188 rc = load_auth_image_recursive(parent_id, image_data); 189 if (rc != 0) { 190 return rc; 191 } 192 } 193 194 /* Load the image */ 195 rc = load_image(image_id, image_data); 196 if (rc != 0) { 197 return rc; 198 } 199 200 /* Authenticate it */ 201 rc = auth_mod_verify_img(image_id, 202 (void *)image_data->image_base, 203 image_data->image_size); 204 if (rc != 0) { 205 /* Authentication error, zero memory and flush it right away. */ 206 zero_normalmem((void *)image_data->image_base, 207 image_data->image_size); 208 flush_dcache_range(image_data->image_base, 209 image_data->image_size); 210 return -EAUTH; 211 } 212 213 return 0; 214 } 215 #endif /* TRUSTED_BOARD_BOOT */ 216 217 static int load_auth_image_internal(unsigned int image_id, 218 image_info_t *image_data) 219 { 220 #if TRUSTED_BOARD_BOOT 221 if (dyn_is_auth_disabled() == 0) { 222 return load_auth_image_recursive(image_id, image_data); 223 } 224 #endif 225 226 return load_image(image_id, image_data); 227 } 228 229 /******************************************************************************* 230 * Generic function to load and authenticate an image. The image is actually 231 * loaded by calling the 'load_image()' function. Therefore, it returns the 232 * same error codes if the loading operation failed, or -EAUTH if the 233 * authentication failed. In addition, this function uses recursion to 234 * authenticate the parent images up to the root of trust (if TBB is enabled). 235 ******************************************************************************/ 236 int load_auth_image(unsigned int image_id, image_info_t *image_data) 237 { 238 int err; 239 240 if ((plat_try_img_ops == NULL) || (plat_try_img_ops->next_instance == NULL)) { 241 err = load_auth_image_internal(image_id, image_data); 242 } else { 243 do { 244 err = load_auth_image_internal(image_id, image_data); 245 if (err != 0) { 246 if (plat_try_img_ops->next_instance(image_id) != 0) { 247 return err; 248 } 249 } 250 } while (err != 0); 251 } 252 253 if (err == 0) { 254 /* 255 * If loading of the image gets passed (along with its 256 * authentication in case of Trusted-Boot flow) then measure 257 * it (if MEASURED_BOOT flag is enabled). 258 */ 259 err = plat_mboot_measure_image(image_id, image_data); 260 if (err != 0) { 261 return err; 262 } 263 264 /* 265 * Flush the image to main memory so that it can be executed 266 * later by any CPU, regardless of cache and MMU state. 267 */ 268 flush_dcache_range(image_data->image_base, 269 image_data->image_size); 270 } 271 272 return err; 273 } 274 275 /******************************************************************************* 276 * Print the content of an entry_point_info_t structure. 277 ******************************************************************************/ 278 void print_entry_point_info(const entry_point_info_t *ep_info) 279 { 280 INFO("Entry point address = 0x%lx\n", ep_info->pc); 281 INFO("SPSR = 0x%x\n", ep_info->spsr); 282 283 #define PRINT_IMAGE_ARG(n) \ 284 VERBOSE("Argument #" #n " = 0x%llx\n", \ 285 (unsigned long long) ep_info->args.arg##n) 286 287 PRINT_IMAGE_ARG(0); 288 PRINT_IMAGE_ARG(1); 289 PRINT_IMAGE_ARG(2); 290 PRINT_IMAGE_ARG(3); 291 #ifdef __aarch64__ 292 PRINT_IMAGE_ARG(4); 293 PRINT_IMAGE_ARG(5); 294 PRINT_IMAGE_ARG(6); 295 PRINT_IMAGE_ARG(7); 296 #endif 297 #undef PRINT_IMAGE_ARG 298 } 299 300 /* 301 * This function is for returning the TF-A version 302 */ 303 const char *get_version(void) 304 { 305 return build_version; 306 } 307