blob: c4d235e0a0d7fd43bda25cfd68d10c05a32872bc [file] [log] [blame]
Jens Wiklander52c798e2015-12-07 14:37:10 +01001/*
Jens Wiklanderd4b84f02022-11-18 15:40:04 +01002 * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
Jens Wiklander52c798e2015-12-07 14:37:10 +01003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Jens Wiklander52c798e2015-12-07 14:37:10 +01005 */
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00006
Fu Weic2f78442017-05-27 21:21:42 +08007#include <assert.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008#include <string.h>
9
Jens Wiklander52c798e2015-12-07 14:37:10 +010010#include <libfdt.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000011
Jens Wiklander52c798e2015-12-07 14:37:10 +010012#include <platform_def.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000013
14#include <arch_helpers.h>
15#include <common/bl_common.h>
16#include <common/debug.h>
17#include <common/desc_image_load.h>
Andre Przywaraffbacb02019-07-10 17:27:17 +010018#include <common/fdt_fixup.h>
Jens Wiklandera43c1282022-11-22 14:39:26 +010019#include <common/fdt_wrappers.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000020#include <lib/optee_utils.h>
21#include <lib/utils.h>
22#include <plat/common/platform.h>
23
Isla Mitchelle3631462017-07-14 10:46:32 +010024#include "qemu_private.h"
Jens Wiklander52c798e2015-12-07 14:37:10 +010025
Chen Baozif7d9aa82023-02-20 10:50:15 +000026#define MAP_BL2_TOTAL MAP_REGION_FLAT( \
27 bl2_tzram_layout.total_base, \
28 bl2_tzram_layout.total_size, \
29 MT_MEMORY | MT_RW | MT_SECURE)
30
31#define MAP_BL2_RO MAP_REGION_FLAT( \
32 BL_CODE_BASE, \
33 BL_CODE_END - BL_CODE_BASE, \
34 MT_CODE | MT_SECURE), \
35 MAP_REGION_FLAT( \
36 BL_RO_DATA_BASE, \
37 BL_RO_DATA_END \
38 - BL_RO_DATA_BASE, \
39 MT_RO_DATA | MT_SECURE)
40
Chen Baozi097a43a2023-03-12 20:58:04 +080041#if USE_COHERENT_MEM
Chen Baozif7d9aa82023-02-20 10:50:15 +000042#define MAP_BL_COHERENT_RAM MAP_REGION_FLAT( \
43 BL_COHERENT_RAM_BASE, \
44 BL_COHERENT_RAM_END \
45 - BL_COHERENT_RAM_BASE, \
46 MT_DEVICE | MT_RW | MT_SECURE)
Chen Baozi097a43a2023-03-12 20:58:04 +080047#endif
Jens Wiklander52c798e2015-12-07 14:37:10 +010048
Fu Weic2f78442017-05-27 21:21:42 +080049/* Data structure which holds the extents of the trusted SRAM for BL2 */
50static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
51
Jens Wiklandere22b91e2018-09-04 14:07:19 +020052void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
53 u_register_t arg2, u_register_t arg3)
Jens Wiklander52c798e2015-12-07 14:37:10 +010054{
Jens Wiklandere22b91e2018-09-04 14:07:19 +020055 meminfo_t *mem_layout = (void *)arg1;
56
Jens Wiklander52c798e2015-12-07 14:37:10 +010057 /* Initialize the console to provide early debug support */
Michalis Pappascca6cb72018-03-04 15:43:38 +080058 qemu_console_init();
Jens Wiklander52c798e2015-12-07 14:37:10 +010059
60 /* Setup the BL2 memory layout */
61 bl2_tzram_layout = *mem_layout;
62
63 plat_qemu_io_setup();
64}
65
66static void security_setup(void)
67{
68 /*
69 * This is where a TrustZone address space controller and other
70 * security related peripherals, would be configured.
71 */
72}
73
74static void update_dt(void)
75{
76 int ret;
Andrew Walbran9c4d0692020-01-15 14:11:31 +000077 void *fdt = (void *)(uintptr_t)ARM_PRELOADED_DTB_BASE;
Jens Wiklander52c798e2015-12-07 14:37:10 +010078
79 ret = fdt_open_into(fdt, fdt, PLAT_QEMU_DT_MAX_SIZE);
80 if (ret < 0) {
81 ERROR("Invalid Device Tree at %p: error %d\n", fdt, ret);
82 return;
83 }
84
85 if (dt_add_psci_node(fdt)) {
86 ERROR("Failed to add PSCI Device Tree node\n");
87 return;
88 }
89
90 if (dt_add_psci_cpu_enable_methods(fdt)) {
91 ERROR("Failed to add PSCI cpu enable methods in Device Tree\n");
92 return;
93 }
94
95 ret = fdt_pack(fdt);
96 if (ret < 0)
97 ERROR("Failed to pack Device Tree at %p: error %d\n", fdt, ret);
98}
99
100void bl2_platform_setup(void)
101{
102 security_setup();
103 update_dt();
104
105 /* TODO Initialize timer */
106}
107
Chen Baozif7d9aa82023-02-20 10:50:15 +0000108void bl2_plat_arch_setup(void)
109{
110 const mmap_region_t bl_regions[] = {
111 MAP_BL2_TOTAL,
112 MAP_BL2_RO,
Chen Baozi097a43a2023-03-12 20:58:04 +0800113#if USE_COHERENT_MEM
Chen Baozif7d9aa82023-02-20 10:50:15 +0000114 MAP_BL_COHERENT_RAM,
Chen Baozi097a43a2023-03-12 20:58:04 +0800115#endif
Chen Baozif7d9aa82023-02-20 10:50:15 +0000116 {0}
117 };
118
119 setup_page_tables(bl_regions, plat_qemu_get_mmap());
120
Julius Werner8e0ef0f2019-07-09 14:02:43 -0700121#ifdef __aarch64__
Chen Baozif7d9aa82023-02-20 10:50:15 +0000122 enable_mmu_el1(0);
Julius Werner8e0ef0f2019-07-09 14:02:43 -0700123#else
Chen Baozif7d9aa82023-02-20 10:50:15 +0000124 enable_mmu_svc_mon(0);
Etienne Carriere911de8c2018-02-02 13:23:22 +0100125#endif
Jens Wiklander52c798e2015-12-07 14:37:10 +0100126}
127
128/*******************************************************************************
129 * Gets SPSR for BL32 entry
130 ******************************************************************************/
131static uint32_t qemu_get_spsr_for_bl32_entry(void)
132{
Julius Werner8e0ef0f2019-07-09 14:02:43 -0700133#ifdef __aarch64__
Jens Wiklander52c798e2015-12-07 14:37:10 +0100134 /*
135 * The Secure Payload Dispatcher service is responsible for
136 * setting the SPSR prior to entry into the BL3-2 image.
137 */
138 return 0;
Etienne Carriere911de8c2018-02-02 13:23:22 +0100139#else
140 return SPSR_MODE32(MODE32_svc, SPSR_T_ARM, SPSR_E_LITTLE,
141 DISABLE_ALL_EXCEPTIONS);
142#endif
Jens Wiklander52c798e2015-12-07 14:37:10 +0100143}
144
145/*******************************************************************************
146 * Gets SPSR for BL33 entry
147 ******************************************************************************/
148static uint32_t qemu_get_spsr_for_bl33_entry(void)
149{
Jens Wiklander52c798e2015-12-07 14:37:10 +0100150 uint32_t spsr;
Julius Werner8e0ef0f2019-07-09 14:02:43 -0700151#ifdef __aarch64__
Etienne Carriere911de8c2018-02-02 13:23:22 +0100152 unsigned int mode;
Jens Wiklander52c798e2015-12-07 14:37:10 +0100153
154 /* Figure out what mode we enter the non-secure world in */
Antonio Nino Diaz864ca6f2018-10-31 15:25:35 +0000155 mode = (el_implemented(2) != EL_IMPL_NONE) ? MODE_EL2 : MODE_EL1;
Jens Wiklander52c798e2015-12-07 14:37:10 +0100156
157 /*
158 * TODO: Consider the possibility of specifying the SPSR in
159 * the FIP ToC and allowing the platform to have a say as
160 * well.
161 */
162 spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
Etienne Carriere911de8c2018-02-02 13:23:22 +0100163#else
164 spsr = SPSR_MODE32(MODE32_svc,
165 plat_get_ns_image_entrypoint() & 0x1,
166 SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS);
167#endif
Jens Wiklander52c798e2015-12-07 14:37:10 +0100168 return spsr;
169}
170
Jens Wiklandera43c1282022-11-22 14:39:26 +0100171#if defined(SPD_spmd) && SPMD_SPM_AT_SEL2
172static int load_sps_from_tb_fw_config(struct image_info *image_info)
173{
174 void *dtb = (void *)image_info->image_base;
175 const char *compat_str = "arm,sp";
176 const struct fdt_property *uuid;
177 uint32_t load_addr;
178 const char *name;
179 int sp_node;
180 int node;
181
182 node = fdt_node_offset_by_compatible(dtb, -1, compat_str);
183 if (node < 0) {
184 ERROR("Can't find %s in TB_FW_CONFIG", compat_str);
185 return -1;
186 }
187
188 fdt_for_each_subnode(sp_node, dtb, node) {
189 name = fdt_get_name(dtb, sp_node, NULL);
190 if (name == NULL) {
191 ERROR("Can't get name of node in dtb\n");
192 return -1;
193 }
194 uuid = fdt_get_property(dtb, sp_node, "uuid", NULL);
195 if (uuid == NULL) {
196 ERROR("Can't find property uuid in node %s", name);
197 return -1;
198 }
199 if (fdt_read_uint32(dtb, sp_node, "load-address",
200 &load_addr) < 0) {
201 ERROR("Can't read load-address in node %s", name);
202 return -1;
203 }
204 if (qemu_io_register_sp_pkg(name, uuid->data, load_addr) < 0) {
205 return -1;
206 }
207 }
208
209 return 0;
210}
211#endif /*defined(SPD_spmd) && SPMD_SPM_AT_SEL2*/
212
Fu Weic2f78442017-05-27 21:21:42 +0800213static int qemu_bl2_handle_post_image_load(unsigned int image_id)
214{
215 int err = 0;
216 bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
Jens Wiklanderff263dc2021-05-25 18:15:11 +0200217#if defined(SPD_opteed) || defined(AARCH32_SP_OPTEE) || defined(SPMC_OPTEE)
Jens Wiklander0acbaaa2017-08-24 13:16:26 +0200218 bl_mem_params_node_t *pager_mem_params = NULL;
219 bl_mem_params_node_t *paged_mem_params = NULL;
220#endif
Jens Wiklanderff263dc2021-05-25 18:15:11 +0200221#if defined(SPD_spmd)
Jens Wiklanderd4b84f02022-11-18 15:40:04 +0100222 bl_mem_params_node_t *bl32_mem_params = NULL;
Jens Wiklanderff263dc2021-05-25 18:15:11 +0200223#endif
Fu Weic2f78442017-05-27 21:21:42 +0800224
225 assert(bl_mem_params);
226
227 switch (image_id) {
Fu Weic2f78442017-05-27 21:21:42 +0800228 case BL32_IMAGE_ID:
Jens Wiklanderff263dc2021-05-25 18:15:11 +0200229#if defined(SPD_opteed) || defined(AARCH32_SP_OPTEE) || defined(SPMC_OPTEE)
Jens Wiklander0acbaaa2017-08-24 13:16:26 +0200230 pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
231 assert(pager_mem_params);
232
233 paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
234 assert(paged_mem_params);
235
236 err = parse_optee_header(&bl_mem_params->ep_info,
237 &pager_mem_params->image_info,
238 &paged_mem_params->image_info);
239 if (err != 0) {
240 WARN("OPTEE header parse error.\n");
241 }
Jens Wiklanderff263dc2021-05-25 18:15:11 +0200242#endif
Jens Wiklander0acbaaa2017-08-24 13:16:26 +0200243
Jens Wiklanderd4b84f02022-11-18 15:40:04 +0100244#if defined(SPMC_OPTEE)
245 /*
246 * Explicit zeroes to unused registers since they may have
247 * been populated by parse_optee_header() above.
248 *
249 * OP-TEE expects system DTB in x2 and TOS_FW_CONFIG in x0,
250 * the latter is filled in below for TOS_FW_CONFIG_ID and
251 * applies to any other SPMC too.
252 */
253 bl_mem_params->ep_info.args.arg2 = ARM_PRELOADED_DTB_BASE;
Jens Wiklanderff263dc2021-05-25 18:15:11 +0200254#elif defined(SPD_opteed)
Jens Wiklander0acbaaa2017-08-24 13:16:26 +0200255 /*
256 * OP-TEE expect to receive DTB address in x2.
257 * This will be copied into x2 by dispatcher.
258 */
Andrew Walbran9c4d0692020-01-15 14:11:31 +0000259 bl_mem_params->ep_info.args.arg3 = ARM_PRELOADED_DTB_BASE;
Jens Wiklanderff263dc2021-05-25 18:15:11 +0200260#elif defined(AARCH32_SP_OPTEE)
Etienne Carriere911de8c2018-02-02 13:23:22 +0100261 bl_mem_params->ep_info.args.arg0 =
262 bl_mem_params->ep_info.args.arg1;
263 bl_mem_params->ep_info.args.arg1 = 0;
Andrew Walbran9c4d0692020-01-15 14:11:31 +0000264 bl_mem_params->ep_info.args.arg2 = ARM_PRELOADED_DTB_BASE;
Etienne Carriere911de8c2018-02-02 13:23:22 +0100265 bl_mem_params->ep_info.args.arg3 = 0;
266#endif
Fu Weic2f78442017-05-27 21:21:42 +0800267 bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl32_entry();
268 break;
Etienne Carriere911de8c2018-02-02 13:23:22 +0100269
Fu Weic2f78442017-05-27 21:21:42 +0800270 case BL33_IMAGE_ID:
Etienne Carriere911de8c2018-02-02 13:23:22 +0100271#ifdef AARCH32_SP_OPTEE
272 /* AArch32 only core: OP-TEE expects NSec EP in register LR */
273 pager_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID);
274 assert(pager_mem_params);
275 pager_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc;
276#endif
277
Andrew Walbran9c4d0692020-01-15 14:11:31 +0000278#if ARM_LINUX_KERNEL_AS_BL33
279 /*
280 * According to the file ``Documentation/arm64/booting.txt`` of
281 * the Linux kernel tree, Linux expects the physical address of
282 * the device tree blob (DTB) in x0, while x1-x3 are reserved
283 * for future use and must be 0.
284 */
285 bl_mem_params->ep_info.args.arg0 =
286 (u_register_t)ARM_PRELOADED_DTB_BASE;
287 bl_mem_params->ep_info.args.arg1 = 0U;
288 bl_mem_params->ep_info.args.arg2 = 0U;
289 bl_mem_params->ep_info.args.arg3 = 0U;
290#else
Fu Weic2f78442017-05-27 21:21:42 +0800291 /* BL33 expects to receive the primary CPU MPID (through r0) */
292 bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr();
Andrew Walbran9c4d0692020-01-15 14:11:31 +0000293#endif
294
Fu Weic2f78442017-05-27 21:21:42 +0800295 bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl33_entry();
296 break;
Jens Wiklandera43c1282022-11-22 14:39:26 +0100297#ifdef SPD_spmd
298#if SPMD_SPM_AT_SEL2
299 case TB_FW_CONFIG_ID:
300 err = load_sps_from_tb_fw_config(&bl_mem_params->image_info);
301 break;
302#endif
Jens Wiklanderd4b84f02022-11-18 15:40:04 +0100303 case TOS_FW_CONFIG_ID:
304 /* An SPMC expects TOS_FW_CONFIG in x0/r0 */
305 bl32_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID);
306 bl32_mem_params->ep_info.args.arg0 =
307 bl_mem_params->image_info.image_base;
308 break;
309#endif
Jonathan Wrightff957ed2018-03-14 15:24:00 +0000310 default:
311 /* Do nothing in default case */
312 break;
Fu Weic2f78442017-05-27 21:21:42 +0800313 }
314
315 return err;
316}
317
318/*******************************************************************************
319 * This function can be used by the platforms to update/use image
320 * information for given `image_id`.
321 ******************************************************************************/
322int bl2_plat_handle_post_image_load(unsigned int image_id)
323{
324 return qemu_bl2_handle_post_image_load(image_id);
325}
Jens Wiklander52c798e2015-12-07 14:37:10 +0100326
Etienne Carriere911de8c2018-02-02 13:23:22 +0100327uintptr_t plat_get_ns_image_entrypoint(void)
Jens Wiklander52c798e2015-12-07 14:37:10 +0100328{
329 return NS_IMAGE_OFFSET;
330}