1 /* 2 * Copyright (c) 2015-2018, 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 <platform_def.h> 12 13 #include <arch_helpers.h> 14 #include <bl1/bl1.h> 15 #include <common/bl_common.h> 16 #include <common/debug.h> 17 #include <context.h> 18 #include <drivers/auth/auth_mod.h> 19 #include <lib/el3_runtime/context_mgmt.h> 20 #include <lib/utils.h> 21 #include <plat/common/platform.h> 22 #include <smccc_helpers.h> 23 24 #include "bl1_private.h" 25 26 /* 27 * Function declarations. 28 */ 29 static int bl1_fwu_image_copy(unsigned int image_id, 30 uintptr_t image_src, 31 unsigned int block_size, 32 unsigned int image_size, 33 unsigned int flags); 34 static int bl1_fwu_image_auth(unsigned int image_id, 35 uintptr_t image_src, 36 unsigned int image_size, 37 unsigned int flags); 38 static int bl1_fwu_image_execute(unsigned int image_id, 39 void **handle, 40 unsigned int flags); 41 static register_t bl1_fwu_image_resume(register_t image_param, 42 void **handle, 43 unsigned int flags); 44 static int bl1_fwu_sec_image_done(void **handle, 45 unsigned int flags); 46 static int bl1_fwu_image_reset(unsigned int image_id, 47 unsigned int flags); 48 __dead2 static void bl1_fwu_done(void *client_cookie, void *reserved); 49 50 /* 51 * This keeps track of last executed secure image id. 52 */ 53 static unsigned int sec_exec_image_id = INVALID_IMAGE_ID; 54 55 /* Authentication status of each image. */ 56 extern unsigned int auth_img_flags[MAX_NUMBER_IDS]; 57 58 /******************************************************************************* 59 * Top level handler for servicing FWU SMCs. 60 ******************************************************************************/ 61 register_t bl1_fwu_smc_handler(unsigned int smc_fid, 62 register_t x1, 63 register_t x2, 64 register_t x3, 65 register_t x4, 66 void *cookie, 67 void *handle, 68 unsigned int flags) 69 { 70 71 switch (smc_fid) { 72 case FWU_SMC_IMAGE_COPY: 73 SMC_RET1(handle, bl1_fwu_image_copy(x1, x2, x3, x4, flags)); 74 75 case FWU_SMC_IMAGE_AUTH: 76 SMC_RET1(handle, bl1_fwu_image_auth(x1, x2, x3, flags)); 77 78 case FWU_SMC_IMAGE_EXECUTE: 79 SMC_RET1(handle, bl1_fwu_image_execute(x1, &handle, flags)); 80 81 case FWU_SMC_IMAGE_RESUME: 82 SMC_RET1(handle, bl1_fwu_image_resume(x1, &handle, flags)); 83 84 case FWU_SMC_SEC_IMAGE_DONE: 85 SMC_RET1(handle, bl1_fwu_sec_image_done(&handle, flags)); 86 87 case FWU_SMC_IMAGE_RESET: 88 SMC_RET1(handle, bl1_fwu_image_reset(x1, flags)); 89 90 case FWU_SMC_UPDATE_DONE: 91 bl1_fwu_done((void *)x1, NULL); 92 93 default: 94 assert(0); /* Unreachable */ 95 break; 96 } 97 98 SMC_RET1(handle, SMC_UNK); 99 } 100 101 /******************************************************************************* 102 * Utility functions to keep track of the images that are loaded at any time. 103 ******************************************************************************/ 104 105 #ifdef PLAT_FWU_MAX_SIMULTANEOUS_IMAGES 106 #define FWU_MAX_SIMULTANEOUS_IMAGES PLAT_FWU_MAX_SIMULTANEOUS_IMAGES 107 #else 108 #define FWU_MAX_SIMULTANEOUS_IMAGES 10 109 #endif 110 111 static int bl1_fwu_loaded_ids[FWU_MAX_SIMULTANEOUS_IMAGES] = { 112 [0 ... FWU_MAX_SIMULTANEOUS_IMAGES-1] = INVALID_IMAGE_ID 113 }; 114 115 /* 116 * Adds an image_id to the bl1_fwu_loaded_ids array. 117 * Returns 0 on success, 1 on error. 118 */ 119 static int bl1_fwu_add_loaded_id(int image_id) 120 { 121 int i; 122 123 /* Check if the ID is already in the list */ 124 for (i = 0; i < FWU_MAX_SIMULTANEOUS_IMAGES; i++) { 125 if (bl1_fwu_loaded_ids[i] == image_id) 126 return 0; 127 } 128 129 /* Find an empty slot */ 130 for (i = 0; i < FWU_MAX_SIMULTANEOUS_IMAGES; i++) { 131 if (bl1_fwu_loaded_ids[i] == INVALID_IMAGE_ID) { 132 bl1_fwu_loaded_ids[i] = image_id; 133 return 0; 134 } 135 } 136 137 return 1; 138 } 139 140 /* 141 * Removes an image_id from the bl1_fwu_loaded_ids array. 142 * Returns 0 on success, 1 on error. 143 */ 144 static int bl1_fwu_remove_loaded_id(int image_id) 145 { 146 int i; 147 148 /* Find the ID */ 149 for (i = 0; i < FWU_MAX_SIMULTANEOUS_IMAGES; i++) { 150 if (bl1_fwu_loaded_ids[i] == image_id) { 151 bl1_fwu_loaded_ids[i] = INVALID_IMAGE_ID; 152 return 0; 153 } 154 } 155 156 return 1; 157 } 158 159 /******************************************************************************* 160 * This function checks if the specified image overlaps another image already 161 * loaded. It returns 0 if there is no overlap, a negative error code otherwise. 162 ******************************************************************************/ 163 static int bl1_fwu_image_check_overlaps(int image_id) 164 { 165 const image_desc_t *image_desc, *checked_image_desc; 166 const image_info_t *info, *checked_info; 167 168 uintptr_t image_base, image_end; 169 uintptr_t checked_image_base, checked_image_end; 170 171 checked_image_desc = bl1_plat_get_image_desc(image_id); 172 checked_info = &checked_image_desc->image_info; 173 174 /* Image being checked mustn't be empty. */ 175 assert(checked_info->image_size != 0); 176 177 checked_image_base = checked_info->image_base; 178 checked_image_end = checked_image_base + checked_info->image_size - 1; 179 /* No need to check for overflows, it's done in bl1_fwu_image_copy(). */ 180 181 for (int i = 0; i < FWU_MAX_SIMULTANEOUS_IMAGES; i++) { 182 183 /* Skip INVALID_IMAGE_IDs and don't check image against itself */ 184 if ((bl1_fwu_loaded_ids[i] == INVALID_IMAGE_ID) || 185 (bl1_fwu_loaded_ids[i] == image_id)) 186 continue; 187 188 image_desc = bl1_plat_get_image_desc(bl1_fwu_loaded_ids[i]); 189 190 /* Only check images that are loaded or being loaded. */ 191 assert (image_desc && image_desc->state != IMAGE_STATE_RESET); 192 193 info = &image_desc->image_info; 194 195 /* There cannot be overlaps with an empty image. */ 196 if (info->image_size == 0) 197 continue; 198 199 image_base = info->image_base; 200 image_end = image_base + info->image_size - 1; 201 /* 202 * Overflows cannot happen. It is checked in 203 * bl1_fwu_image_copy() when the image goes from RESET to 204 * COPYING or COPIED. 205 */ 206 assert (image_end > image_base); 207 208 /* Check if there are overlaps. */ 209 if (!(image_end < checked_image_base || 210 checked_image_end < image_base)) { 211 VERBOSE("Image with ID %d overlaps existing image with ID %d", 212 checked_image_desc->image_id, image_desc->image_id); 213 return -EPERM; 214 } 215 } 216 217 return 0; 218 } 219 220 /******************************************************************************* 221 * This function is responsible for copying secure images in AP Secure RAM. 222 ******************************************************************************/ 223 static int bl1_fwu_image_copy(unsigned int image_id, 224 uintptr_t image_src, 225 unsigned int block_size, 226 unsigned int image_size, 227 unsigned int flags) 228 { 229 uintptr_t dest_addr; 230 unsigned int remaining; 231 232 /* Get the image descriptor. */ 233 image_desc_t *image_desc = bl1_plat_get_image_desc(image_id); 234 if (!image_desc) { 235 WARN("BL1-FWU: Invalid image ID %u\n", image_id); 236 return -EPERM; 237 } 238 239 /* 240 * The request must originate from a non-secure caller and target a 241 * secure image. Any other scenario is invalid. 242 */ 243 if (GET_SECURITY_STATE(flags) == SECURE) { 244 WARN("BL1-FWU: Copy not allowed from secure world.\n"); 245 return -EPERM; 246 } 247 if (GET_SECURITY_STATE(image_desc->ep_info.h.attr) == NON_SECURE) { 248 WARN("BL1-FWU: Copy not allowed for non-secure images.\n"); 249 return -EPERM; 250 } 251 252 /* Check whether the FWU state machine is in the correct state. */ 253 if ((image_desc->state != IMAGE_STATE_RESET) && 254 (image_desc->state != IMAGE_STATE_COPYING)) { 255 WARN("BL1-FWU: Copy not allowed at this point of the FWU" 256 " process.\n"); 257 return -EPERM; 258 } 259 260 if ((!image_src) || (!block_size) || 261 check_uptr_overflow(image_src, block_size - 1)) { 262 WARN("BL1-FWU: Copy not allowed due to invalid image source" 263 " or block size\n"); 264 return -ENOMEM; 265 } 266 267 if (image_desc->state == IMAGE_STATE_COPYING) { 268 /* 269 * There must have been at least 1 copy operation for this image 270 * previously. 271 */ 272 assert(image_desc->copied_size != 0); 273 /* 274 * The image size must have been recorded in the 1st copy 275 * operation. 276 */ 277 image_size = image_desc->image_info.image_size; 278 assert(image_size != 0); 279 assert(image_desc->copied_size < image_size); 280 281 INFO("BL1-FWU: Continuing image copy in blocks\n"); 282 } else { /* image_desc->state == IMAGE_STATE_RESET */ 283 INFO("BL1-FWU: Initial call to copy an image\n"); 284 285 /* 286 * image_size is relevant only for the 1st copy request, it is 287 * then ignored for subsequent calls for this image. 288 */ 289 if (!image_size) { 290 WARN("BL1-FWU: Copy not allowed due to invalid image" 291 " size\n"); 292 return -ENOMEM; 293 } 294 295 /* Check that the image size to load is within limit */ 296 if (image_size > image_desc->image_info.image_max_size) { 297 WARN("BL1-FWU: Image size out of bounds\n"); 298 return -ENOMEM; 299 } 300 301 /* Save the given image size. */ 302 image_desc->image_info.image_size = image_size; 303 304 /* Make sure the image doesn't overlap other images. */ 305 if (bl1_fwu_image_check_overlaps(image_id)) { 306 image_desc->image_info.image_size = 0; 307 WARN("BL1-FWU: This image overlaps another one\n"); 308 return -EPERM; 309 } 310 311 /* 312 * copied_size must be explicitly initialized here because the 313 * FWU code doesn't necessarily do it when it resets the state 314 * machine. 315 */ 316 image_desc->copied_size = 0; 317 } 318 319 /* 320 * If the given block size is more than the total image size 321 * then clip the former to the latter. 322 */ 323 remaining = image_size - image_desc->copied_size; 324 if (block_size > remaining) { 325 WARN("BL1-FWU: Block size is too big, clipping it.\n"); 326 block_size = remaining; 327 } 328 329 /* Make sure the source image is mapped in memory. */ 330 if (bl1_plat_mem_check(image_src, block_size, flags)) { 331 WARN("BL1-FWU: Source image is not mapped.\n"); 332 return -ENOMEM; 333 } 334 335 if (bl1_fwu_add_loaded_id(image_id)) { 336 WARN("BL1-FWU: Too many images loaded at the same time.\n"); 337 return -ENOMEM; 338 } 339 340 /* Allow the platform to handle pre-image load before copying */ 341 if (image_desc->state == IMAGE_STATE_RESET) { 342 if (bl1_plat_handle_pre_image_load(image_id) != 0) { 343 ERROR("BL1-FWU: Failure in pre-image load of image id %d\n", 344 image_id); 345 return -EPERM; 346 } 347 } 348 349 /* Everything looks sane. Go ahead and copy the block of data. */ 350 dest_addr = image_desc->image_info.image_base + image_desc->copied_size; 351 memcpy((void *) dest_addr, (const void *) image_src, block_size); 352 flush_dcache_range(dest_addr, block_size); 353 354 image_desc->copied_size += block_size; 355 image_desc->state = (block_size == remaining) ? 356 IMAGE_STATE_COPIED : IMAGE_STATE_COPYING; 357 358 INFO("BL1-FWU: Copy operation successful.\n"); 359 return 0; 360 } 361 362 /******************************************************************************* 363 * This function is responsible for authenticating Normal/Secure images. 364 ******************************************************************************/ 365 static int bl1_fwu_image_auth(unsigned int image_id, 366 uintptr_t image_src, 367 unsigned int image_size, 368 unsigned int flags) 369 { 370 int result; 371 uintptr_t base_addr; 372 unsigned int total_size; 373 374 /* Get the image descriptor. */ 375 image_desc_t *image_desc = bl1_plat_get_image_desc(image_id); 376 if (!image_desc) 377 return -EPERM; 378 379 if (GET_SECURITY_STATE(flags) == SECURE) { 380 if (image_desc->state != IMAGE_STATE_RESET) { 381 WARN("BL1-FWU: Authentication from secure world " 382 "while in invalid state\n"); 383 return -EPERM; 384 } 385 } else { 386 if (GET_SECURITY_STATE(image_desc->ep_info.h.attr) == SECURE) { 387 if (image_desc->state != IMAGE_STATE_COPIED) { 388 WARN("BL1-FWU: Authentication of secure image " 389 "from non-secure world while not in copied state\n"); 390 return -EPERM; 391 } 392 } else { 393 if (image_desc->state != IMAGE_STATE_RESET) { 394 WARN("BL1-FWU: Authentication of non-secure image " 395 "from non-secure world while in invalid state\n"); 396 return -EPERM; 397 } 398 } 399 } 400 401 if (image_desc->state == IMAGE_STATE_COPIED) { 402 /* 403 * Image is in COPIED state. 404 * Use the stored address and size. 405 */ 406 base_addr = image_desc->image_info.image_base; 407 total_size = image_desc->image_info.image_size; 408 } else { 409 if ((!image_src) || (!image_size) || 410 check_uptr_overflow(image_src, image_size - 1)) { 411 WARN("BL1-FWU: Auth not allowed due to invalid" 412 " image source/size\n"); 413 return -ENOMEM; 414 } 415 416 /* 417 * Image is in RESET state. 418 * Check the parameters and authenticate the source image in place. 419 */ 420 if (bl1_plat_mem_check(image_src, image_size, \ 421 image_desc->ep_info.h.attr)) { 422 WARN("BL1-FWU: Authentication arguments source/size not mapped\n"); 423 return -ENOMEM; 424 } 425 426 if (bl1_fwu_add_loaded_id(image_id)) { 427 WARN("BL1-FWU: Too many images loaded at the same time.\n"); 428 return -ENOMEM; 429 } 430 431 base_addr = image_src; 432 total_size = image_size; 433 434 /* Update the image size in the descriptor. */ 435 image_desc->image_info.image_size = total_size; 436 } 437 438 /* 439 * Authenticate the image. 440 */ 441 INFO("BL1-FWU: Authenticating image_id:%d\n", image_id); 442 result = auth_mod_verify_img(image_id, (void *)base_addr, total_size); 443 if (result != 0) { 444 WARN("BL1-FWU: Authentication Failed err=%d\n", result); 445 446 /* 447 * Authentication has failed. 448 * Clear the memory if the image was copied. 449 * This is to prevent an attack where this contains 450 * some malicious code that can somehow be executed later. 451 */ 452 if (image_desc->state == IMAGE_STATE_COPIED) { 453 /* Clear the memory.*/ 454 zero_normalmem((void *)base_addr, total_size); 455 flush_dcache_range(base_addr, total_size); 456 457 /* Indicate that image can be copied again*/ 458 image_desc->state = IMAGE_STATE_RESET; 459 } 460 461 /* 462 * Even if this fails it's ok because the ID isn't in the array. 463 * The image cannot be in RESET state here, it is checked at the 464 * beginning of the function. 465 */ 466 bl1_fwu_remove_loaded_id(image_id); 467 return -EAUTH; 468 } 469 470 /* Indicate that image is in authenticated state. */ 471 image_desc->state = IMAGE_STATE_AUTHENTICATED; 472 473 /* Allow the platform to handle post-image load */ 474 result = bl1_plat_handle_post_image_load(image_id); 475 if (result != 0) { 476 ERROR("BL1-FWU: Failure %d in post-image load of image id %d\n", 477 result, image_id); 478 /* 479 * Panic here as the platform handling of post-image load is 480 * not correct. 481 */ 482 plat_error_handler(result); 483 } 484 485 /* 486 * Flush image_info to memory so that other 487 * secure world images can see changes. 488 */ 489 flush_dcache_range((unsigned long)&image_desc->image_info, 490 sizeof(image_info_t)); 491 492 INFO("BL1-FWU: Authentication was successful\n"); 493 494 return 0; 495 } 496 497 /******************************************************************************* 498 * This function is responsible for executing Secure images. 499 ******************************************************************************/ 500 static int bl1_fwu_image_execute(unsigned int image_id, 501 void **handle, 502 unsigned int flags) 503 { 504 /* Get the image descriptor. */ 505 image_desc_t *image_desc = bl1_plat_get_image_desc(image_id); 506 507 /* 508 * Execution is NOT allowed if: 509 * image_id is invalid OR 510 * Caller is from Secure world OR 511 * Image is Non-Secure OR 512 * Image is Non-Executable OR 513 * Image is NOT in AUTHENTICATED state. 514 */ 515 if ((!image_desc) || 516 (GET_SECURITY_STATE(flags) == SECURE) || 517 (GET_SECURITY_STATE(image_desc->ep_info.h.attr) == NON_SECURE) || 518 (EP_GET_EXE(image_desc->ep_info.h.attr) == NON_EXECUTABLE) || 519 (image_desc->state != IMAGE_STATE_AUTHENTICATED)) { 520 WARN("BL1-FWU: Execution not allowed due to invalid state/args\n"); 521 return -EPERM; 522 } 523 524 INFO("BL1-FWU: Executing Secure image\n"); 525 526 #ifdef AARCH64 527 /* Save NS-EL1 system registers. */ 528 cm_el1_sysregs_context_save(NON_SECURE); 529 #endif 530 531 /* Prepare the image for execution. */ 532 bl1_prepare_next_image(image_id); 533 534 /* Update the secure image id. */ 535 sec_exec_image_id = image_id; 536 537 #ifdef AARCH64 538 *handle = cm_get_context(SECURE); 539 #else 540 *handle = smc_get_ctx(SECURE); 541 #endif 542 return 0; 543 } 544 545 /******************************************************************************* 546 * This function is responsible for resuming execution in the other security 547 * world 548 ******************************************************************************/ 549 static register_t bl1_fwu_image_resume(register_t image_param, 550 void **handle, 551 unsigned int flags) 552 { 553 image_desc_t *image_desc; 554 unsigned int resume_sec_state; 555 unsigned int caller_sec_state = GET_SECURITY_STATE(flags); 556 557 /* Get the image descriptor for last executed secure image id. */ 558 image_desc = bl1_plat_get_image_desc(sec_exec_image_id); 559 if (caller_sec_state == NON_SECURE) { 560 if (!image_desc) { 561 WARN("BL1-FWU: Resume not allowed due to no available" 562 "secure image\n"); 563 return -EPERM; 564 } 565 } else { 566 /* image_desc must be valid for secure world callers */ 567 assert(image_desc); 568 } 569 570 assert(GET_SECURITY_STATE(image_desc->ep_info.h.attr) == SECURE); 571 assert(EP_GET_EXE(image_desc->ep_info.h.attr) == EXECUTABLE); 572 573 if (caller_sec_state == SECURE) { 574 assert(image_desc->state == IMAGE_STATE_EXECUTED); 575 576 /* Update the flags. */ 577 image_desc->state = IMAGE_STATE_INTERRUPTED; 578 resume_sec_state = NON_SECURE; 579 } else { 580 assert(image_desc->state == IMAGE_STATE_INTERRUPTED); 581 582 /* Update the flags. */ 583 image_desc->state = IMAGE_STATE_EXECUTED; 584 resume_sec_state = SECURE; 585 } 586 587 INFO("BL1-FWU: Resuming %s world context\n", 588 (resume_sec_state == SECURE) ? "secure" : "normal"); 589 590 #ifdef AARCH64 591 /* Save the EL1 system registers of calling world. */ 592 cm_el1_sysregs_context_save(caller_sec_state); 593 594 /* Restore the EL1 system registers of resuming world. */ 595 cm_el1_sysregs_context_restore(resume_sec_state); 596 597 /* Update the next context. */ 598 cm_set_next_eret_context(resume_sec_state); 599 600 *handle = cm_get_context(resume_sec_state); 601 #else 602 /* Update the next context. */ 603 cm_set_next_context(cm_get_context(resume_sec_state)); 604 605 /* Prepare the smc context for the next BL image. */ 606 smc_set_next_ctx(resume_sec_state); 607 608 *handle = smc_get_ctx(resume_sec_state); 609 #endif 610 return image_param; 611 } 612 613 /******************************************************************************* 614 * This function is responsible for resuming normal world context. 615 ******************************************************************************/ 616 static int bl1_fwu_sec_image_done(void **handle, unsigned int flags) 617 { 618 image_desc_t *image_desc; 619 620 /* Make sure caller is from the secure world */ 621 if (GET_SECURITY_STATE(flags) == NON_SECURE) { 622 WARN("BL1-FWU: Image done not allowed from normal world\n"); 623 return -EPERM; 624 } 625 626 /* Get the image descriptor for last executed secure image id */ 627 image_desc = bl1_plat_get_image_desc(sec_exec_image_id); 628 629 /* image_desc must correspond to a valid secure executing image */ 630 assert(image_desc); 631 assert(GET_SECURITY_STATE(image_desc->ep_info.h.attr) == SECURE); 632 assert(EP_GET_EXE(image_desc->ep_info.h.attr) == EXECUTABLE); 633 assert(image_desc->state == IMAGE_STATE_EXECUTED); 634 635 #if ENABLE_ASSERTIONS 636 int rc = bl1_fwu_remove_loaded_id(sec_exec_image_id); 637 assert(rc == 0); 638 #else 639 bl1_fwu_remove_loaded_id(sec_exec_image_id); 640 #endif 641 642 /* Update the flags. */ 643 image_desc->state = IMAGE_STATE_RESET; 644 sec_exec_image_id = INVALID_IMAGE_ID; 645 646 INFO("BL1-FWU: Resuming Normal world context\n"); 647 #ifdef AARCH64 648 /* 649 * Secure world is done so no need to save the context. 650 * Just restore the Non-Secure context. 651 */ 652 cm_el1_sysregs_context_restore(NON_SECURE); 653 654 /* Update the next context. */ 655 cm_set_next_eret_context(NON_SECURE); 656 657 *handle = cm_get_context(NON_SECURE); 658 #else 659 /* Update the next context. */ 660 cm_set_next_context(cm_get_context(NON_SECURE)); 661 662 /* Prepare the smc context for the next BL image. */ 663 smc_set_next_ctx(NON_SECURE); 664 665 *handle = smc_get_ctx(NON_SECURE); 666 #endif 667 return 0; 668 } 669 670 /******************************************************************************* 671 * This function provides the opportunity for users to perform any 672 * platform specific handling after the Firmware update is done. 673 ******************************************************************************/ 674 __dead2 static void bl1_fwu_done(void *client_cookie, void *reserved) 675 { 676 NOTICE("BL1-FWU: *******FWU Process Completed*******\n"); 677 678 /* 679 * Call platform done function. 680 */ 681 bl1_plat_fwu_done(client_cookie, reserved); 682 assert(0); 683 } 684 685 /******************************************************************************* 686 * This function resets an image to IMAGE_STATE_RESET. It fails if the image is 687 * being executed. 688 ******************************************************************************/ 689 static int bl1_fwu_image_reset(unsigned int image_id, unsigned int flags) 690 { 691 image_desc_t *image_desc = bl1_plat_get_image_desc(image_id); 692 693 if ((!image_desc) || (GET_SECURITY_STATE(flags) == SECURE)) { 694 WARN("BL1-FWU: Reset not allowed due to invalid args\n"); 695 return -EPERM; 696 } 697 698 switch (image_desc->state) { 699 700 case IMAGE_STATE_RESET: 701 /* Nothing to do. */ 702 break; 703 704 case IMAGE_STATE_INTERRUPTED: 705 case IMAGE_STATE_AUTHENTICATED: 706 case IMAGE_STATE_COPIED: 707 case IMAGE_STATE_COPYING: 708 709 if (bl1_fwu_remove_loaded_id(image_id)) { 710 WARN("BL1-FWU: Image reset couldn't find the image ID\n"); 711 return -EPERM; 712 } 713 714 if (image_desc->copied_size) { 715 /* Clear the memory if the image is copied */ 716 assert(GET_SECURITY_STATE(image_desc->ep_info.h.attr) == SECURE); 717 718 zero_normalmem((void *)image_desc->image_info.image_base, 719 image_desc->copied_size); 720 flush_dcache_range(image_desc->image_info.image_base, 721 image_desc->copied_size); 722 } 723 724 /* Reset status variables */ 725 image_desc->copied_size = 0; 726 image_desc->image_info.image_size = 0; 727 image_desc->state = IMAGE_STATE_RESET; 728 729 /* Clear authentication state */ 730 auth_img_flags[image_id] = 0; 731 732 break; 733 734 case IMAGE_STATE_EXECUTED: 735 default: 736 assert(0); /* Unreachable */ 737 break; 738 } 739 740 return 0; 741 } 742