xref: /rk3399_ARM-atf/bl1/bl1_fwu.c (revision 48bfb88eb6087bb3a293a13a0f702a0e40466b14)
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