1 /* 2 * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <arch_helpers.h> 9 #include <auth_mod.h> 10 #include <bl1.h> 11 #include <bl_common.h> 12 #include <context.h> 13 #include <context_mgmt.h> 14 #include <debug.h> 15 #include <errno.h> 16 #include <platform.h> 17 #include <platform_def.h> 18 #include <smcc_helpers.h> 19 #include <string.h> 20 #include <utils.h> 21 #include "bl1_private.h" 22 23 /* 24 * Function declarations. 25 */ 26 static int bl1_fwu_image_copy(unsigned int image_id, 27 uintptr_t image_addr, 28 unsigned int block_size, 29 unsigned int image_size, 30 unsigned int flags); 31 static int bl1_fwu_image_auth(unsigned int image_id, 32 uintptr_t image_addr, 33 unsigned int image_size, 34 unsigned int flags); 35 static int bl1_fwu_image_execute(unsigned int image_id, 36 void **handle, 37 unsigned int flags); 38 static register_t bl1_fwu_image_resume(register_t image_param, 39 void **handle, 40 unsigned int flags); 41 static int bl1_fwu_sec_image_done(void **handle, 42 unsigned int flags); 43 __dead2 static void bl1_fwu_done(void *client_cookie, void *reserved); 44 45 /* 46 * This keeps track of last executed secure image id. 47 */ 48 static unsigned int sec_exec_image_id = INVALID_IMAGE_ID; 49 50 /******************************************************************************* 51 * Top level handler for servicing FWU SMCs. 52 ******************************************************************************/ 53 register_t bl1_fwu_smc_handler(unsigned int smc_fid, 54 register_t x1, 55 register_t x2, 56 register_t x3, 57 register_t x4, 58 void *cookie, 59 void *handle, 60 unsigned int flags) 61 { 62 63 switch (smc_fid) { 64 case FWU_SMC_IMAGE_COPY: 65 SMC_RET1(handle, bl1_fwu_image_copy(x1, x2, x3, x4, flags)); 66 67 case FWU_SMC_IMAGE_AUTH: 68 SMC_RET1(handle, bl1_fwu_image_auth(x1, x2, x3, flags)); 69 70 case FWU_SMC_IMAGE_EXECUTE: 71 SMC_RET1(handle, bl1_fwu_image_execute(x1, &handle, flags)); 72 73 case FWU_SMC_IMAGE_RESUME: 74 SMC_RET1(handle, bl1_fwu_image_resume(x1, &handle, flags)); 75 76 case FWU_SMC_SEC_IMAGE_DONE: 77 SMC_RET1(handle, bl1_fwu_sec_image_done(&handle, flags)); 78 79 case FWU_SMC_UPDATE_DONE: 80 bl1_fwu_done((void *)x1, NULL); 81 /* We should never return from bl1_fwu_done() */ 82 83 default: 84 assert(0); 85 break; 86 } 87 88 SMC_RET1(handle, SMC_UNK); 89 } 90 91 /******************************************************************************* 92 * This function is responsible for copying secure images in AP Secure RAM. 93 ******************************************************************************/ 94 static int bl1_fwu_image_copy(unsigned int image_id, 95 uintptr_t image_src, 96 unsigned int block_size, 97 unsigned int image_size, 98 unsigned int flags) 99 { 100 uintptr_t dest_addr; 101 unsigned int remaining; 102 103 /* Get the image descriptor. */ 104 image_desc_t *image_desc = bl1_plat_get_image_desc(image_id); 105 if (!image_desc) { 106 WARN("BL1-FWU: Invalid image ID %u\n", image_id); 107 return -EPERM; 108 } 109 110 /* 111 * The request must originate from a non-secure caller and target a 112 * secure image. Any other scenario is invalid. 113 */ 114 if (GET_SECURITY_STATE(flags) == SECURE) { 115 WARN("BL1-FWU: Copy not allowed from secure world.\n"); 116 return -EPERM; 117 } 118 if (GET_SECURITY_STATE(image_desc->ep_info.h.attr) == NON_SECURE) { 119 WARN("BL1-FWU: Copy not allowed for non-secure images.\n"); 120 return -EPERM; 121 } 122 123 /* Check whether the FWU state machine is in the correct state. */ 124 if ((image_desc->state != IMAGE_STATE_RESET) && 125 (image_desc->state != IMAGE_STATE_COPYING)) { 126 WARN("BL1-FWU: Copy not allowed at this point of the FWU" 127 " process.\n"); 128 return -EPERM; 129 } 130 131 if ((!image_src) || (!block_size) || 132 check_uptr_overflow(image_src, block_size - 1)) { 133 WARN("BL1-FWU: Copy not allowed due to invalid image source" 134 " or block size\n"); 135 return -ENOMEM; 136 } 137 138 if (image_desc->state == IMAGE_STATE_COPYING) { 139 /* 140 * There must have been at least 1 copy operation for this image 141 * previously. 142 */ 143 assert(image_desc->copied_size != 0); 144 /* 145 * The image size must have been recorded in the 1st copy 146 * operation. 147 */ 148 image_size = image_desc->image_info.image_size; 149 assert(image_size != 0); 150 assert(image_desc->copied_size < image_size); 151 152 INFO("BL1-FWU: Continuing image copy in blocks\n"); 153 } else { /* image_desc->state == IMAGE_STATE_RESET */ 154 INFO("BL1-FWU: Initial call to copy an image\n"); 155 156 /* 157 * image_size is relevant only for the 1st copy request, it is 158 * then ignored for subsequent calls for this image. 159 */ 160 if (!image_size) { 161 WARN("BL1-FWU: Copy not allowed due to invalid image" 162 " size\n"); 163 return -ENOMEM; 164 } 165 166 #if LOAD_IMAGE_V2 167 /* Check that the image size to load is within limit */ 168 if (image_size > image_desc->image_info.image_max_size) { 169 WARN("BL1-FWU: Image size out of bounds\n"); 170 return -ENOMEM; 171 } 172 #else 173 /* 174 * Check the image will fit into the free trusted RAM after BL1 175 * load. 176 */ 177 const meminfo_t *mem_layout = bl1_plat_sec_mem_layout(); 178 if (!is_mem_free(mem_layout->free_base, mem_layout->free_size, 179 image_desc->image_info.image_base, 180 image_size)) { 181 WARN("BL1-FWU: Copy not allowed due to insufficient" 182 " resources.\n"); 183 return -ENOMEM; 184 } 185 #endif 186 187 /* Save the given image size. */ 188 image_desc->image_info.image_size = image_size; 189 190 /* 191 * copied_size must be explicitly initialized here because the 192 * FWU code doesn't necessarily do it when it resets the state 193 * machine. 194 */ 195 image_desc->copied_size = 0; 196 } 197 198 /* 199 * If the given block size is more than the total image size 200 * then clip the former to the latter. 201 */ 202 remaining = image_size - image_desc->copied_size; 203 if (block_size > remaining) { 204 WARN("BL1-FWU: Block size is too big, clipping it.\n"); 205 block_size = remaining; 206 } 207 208 /* Make sure the source image is mapped in memory. */ 209 if (bl1_plat_mem_check(image_src, block_size, flags)) { 210 WARN("BL1-FWU: Source image is not mapped.\n"); 211 return -ENOMEM; 212 } 213 214 /* Everything looks sane. Go ahead and copy the block of data. */ 215 dest_addr = image_desc->image_info.image_base + image_desc->copied_size; 216 memcpy((void *) dest_addr, (const void *) image_src, block_size); 217 flush_dcache_range(dest_addr, block_size); 218 219 image_desc->copied_size += block_size; 220 image_desc->state = (block_size == remaining) ? 221 IMAGE_STATE_COPIED : IMAGE_STATE_COPYING; 222 223 INFO("BL1-FWU: Copy operation successful.\n"); 224 return 0; 225 } 226 227 /******************************************************************************* 228 * This function is responsible for authenticating Normal/Secure images. 229 ******************************************************************************/ 230 static int bl1_fwu_image_auth(unsigned int image_id, 231 uintptr_t image_src, 232 unsigned int image_size, 233 unsigned int flags) 234 { 235 int result; 236 uintptr_t base_addr; 237 unsigned int total_size; 238 239 /* Get the image descriptor. */ 240 image_desc_t *image_desc = bl1_plat_get_image_desc(image_id); 241 if (!image_desc) 242 return -EPERM; 243 244 if (GET_SECURITY_STATE(flags) == SECURE) { 245 if (image_desc->state != IMAGE_STATE_RESET) { 246 WARN("BL1-FWU: Authentication from secure world " 247 "while in invalid state\n"); 248 return -EPERM; 249 } 250 } else { 251 if (GET_SECURITY_STATE(image_desc->ep_info.h.attr) == SECURE) { 252 if (image_desc->state != IMAGE_STATE_COPIED) { 253 WARN("BL1-FWU: Authentication of secure image " 254 "from non-secure world while not in copied state\n"); 255 return -EPERM; 256 } 257 } else { 258 if (image_desc->state != IMAGE_STATE_RESET) { 259 WARN("BL1-FWU: Authentication of non-secure image " 260 "from non-secure world while in invalid state\n"); 261 return -EPERM; 262 } 263 } 264 } 265 266 if (image_desc->state == IMAGE_STATE_COPIED) { 267 /* 268 * Image is in COPIED state. 269 * Use the stored address and size. 270 */ 271 base_addr = image_desc->image_info.image_base; 272 total_size = image_desc->image_info.image_size; 273 } else { 274 if ((!image_src) || (!image_size) || 275 check_uptr_overflow(image_src, image_size - 1)) { 276 WARN("BL1-FWU: Auth not allowed due to invalid" 277 " image source/size\n"); 278 return -ENOMEM; 279 } 280 281 /* 282 * Image is in RESET state. 283 * Check the parameters and authenticate the source image in place. 284 */ 285 if (bl1_plat_mem_check(image_src, image_size, \ 286 image_desc->ep_info.h.attr)) { 287 WARN("BL1-FWU: Authentication arguments source/size not mapped\n"); 288 return -ENOMEM; 289 } 290 291 base_addr = image_src; 292 total_size = image_size; 293 294 /* Update the image size in the descriptor. */ 295 image_desc->image_info.image_size = total_size; 296 } 297 298 /* 299 * Authenticate the image. 300 */ 301 INFO("BL1-FWU: Authenticating image_id:%d\n", image_id); 302 result = auth_mod_verify_img(image_id, (void *)base_addr, total_size); 303 if (result != 0) { 304 WARN("BL1-FWU: Authentication Failed err=%d\n", result); 305 306 /* 307 * Authentication has failed. 308 * Clear the memory if the image was copied. 309 * This is to prevent an attack where this contains 310 * some malicious code that can somehow be executed later. 311 */ 312 if (image_desc->state == IMAGE_STATE_COPIED) { 313 /* Clear the memory.*/ 314 zero_normalmem((void *)base_addr, total_size); 315 flush_dcache_range(base_addr, total_size); 316 317 /* Indicate that image can be copied again*/ 318 image_desc->state = IMAGE_STATE_RESET; 319 } 320 return -EAUTH; 321 } 322 323 /* Indicate that image is in authenticated state. */ 324 image_desc->state = IMAGE_STATE_AUTHENTICATED; 325 326 /* 327 * Flush image_info to memory so that other 328 * secure world images can see changes. 329 */ 330 flush_dcache_range((unsigned long)&image_desc->image_info, 331 sizeof(image_info_t)); 332 333 INFO("BL1-FWU: Authentication was successful\n"); 334 335 return 0; 336 } 337 338 /******************************************************************************* 339 * This function is responsible for executing Secure images. 340 ******************************************************************************/ 341 static int bl1_fwu_image_execute(unsigned int image_id, 342 void **handle, 343 unsigned int flags) 344 { 345 /* Get the image descriptor. */ 346 image_desc_t *image_desc = bl1_plat_get_image_desc(image_id); 347 348 /* 349 * Execution is NOT allowed if: 350 * image_id is invalid OR 351 * Caller is from Secure world OR 352 * Image is Non-Secure OR 353 * Image is Non-Executable OR 354 * Image is NOT in AUTHENTICATED state. 355 */ 356 if ((!image_desc) || 357 (GET_SECURITY_STATE(flags) == SECURE) || 358 (GET_SECURITY_STATE(image_desc->ep_info.h.attr) == NON_SECURE) || 359 (EP_GET_EXE(image_desc->ep_info.h.attr) == NON_EXECUTABLE) || 360 (image_desc->state != IMAGE_STATE_AUTHENTICATED)) { 361 WARN("BL1-FWU: Execution not allowed due to invalid state/args\n"); 362 return -EPERM; 363 } 364 365 INFO("BL1-FWU: Executing Secure image\n"); 366 367 /* Save NS-EL1 system registers. */ 368 cm_el1_sysregs_context_save(NON_SECURE); 369 370 /* Prepare the image for execution. */ 371 bl1_prepare_next_image(image_id); 372 373 /* Update the secure image id. */ 374 sec_exec_image_id = image_id; 375 376 *handle = cm_get_context(SECURE); 377 return 0; 378 } 379 380 /******************************************************************************* 381 * This function is responsible for resuming execution in the other security 382 * world 383 ******************************************************************************/ 384 static register_t bl1_fwu_image_resume(register_t image_param, 385 void **handle, 386 unsigned int flags) 387 { 388 image_desc_t *image_desc; 389 unsigned int resume_sec_state; 390 unsigned int caller_sec_state = GET_SECURITY_STATE(flags); 391 392 /* Get the image descriptor for last executed secure image id. */ 393 image_desc = bl1_plat_get_image_desc(sec_exec_image_id); 394 if (caller_sec_state == NON_SECURE) { 395 if (!image_desc) { 396 WARN("BL1-FWU: Resume not allowed due to no available" 397 "secure image\n"); 398 return -EPERM; 399 } 400 } else { 401 /* image_desc must be valid for secure world callers */ 402 assert(image_desc); 403 } 404 405 assert(GET_SECURITY_STATE(image_desc->ep_info.h.attr) == SECURE); 406 assert(EP_GET_EXE(image_desc->ep_info.h.attr) == EXECUTABLE); 407 408 if (caller_sec_state == SECURE) { 409 assert(image_desc->state == IMAGE_STATE_EXECUTED); 410 411 /* Update the flags. */ 412 image_desc->state = IMAGE_STATE_INTERRUPTED; 413 resume_sec_state = NON_SECURE; 414 } else { 415 assert(image_desc->state == IMAGE_STATE_INTERRUPTED); 416 417 /* Update the flags. */ 418 image_desc->state = IMAGE_STATE_EXECUTED; 419 resume_sec_state = SECURE; 420 } 421 422 /* Save the EL1 system registers of calling world. */ 423 cm_el1_sysregs_context_save(caller_sec_state); 424 425 /* Restore the EL1 system registers of resuming world. */ 426 cm_el1_sysregs_context_restore(resume_sec_state); 427 428 /* Update the next context. */ 429 cm_set_next_eret_context(resume_sec_state); 430 431 INFO("BL1-FWU: Resuming %s world context\n", 432 (resume_sec_state == SECURE) ? "secure" : "normal"); 433 434 *handle = cm_get_context(resume_sec_state); 435 return image_param; 436 } 437 438 /******************************************************************************* 439 * This function is responsible for resuming normal world context. 440 ******************************************************************************/ 441 static int bl1_fwu_sec_image_done(void **handle, unsigned int flags) 442 { 443 image_desc_t *image_desc; 444 445 /* Make sure caller is from the secure world */ 446 if (GET_SECURITY_STATE(flags) == NON_SECURE) { 447 WARN("BL1-FWU: Image done not allowed from normal world\n"); 448 return -EPERM; 449 } 450 451 /* Get the image descriptor for last executed secure image id */ 452 image_desc = bl1_plat_get_image_desc(sec_exec_image_id); 453 454 /* image_desc must correspond to a valid secure executing image */ 455 assert(image_desc); 456 assert(GET_SECURITY_STATE(image_desc->ep_info.h.attr) == SECURE); 457 assert(EP_GET_EXE(image_desc->ep_info.h.attr) == EXECUTABLE); 458 assert(image_desc->state == IMAGE_STATE_EXECUTED); 459 460 /* Update the flags. */ 461 image_desc->state = IMAGE_STATE_RESET; 462 sec_exec_image_id = INVALID_IMAGE_ID; 463 464 /* 465 * Secure world is done so no need to save the context. 466 * Just restore the Non-Secure context. 467 */ 468 cm_el1_sysregs_context_restore(NON_SECURE); 469 470 /* Update the next context. */ 471 cm_set_next_eret_context(NON_SECURE); 472 473 INFO("BL1-FWU: Resuming Normal world context\n"); 474 475 *handle = cm_get_context(NON_SECURE); 476 return 0; 477 } 478 479 /******************************************************************************* 480 * This function provides the opportunity for users to perform any 481 * platform specific handling after the Firmware update is done. 482 ******************************************************************************/ 483 __dead2 static void bl1_fwu_done(void *client_cookie, void *reserved) 484 { 485 NOTICE("BL1-FWU: *******FWU Process Completed*******\n"); 486 487 /* 488 * Call platform done function. 489 */ 490 bl1_plat_fwu_done(client_cookie, reserved); 491 assert(0); 492 } 493