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