xref: /rk3399_rockchip-uboot/arch/arm/cpu/armv8/sec_firmware.c (revision a797f274d7ae806d84b9ececf71f043ca6c1502a)
1b45db3b5SHou Zhiqiang /*
2b45db3b5SHou Zhiqiang  * Copyright 2016 NXP Semiconductor, Inc.
3b45db3b5SHou Zhiqiang  *
4b45db3b5SHou Zhiqiang  * SPDX-License-Identifier:	GPL-2.0+
5b45db3b5SHou Zhiqiang  */
6b45db3b5SHou Zhiqiang 
7b45db3b5SHou Zhiqiang #include <common.h>
8b45db3b5SHou Zhiqiang #include <errno.h>
9b45db3b5SHou Zhiqiang #include <linux/kernel.h>
10b45db3b5SHou Zhiqiang #include <asm/io.h>
11b45db3b5SHou Zhiqiang #include <asm/system.h>
12b45db3b5SHou Zhiqiang #include <asm/types.h>
13b45db3b5SHou Zhiqiang #include <asm/macro.h>
14b45db3b5SHou Zhiqiang #include <asm/armv8/sec_firmware.h>
15b45db3b5SHou Zhiqiang 
16b45db3b5SHou Zhiqiang DECLARE_GLOBAL_DATA_PTR;
17b45db3b5SHou Zhiqiang extern void c_runtime_cpu_setup(void);
18b45db3b5SHou Zhiqiang 
19b45db3b5SHou Zhiqiang #define SEC_FIRMWARE_LOADED	0x1
20b45db3b5SHou Zhiqiang #define SEC_FIRMWARE_RUNNING	0x2
21b45db3b5SHou Zhiqiang #define SEC_FIRMWARE_ADDR_MASK	(~0x3)
22b45db3b5SHou Zhiqiang /*
23b45db3b5SHou Zhiqiang  * Secure firmware load addr
24b45db3b5SHou Zhiqiang  * Flags used: 0x1 secure firmware has been loaded to secure memory
25b45db3b5SHou Zhiqiang  *             0x2 secure firmware is running
26b45db3b5SHou Zhiqiang  */
27b45db3b5SHou Zhiqiang phys_addr_t sec_firmware_addr;
2881049ba8SHou Zhiqiang 
2981049ba8SHou Zhiqiang #ifndef SEC_FIRMWARE_FIT_IMAGE
3081049ba8SHou Zhiqiang #define SEC_FIRMWARE_FIT_IMAGE		"firmware"
3181049ba8SHou Zhiqiang #endif
3281049ba8SHou Zhiqiang #ifndef SEC_FIRMEWARE_FIT_CNF_NAME
3381049ba8SHou Zhiqiang #define SEC_FIRMEWARE_FIT_CNF_NAME	"config@1"
3481049ba8SHou Zhiqiang #endif
3581049ba8SHou Zhiqiang #ifndef SEC_FIRMWARE_TARGET_EL
3681049ba8SHou Zhiqiang #define SEC_FIRMWARE_TARGET_EL		2
3781049ba8SHou Zhiqiang #endif
38b45db3b5SHou Zhiqiang 
sec_firmware_get_data(const void * sec_firmware_img,const void ** data,size_t * size)39b45db3b5SHou Zhiqiang static int sec_firmware_get_data(const void *sec_firmware_img,
40b45db3b5SHou Zhiqiang 				const void **data, size_t *size)
41b45db3b5SHou Zhiqiang {
42b45db3b5SHou Zhiqiang 	int conf_node_off, fw_node_off;
43b45db3b5SHou Zhiqiang 	char *conf_node_name = NULL;
44b45db3b5SHou Zhiqiang 	char *desc;
45b45db3b5SHou Zhiqiang 	int ret;
46b45db3b5SHou Zhiqiang 
47b45db3b5SHou Zhiqiang 	conf_node_name = SEC_FIRMEWARE_FIT_CNF_NAME;
48b45db3b5SHou Zhiqiang 
49b45db3b5SHou Zhiqiang 	conf_node_off = fit_conf_get_node(sec_firmware_img, conf_node_name);
50b45db3b5SHou Zhiqiang 	if (conf_node_off < 0) {
51b45db3b5SHou Zhiqiang 		printf("SEC Firmware: %s: no such config\n", conf_node_name);
52b45db3b5SHou Zhiqiang 		return -ENOENT;
53b45db3b5SHou Zhiqiang 	}
54b45db3b5SHou Zhiqiang 
55b45db3b5SHou Zhiqiang 	fw_node_off = fit_conf_get_prop_node(sec_firmware_img, conf_node_off,
56b45db3b5SHou Zhiqiang 			SEC_FIRMWARE_FIT_IMAGE);
57b45db3b5SHou Zhiqiang 	if (fw_node_off < 0) {
58b45db3b5SHou Zhiqiang 		printf("SEC Firmware: No '%s' in config\n",
59b45db3b5SHou Zhiqiang 		       SEC_FIRMWARE_FIT_IMAGE);
60b45db3b5SHou Zhiqiang 		return -ENOLINK;
61b45db3b5SHou Zhiqiang 	}
62b45db3b5SHou Zhiqiang 
63b45db3b5SHou Zhiqiang 	/* Verify secure firmware image */
64b45db3b5SHou Zhiqiang 	if (!(fit_image_verify(sec_firmware_img, fw_node_off))) {
65b45db3b5SHou Zhiqiang 		printf("SEC Firmware: Bad firmware image (bad CRC)\n");
66b45db3b5SHou Zhiqiang 		return -EINVAL;
67b45db3b5SHou Zhiqiang 	}
68b45db3b5SHou Zhiqiang 
69b45db3b5SHou Zhiqiang 	if (fit_image_get_data(sec_firmware_img, fw_node_off, data, size)) {
70b45db3b5SHou Zhiqiang 		printf("SEC Firmware: Can't get %s subimage data/size",
71b45db3b5SHou Zhiqiang 		       SEC_FIRMWARE_FIT_IMAGE);
72b45db3b5SHou Zhiqiang 		return -ENOENT;
73b45db3b5SHou Zhiqiang 	}
74b45db3b5SHou Zhiqiang 
75b45db3b5SHou Zhiqiang 	ret = fit_get_desc(sec_firmware_img, fw_node_off, &desc);
76b45db3b5SHou Zhiqiang 	if (ret)
77b45db3b5SHou Zhiqiang 		printf("SEC Firmware: Can't get description\n");
78b45db3b5SHou Zhiqiang 	else
79b45db3b5SHou Zhiqiang 		printf("%s\n", desc);
80b45db3b5SHou Zhiqiang 
81b45db3b5SHou Zhiqiang 	return ret;
82b45db3b5SHou Zhiqiang }
83b45db3b5SHou Zhiqiang 
84b45db3b5SHou Zhiqiang /*
85b45db3b5SHou Zhiqiang  * SEC Firmware FIT image parser checks if the image is in FIT
86b45db3b5SHou Zhiqiang  * format, verifies integrity of the image and calculates raw
87b45db3b5SHou Zhiqiang  * image address and size values.
88b45db3b5SHou Zhiqiang  *
89b45db3b5SHou Zhiqiang  * Returns 0 on success and a negative errno on error task fail.
90b45db3b5SHou Zhiqiang  */
sec_firmware_parse_image(const void * sec_firmware_img,const void ** raw_image_addr,size_t * raw_image_size)91b45db3b5SHou Zhiqiang static int sec_firmware_parse_image(const void *sec_firmware_img,
92b45db3b5SHou Zhiqiang 					const void **raw_image_addr,
93b45db3b5SHou Zhiqiang 					size_t *raw_image_size)
94b45db3b5SHou Zhiqiang {
95b45db3b5SHou Zhiqiang 	int ret;
96b45db3b5SHou Zhiqiang 
97b45db3b5SHou Zhiqiang 	ret = sec_firmware_get_data(sec_firmware_img, raw_image_addr,
98b45db3b5SHou Zhiqiang 					raw_image_size);
99b45db3b5SHou Zhiqiang 	if (ret)
100b45db3b5SHou Zhiqiang 		return ret;
101b45db3b5SHou Zhiqiang 
102b45db3b5SHou Zhiqiang 	debug("SEC Firmware: raw_image_addr = 0x%p, raw_image_size = 0x%lx\n",
103b45db3b5SHou Zhiqiang 	      *raw_image_addr, *raw_image_size);
104b45db3b5SHou Zhiqiang 
105b45db3b5SHou Zhiqiang 	return 0;
106b45db3b5SHou Zhiqiang }
107b45db3b5SHou Zhiqiang 
sec_firmware_copy_image(const char * title,u64 image_addr,u32 image_size,u64 sec_firmware)108b45db3b5SHou Zhiqiang static int sec_firmware_copy_image(const char *title,
109b45db3b5SHou Zhiqiang 			 u64 image_addr, u32 image_size, u64 sec_firmware)
110b45db3b5SHou Zhiqiang {
111b45db3b5SHou Zhiqiang 	debug("%s copied to address 0x%p\n", title, (void *)sec_firmware);
112b45db3b5SHou Zhiqiang 	memcpy((void *)sec_firmware, (void *)image_addr, image_size);
113b45db3b5SHou Zhiqiang 	flush_dcache_range(sec_firmware, sec_firmware + image_size);
114b45db3b5SHou Zhiqiang 
115b45db3b5SHou Zhiqiang 	return 0;
116b45db3b5SHou Zhiqiang }
117b45db3b5SHou Zhiqiang 
118b45db3b5SHou Zhiqiang /*
119b45db3b5SHou Zhiqiang  * This function will parse the SEC Firmware image, and then load it
120b45db3b5SHou Zhiqiang  * to secure memory.
121b45db3b5SHou Zhiqiang  */
sec_firmware_load_image(const void * sec_firmware_img)122b45db3b5SHou Zhiqiang static int sec_firmware_load_image(const void *sec_firmware_img)
123b45db3b5SHou Zhiqiang {
124b45db3b5SHou Zhiqiang 	const void *raw_image_addr;
125b45db3b5SHou Zhiqiang 	size_t raw_image_size = 0;
126b45db3b5SHou Zhiqiang 	int ret;
127b45db3b5SHou Zhiqiang 
128b45db3b5SHou Zhiqiang 	/*
129b45db3b5SHou Zhiqiang 	 * The Excetpion Level must be EL3 to load and initialize
130b45db3b5SHou Zhiqiang 	 * the SEC Firmware.
131b45db3b5SHou Zhiqiang 	 */
132b45db3b5SHou Zhiqiang 	if (current_el() != 3) {
133b45db3b5SHou Zhiqiang 		ret = -EACCES;
134b45db3b5SHou Zhiqiang 		goto out;
135b45db3b5SHou Zhiqiang 	}
136b45db3b5SHou Zhiqiang 
137b45db3b5SHou Zhiqiang #ifdef CONFIG_SYS_MEM_RESERVE_SECURE
138b45db3b5SHou Zhiqiang 	/*
139b45db3b5SHou Zhiqiang 	 * The SEC Firmware must be stored in secure memory.
140b45db3b5SHou Zhiqiang 	 * Append SEC Firmware to secure mmu table.
141b45db3b5SHou Zhiqiang 	 */
142b45db3b5SHou Zhiqiang 	if (!(gd->arch.secure_ram & MEM_RESERVE_SECURE_MAINTAINED)) {
143b45db3b5SHou Zhiqiang 		ret = -ENXIO;
144b45db3b5SHou Zhiqiang 		goto out;
145b45db3b5SHou Zhiqiang 	}
146b45db3b5SHou Zhiqiang 
147b45db3b5SHou Zhiqiang 	sec_firmware_addr = (gd->arch.secure_ram & MEM_RESERVE_SECURE_ADDR_MASK) +
148b45db3b5SHou Zhiqiang 			gd->arch.tlb_size;
149b45db3b5SHou Zhiqiang #else
150b45db3b5SHou Zhiqiang #error "The CONFIG_SYS_MEM_RESERVE_SECURE must be defined when enabled SEC Firmware support"
151b45db3b5SHou Zhiqiang #endif
152b45db3b5SHou Zhiqiang 
153b45db3b5SHou Zhiqiang 	/* Align SEC Firmware base address to 4K */
154b45db3b5SHou Zhiqiang 	sec_firmware_addr = (sec_firmware_addr + 0xfff) & ~0xfff;
155b45db3b5SHou Zhiqiang 	debug("SEC Firmware: Load address: 0x%llx\n",
156b45db3b5SHou Zhiqiang 	      sec_firmware_addr & SEC_FIRMWARE_ADDR_MASK);
157b45db3b5SHou Zhiqiang 
158b45db3b5SHou Zhiqiang 	ret = sec_firmware_parse_image(sec_firmware_img, &raw_image_addr,
159b45db3b5SHou Zhiqiang 			&raw_image_size);
160b45db3b5SHou Zhiqiang 	if (ret)
161b45db3b5SHou Zhiqiang 		goto out;
162b45db3b5SHou Zhiqiang 
163b45db3b5SHou Zhiqiang 	/* TODO:
164b45db3b5SHou Zhiqiang 	 * Check if the end addr of SEC Firmware has been extend the secure
165b45db3b5SHou Zhiqiang 	 * memory.
166b45db3b5SHou Zhiqiang 	 */
167b45db3b5SHou Zhiqiang 
168b45db3b5SHou Zhiqiang 	/* Copy the secure firmware to secure memory */
169b45db3b5SHou Zhiqiang 	ret = sec_firmware_copy_image("SEC Firmware", (u64)raw_image_addr,
170b45db3b5SHou Zhiqiang 			raw_image_size, sec_firmware_addr &
171b45db3b5SHou Zhiqiang 			SEC_FIRMWARE_ADDR_MASK);
172b45db3b5SHou Zhiqiang 	if (ret)
173b45db3b5SHou Zhiqiang 		goto out;
174b45db3b5SHou Zhiqiang 
175b45db3b5SHou Zhiqiang 	sec_firmware_addr |= SEC_FIRMWARE_LOADED;
176b45db3b5SHou Zhiqiang 	debug("SEC Firmware: Entry point: 0x%llx\n",
177b45db3b5SHou Zhiqiang 	      sec_firmware_addr & SEC_FIRMWARE_ADDR_MASK);
178b45db3b5SHou Zhiqiang 
179b45db3b5SHou Zhiqiang 	return 0;
180b45db3b5SHou Zhiqiang 
181b45db3b5SHou Zhiqiang out:
182b45db3b5SHou Zhiqiang 	printf("SEC Firmware: error (%d)\n", ret);
183b45db3b5SHou Zhiqiang 	sec_firmware_addr = 0;
184b45db3b5SHou Zhiqiang 
185b45db3b5SHou Zhiqiang 	return ret;
186b45db3b5SHou Zhiqiang }
187b45db3b5SHou Zhiqiang 
sec_firmware_entry(u32 * eret_hold_l,u32 * eret_hold_h)188b45db3b5SHou Zhiqiang static int sec_firmware_entry(u32 *eret_hold_l, u32 *eret_hold_h)
189b45db3b5SHou Zhiqiang {
190b45db3b5SHou Zhiqiang 	const void *entry = (void *)(sec_firmware_addr &
191b45db3b5SHou Zhiqiang 				SEC_FIRMWARE_ADDR_MASK);
192b45db3b5SHou Zhiqiang 
193b45db3b5SHou Zhiqiang 	return _sec_firmware_entry(entry, eret_hold_l, eret_hold_h);
194b45db3b5SHou Zhiqiang }
195b45db3b5SHou Zhiqiang 
196b45db3b5SHou Zhiqiang /* Check the secure firmware FIT image */
sec_firmware_is_valid(const void * sec_firmware_img)197b45db3b5SHou Zhiqiang __weak bool sec_firmware_is_valid(const void *sec_firmware_img)
198b45db3b5SHou Zhiqiang {
199b45db3b5SHou Zhiqiang 	if (fdt_check_header(sec_firmware_img)) {
200b45db3b5SHou Zhiqiang 		printf("SEC Firmware: Bad firmware image (not a FIT image)\n");
201b45db3b5SHou Zhiqiang 		return false;
202b45db3b5SHou Zhiqiang 	}
203b45db3b5SHou Zhiqiang 
204b45db3b5SHou Zhiqiang 	if (!fit_check_format(sec_firmware_img)) {
205b45db3b5SHou Zhiqiang 		printf("SEC Firmware: Bad firmware image (bad FIT header)\n");
206b45db3b5SHou Zhiqiang 		return false;
207b45db3b5SHou Zhiqiang 	}
208b45db3b5SHou Zhiqiang 
209b45db3b5SHou Zhiqiang 	return true;
210b45db3b5SHou Zhiqiang }
211b45db3b5SHou Zhiqiang 
212daa92644SHou Zhiqiang #ifdef CONFIG_SEC_FIRMWARE_ARMV8_PSCI
213b45db3b5SHou Zhiqiang /*
214b45db3b5SHou Zhiqiang  * The PSCI_VERSION function is added from PSCI v0.2. When the PSCI
215b45db3b5SHou Zhiqiang  * v0.1 received this function, the NOT_SUPPORTED (0xffff_ffff) error
216b45db3b5SHou Zhiqiang  * number will be returned according to SMC Calling Conventions. But
217b45db3b5SHou Zhiqiang  * when getting the NOT_SUPPORTED error number, we cannot ensure if
218b45db3b5SHou Zhiqiang  * the PSCI version is v0.1 or other error occurred. So, PSCI v0.1
219b45db3b5SHou Zhiqiang  * won't be supported by this framework.
220b45db3b5SHou Zhiqiang  * And if the secure firmware isn't running, return NOT_SUPPORTED.
221b45db3b5SHou Zhiqiang  *
222b45db3b5SHou Zhiqiang  * The return value on success is PSCI version in format
223b45db3b5SHou Zhiqiang  * major[31:16]:minor[15:0].
224b45db3b5SHou Zhiqiang  */
sec_firmware_support_psci_version(void)225b45db3b5SHou Zhiqiang unsigned int sec_firmware_support_psci_version(void)
226b45db3b5SHou Zhiqiang {
227399e2bb6SYork Sun 	if (current_el() == SEC_FIRMWARE_TARGET_EL)
228b45db3b5SHou Zhiqiang 		return _sec_firmware_support_psci_version();
229b45db3b5SHou Zhiqiang 
230026f30ecSYuantian Tang 	return PSCI_INVALID_VER;
231b45db3b5SHou Zhiqiang }
232b45db3b5SHou Zhiqiang #endif
233b45db3b5SHou Zhiqiang 
234b45db3b5SHou Zhiqiang /*
235*a797f274SRuchika Gupta  * Check with sec_firmware if it supports random number generation
236*a797f274SRuchika Gupta  * via HW RNG
237*a797f274SRuchika Gupta  *
238*a797f274SRuchika Gupta  * The return value will be true if it is supported
239*a797f274SRuchika Gupta  */
sec_firmware_support_hwrng(void)240*a797f274SRuchika Gupta bool sec_firmware_support_hwrng(void)
241*a797f274SRuchika Gupta {
242*a797f274SRuchika Gupta 	uint8_t rand[8];
243*a797f274SRuchika Gupta 	if (sec_firmware_addr & SEC_FIRMWARE_RUNNING) {
244*a797f274SRuchika Gupta 		if (!sec_firmware_get_random(rand, 8))
245*a797f274SRuchika Gupta 			return true;
246*a797f274SRuchika Gupta 	}
247*a797f274SRuchika Gupta 
248*a797f274SRuchika Gupta 	return false;
249*a797f274SRuchika Gupta }
250*a797f274SRuchika Gupta 
251*a797f274SRuchika Gupta /*
252*a797f274SRuchika Gupta  * sec_firmware_get_random - Get a random number from SEC Firmware
253*a797f274SRuchika Gupta  * @rand:		random number buffer to be filled
254*a797f274SRuchika Gupta  * @bytes:		Number of bytes of random number to be supported
255*a797f274SRuchika Gupta  * @eret:		-1 in case of error, 0 for success
256*a797f274SRuchika Gupta  */
sec_firmware_get_random(uint8_t * rand,int bytes)257*a797f274SRuchika Gupta int sec_firmware_get_random(uint8_t *rand, int bytes)
258*a797f274SRuchika Gupta {
259*a797f274SRuchika Gupta 	unsigned long long num;
260*a797f274SRuchika Gupta 	struct pt_regs regs;
261*a797f274SRuchika Gupta 	int param1;
262*a797f274SRuchika Gupta 
263*a797f274SRuchika Gupta 	if (!bytes || bytes > 8) {
264*a797f274SRuchika Gupta 		printf("Max Random bytes genration supported is 8\n");
265*a797f274SRuchika Gupta 		return -1;
266*a797f274SRuchika Gupta 	}
267*a797f274SRuchika Gupta #define SIP_RNG_64 0xC200FF11
268*a797f274SRuchika Gupta 	regs.regs[0] = SIP_RNG_64;
269*a797f274SRuchika Gupta 
270*a797f274SRuchika Gupta 	if (bytes <= 4)
271*a797f274SRuchika Gupta 		param1 = 0;
272*a797f274SRuchika Gupta 	else
273*a797f274SRuchika Gupta 		param1 = 1;
274*a797f274SRuchika Gupta 	regs.regs[1] = param1;
275*a797f274SRuchika Gupta 
276*a797f274SRuchika Gupta 	smc_call(&regs);
277*a797f274SRuchika Gupta 
278*a797f274SRuchika Gupta 	if (regs.regs[0])
279*a797f274SRuchika Gupta 		return -1;
280*a797f274SRuchika Gupta 
281*a797f274SRuchika Gupta 	num = regs.regs[1];
282*a797f274SRuchika Gupta 	memcpy(rand, &num, bytes);
283*a797f274SRuchika Gupta 
284*a797f274SRuchika Gupta 	return 0;
285*a797f274SRuchika Gupta }
286*a797f274SRuchika Gupta 
287*a797f274SRuchika Gupta /*
288b45db3b5SHou Zhiqiang  * sec_firmware_init - Initialize the SEC Firmware
289b45db3b5SHou Zhiqiang  * @sec_firmware_img:	the SEC Firmware image address
290b45db3b5SHou Zhiqiang  * @eret_hold_l:	the address to hold exception return address low
291b45db3b5SHou Zhiqiang  * @eret_hold_h:	the address to hold exception return address high
292b45db3b5SHou Zhiqiang  */
sec_firmware_init(const void * sec_firmware_img,u32 * eret_hold_l,u32 * eret_hold_h)293b45db3b5SHou Zhiqiang int sec_firmware_init(const void *sec_firmware_img,
294b45db3b5SHou Zhiqiang 			u32 *eret_hold_l,
295b45db3b5SHou Zhiqiang 			u32 *eret_hold_h)
296b45db3b5SHou Zhiqiang {
297b45db3b5SHou Zhiqiang 	int ret;
298b45db3b5SHou Zhiqiang 
299b45db3b5SHou Zhiqiang 	if (!sec_firmware_is_valid(sec_firmware_img))
300b45db3b5SHou Zhiqiang 		return -EINVAL;
301b45db3b5SHou Zhiqiang 
302b45db3b5SHou Zhiqiang 	ret = sec_firmware_load_image(sec_firmware_img);
303b45db3b5SHou Zhiqiang 	if (ret) {
304b45db3b5SHou Zhiqiang 		printf("SEC Firmware: Failed to load image\n");
305b45db3b5SHou Zhiqiang 		return ret;
306b45db3b5SHou Zhiqiang 	} else if (sec_firmware_addr & SEC_FIRMWARE_LOADED) {
307b45db3b5SHou Zhiqiang 		ret = sec_firmware_entry(eret_hold_l, eret_hold_h);
308b45db3b5SHou Zhiqiang 		if (ret) {
309b45db3b5SHou Zhiqiang 			printf("SEC Firmware: Failed to initialize\n");
310b45db3b5SHou Zhiqiang 			return ret;
311b45db3b5SHou Zhiqiang 		}
312b45db3b5SHou Zhiqiang 	}
313b45db3b5SHou Zhiqiang 
314b45db3b5SHou Zhiqiang 	debug("SEC Firmware: Return from SEC Firmware: current_el = %d\n",
315b45db3b5SHou Zhiqiang 	      current_el());
316b45db3b5SHou Zhiqiang 
317b45db3b5SHou Zhiqiang 	/*
318b45db3b5SHou Zhiqiang 	 * The PE will be turned into target EL when returned from
319b45db3b5SHou Zhiqiang 	 * SEC Firmware.
320b45db3b5SHou Zhiqiang 	 */
321b45db3b5SHou Zhiqiang 	if (current_el() != SEC_FIRMWARE_TARGET_EL)
322b45db3b5SHou Zhiqiang 		return -EACCES;
323b45db3b5SHou Zhiqiang 
324b45db3b5SHou Zhiqiang 	sec_firmware_addr |= SEC_FIRMWARE_RUNNING;
325b45db3b5SHou Zhiqiang 
326b45db3b5SHou Zhiqiang 	/* Set exception table and enable caches if it isn't EL3 */
327b45db3b5SHou Zhiqiang 	if (current_el() != 3) {
328b45db3b5SHou Zhiqiang 		c_runtime_cpu_setup();
329b45db3b5SHou Zhiqiang 		enable_caches();
330b45db3b5SHou Zhiqiang 	}
331b45db3b5SHou Zhiqiang 
332b45db3b5SHou Zhiqiang 	return 0;
333b45db3b5SHou Zhiqiang }
334*a797f274SRuchika Gupta 
335*a797f274SRuchika Gupta /*
336*a797f274SRuchika Gupta  * fdt_fix_kaslr - Add kalsr-seed node in Device tree
337*a797f274SRuchika Gupta  * @fdt:		Device tree
338*a797f274SRuchika Gupta  * @eret:		0 in case of error, 1 for success
339*a797f274SRuchika Gupta  */
fdt_fixup_kaslr(void * fdt)340*a797f274SRuchika Gupta int fdt_fixup_kaslr(void *fdt)
341*a797f274SRuchika Gupta {
342*a797f274SRuchika Gupta 	int nodeoffset;
343*a797f274SRuchika Gupta 	int err, ret = 0;
344*a797f274SRuchika Gupta 	u8 rand[8];
345*a797f274SRuchika Gupta 
346*a797f274SRuchika Gupta #if defined(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT)
347*a797f274SRuchika Gupta 	/* Check if random seed generation is  supported */
348*a797f274SRuchika Gupta 	if (sec_firmware_support_hwrng() == false)
349*a797f274SRuchika Gupta 		return 0;
350*a797f274SRuchika Gupta 
351*a797f274SRuchika Gupta 	ret = sec_firmware_get_random(rand, 8);
352*a797f274SRuchika Gupta 	if (ret < 0) {
353*a797f274SRuchika Gupta 		printf("WARNING: No random number to set kaslr-seed\n");
354*a797f274SRuchika Gupta 		return 0;
355*a797f274SRuchika Gupta 	}
356*a797f274SRuchika Gupta 
357*a797f274SRuchika Gupta 	err = fdt_check_header(fdt);
358*a797f274SRuchika Gupta 	if (err < 0) {
359*a797f274SRuchika Gupta 		printf("fdt_chosen: %s\n", fdt_strerror(err));
360*a797f274SRuchika Gupta 		return 0;
361*a797f274SRuchika Gupta 	}
362*a797f274SRuchika Gupta 
363*a797f274SRuchika Gupta 	/* find or create "/chosen" node. */
364*a797f274SRuchika Gupta 	nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
365*a797f274SRuchika Gupta 	if (nodeoffset < 0)
366*a797f274SRuchika Gupta 		return 0;
367*a797f274SRuchika Gupta 
368*a797f274SRuchika Gupta 	err = fdt_setprop(fdt, nodeoffset, "kaslr-seed", rand,
369*a797f274SRuchika Gupta 				  sizeof(rand));
370*a797f274SRuchika Gupta 	if (err < 0) {
371*a797f274SRuchika Gupta 		printf("WARNING: can't set kaslr-seed %s.\n",
372*a797f274SRuchika Gupta 		       fdt_strerror(err));
373*a797f274SRuchika Gupta 		return 0;
374*a797f274SRuchika Gupta 	}
375*a797f274SRuchika Gupta 	ret = 1;
376*a797f274SRuchika Gupta #endif
377*a797f274SRuchika Gupta 
378*a797f274SRuchika Gupta 	return ret;
379*a797f274SRuchika Gupta }
380