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