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