xref: /rk3399_ARM-atf/plat/qemu/common/qemu_io_storage.c (revision 301d27d998892c054dec925264f81b11dcd64822)
1*301d27d9SRadoslaw Biernacki /*
2*301d27d9SRadoslaw Biernacki  * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved.
3*301d27d9SRadoslaw Biernacki  *
4*301d27d9SRadoslaw Biernacki  * SPDX-License-Identifier: BSD-3-Clause
5*301d27d9SRadoslaw Biernacki  */
6*301d27d9SRadoslaw Biernacki 
7*301d27d9SRadoslaw Biernacki #include <assert.h>
8*301d27d9SRadoslaw Biernacki #include <string.h>
9*301d27d9SRadoslaw Biernacki 
10*301d27d9SRadoslaw Biernacki #include <platform_def.h>
11*301d27d9SRadoslaw Biernacki 
12*301d27d9SRadoslaw Biernacki #include <common/bl_common.h>
13*301d27d9SRadoslaw Biernacki #include <common/debug.h>
14*301d27d9SRadoslaw Biernacki #include <drivers/io/io_driver.h>
15*301d27d9SRadoslaw Biernacki #include <drivers/io/io_fip.h>
16*301d27d9SRadoslaw Biernacki #include <drivers/io/io_memmap.h>
17*301d27d9SRadoslaw Biernacki #include <drivers/io/io_semihosting.h>
18*301d27d9SRadoslaw Biernacki #include <drivers/io/io_storage.h>
19*301d27d9SRadoslaw Biernacki #include <lib/semihosting.h>
20*301d27d9SRadoslaw Biernacki #include <tools_share/firmware_image_package.h>
21*301d27d9SRadoslaw Biernacki 
22*301d27d9SRadoslaw Biernacki /* Semihosting filenames */
23*301d27d9SRadoslaw Biernacki #define BL2_IMAGE_NAME			"bl2.bin"
24*301d27d9SRadoslaw Biernacki #define BL31_IMAGE_NAME			"bl31.bin"
25*301d27d9SRadoslaw Biernacki #define BL32_IMAGE_NAME			"bl32.bin"
26*301d27d9SRadoslaw Biernacki #define BL32_EXTRA1_IMAGE_NAME		"bl32_extra1.bin"
27*301d27d9SRadoslaw Biernacki #define BL32_EXTRA2_IMAGE_NAME		"bl32_extra2.bin"
28*301d27d9SRadoslaw Biernacki #define BL33_IMAGE_NAME			"bl33.bin"
29*301d27d9SRadoslaw Biernacki 
30*301d27d9SRadoslaw Biernacki #if TRUSTED_BOARD_BOOT
31*301d27d9SRadoslaw Biernacki #define TRUSTED_BOOT_FW_CERT_NAME	"tb_fw.crt"
32*301d27d9SRadoslaw Biernacki #define TRUSTED_KEY_CERT_NAME		"trusted_key.crt"
33*301d27d9SRadoslaw Biernacki #define SOC_FW_KEY_CERT_NAME		"soc_fw_key.crt"
34*301d27d9SRadoslaw Biernacki #define TOS_FW_KEY_CERT_NAME		"tos_fw_key.crt"
35*301d27d9SRadoslaw Biernacki #define NT_FW_KEY_CERT_NAME		"nt_fw_key.crt"
36*301d27d9SRadoslaw Biernacki #define SOC_FW_CONTENT_CERT_NAME	"soc_fw_content.crt"
37*301d27d9SRadoslaw Biernacki #define TOS_FW_CONTENT_CERT_NAME	"tos_fw_content.crt"
38*301d27d9SRadoslaw Biernacki #define NT_FW_CONTENT_CERT_NAME		"nt_fw_content.crt"
39*301d27d9SRadoslaw Biernacki #endif /* TRUSTED_BOARD_BOOT */
40*301d27d9SRadoslaw Biernacki 
41*301d27d9SRadoslaw Biernacki 
42*301d27d9SRadoslaw Biernacki 
43*301d27d9SRadoslaw Biernacki /* IO devices */
44*301d27d9SRadoslaw Biernacki static const io_dev_connector_t *fip_dev_con;
45*301d27d9SRadoslaw Biernacki static uintptr_t fip_dev_handle;
46*301d27d9SRadoslaw Biernacki static const io_dev_connector_t *memmap_dev_con;
47*301d27d9SRadoslaw Biernacki static uintptr_t memmap_dev_handle;
48*301d27d9SRadoslaw Biernacki static const io_dev_connector_t *sh_dev_con;
49*301d27d9SRadoslaw Biernacki static uintptr_t sh_dev_handle;
50*301d27d9SRadoslaw Biernacki 
51*301d27d9SRadoslaw Biernacki static const io_block_spec_t fip_block_spec = {
52*301d27d9SRadoslaw Biernacki 	.offset = PLAT_QEMU_FIP_BASE,
53*301d27d9SRadoslaw Biernacki 	.length = PLAT_QEMU_FIP_MAX_SIZE
54*301d27d9SRadoslaw Biernacki };
55*301d27d9SRadoslaw Biernacki 
56*301d27d9SRadoslaw Biernacki static const io_uuid_spec_t bl2_uuid_spec = {
57*301d27d9SRadoslaw Biernacki 	.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
58*301d27d9SRadoslaw Biernacki };
59*301d27d9SRadoslaw Biernacki 
60*301d27d9SRadoslaw Biernacki static const io_uuid_spec_t bl31_uuid_spec = {
61*301d27d9SRadoslaw Biernacki 	.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
62*301d27d9SRadoslaw Biernacki };
63*301d27d9SRadoslaw Biernacki 
64*301d27d9SRadoslaw Biernacki static const io_uuid_spec_t bl32_uuid_spec = {
65*301d27d9SRadoslaw Biernacki 	.uuid = UUID_SECURE_PAYLOAD_BL32,
66*301d27d9SRadoslaw Biernacki };
67*301d27d9SRadoslaw Biernacki 
68*301d27d9SRadoslaw Biernacki static const io_uuid_spec_t bl32_extra1_uuid_spec = {
69*301d27d9SRadoslaw Biernacki 	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
70*301d27d9SRadoslaw Biernacki };
71*301d27d9SRadoslaw Biernacki 
72*301d27d9SRadoslaw Biernacki static const io_uuid_spec_t bl32_extra2_uuid_spec = {
73*301d27d9SRadoslaw Biernacki 	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
74*301d27d9SRadoslaw Biernacki };
75*301d27d9SRadoslaw Biernacki 
76*301d27d9SRadoslaw Biernacki static const io_uuid_spec_t bl33_uuid_spec = {
77*301d27d9SRadoslaw Biernacki 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
78*301d27d9SRadoslaw Biernacki };
79*301d27d9SRadoslaw Biernacki 
80*301d27d9SRadoslaw Biernacki #if TRUSTED_BOARD_BOOT
81*301d27d9SRadoslaw Biernacki static const io_uuid_spec_t tb_fw_cert_uuid_spec = {
82*301d27d9SRadoslaw Biernacki 	.uuid = UUID_TRUSTED_BOOT_FW_CERT,
83*301d27d9SRadoslaw Biernacki };
84*301d27d9SRadoslaw Biernacki 
85*301d27d9SRadoslaw Biernacki static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
86*301d27d9SRadoslaw Biernacki 	.uuid = UUID_TRUSTED_KEY_CERT,
87*301d27d9SRadoslaw Biernacki };
88*301d27d9SRadoslaw Biernacki 
89*301d27d9SRadoslaw Biernacki static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = {
90*301d27d9SRadoslaw Biernacki 	.uuid = UUID_SOC_FW_KEY_CERT,
91*301d27d9SRadoslaw Biernacki };
92*301d27d9SRadoslaw Biernacki 
93*301d27d9SRadoslaw Biernacki static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = {
94*301d27d9SRadoslaw Biernacki 	.uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
95*301d27d9SRadoslaw Biernacki };
96*301d27d9SRadoslaw Biernacki 
97*301d27d9SRadoslaw Biernacki static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = {
98*301d27d9SRadoslaw Biernacki 	.uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
99*301d27d9SRadoslaw Biernacki };
100*301d27d9SRadoslaw Biernacki 
101*301d27d9SRadoslaw Biernacki static const io_uuid_spec_t soc_fw_cert_uuid_spec = {
102*301d27d9SRadoslaw Biernacki 	.uuid = UUID_SOC_FW_CONTENT_CERT,
103*301d27d9SRadoslaw Biernacki };
104*301d27d9SRadoslaw Biernacki 
105*301d27d9SRadoslaw Biernacki static const io_uuid_spec_t tos_fw_cert_uuid_spec = {
106*301d27d9SRadoslaw Biernacki 	.uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
107*301d27d9SRadoslaw Biernacki };
108*301d27d9SRadoslaw Biernacki 
109*301d27d9SRadoslaw Biernacki static const io_uuid_spec_t nt_fw_cert_uuid_spec = {
110*301d27d9SRadoslaw Biernacki 	.uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
111*301d27d9SRadoslaw Biernacki };
112*301d27d9SRadoslaw Biernacki #endif /* TRUSTED_BOARD_BOOT */
113*301d27d9SRadoslaw Biernacki 
114*301d27d9SRadoslaw Biernacki static const io_file_spec_t sh_file_spec[] = {
115*301d27d9SRadoslaw Biernacki 	[BL2_IMAGE_ID] = {
116*301d27d9SRadoslaw Biernacki 		.path = BL2_IMAGE_NAME,
117*301d27d9SRadoslaw Biernacki 		.mode = FOPEN_MODE_RB
118*301d27d9SRadoslaw Biernacki 	},
119*301d27d9SRadoslaw Biernacki 	[BL31_IMAGE_ID] = {
120*301d27d9SRadoslaw Biernacki 		.path = BL31_IMAGE_NAME,
121*301d27d9SRadoslaw Biernacki 		.mode = FOPEN_MODE_RB
122*301d27d9SRadoslaw Biernacki 	},
123*301d27d9SRadoslaw Biernacki 	[BL32_IMAGE_ID] = {
124*301d27d9SRadoslaw Biernacki 		.path = BL32_IMAGE_NAME,
125*301d27d9SRadoslaw Biernacki 		.mode = FOPEN_MODE_RB
126*301d27d9SRadoslaw Biernacki 	},
127*301d27d9SRadoslaw Biernacki 	[BL32_EXTRA1_IMAGE_ID] = {
128*301d27d9SRadoslaw Biernacki 		.path = BL32_EXTRA1_IMAGE_NAME,
129*301d27d9SRadoslaw Biernacki 		.mode = FOPEN_MODE_RB
130*301d27d9SRadoslaw Biernacki 	},
131*301d27d9SRadoslaw Biernacki 	[BL32_EXTRA2_IMAGE_ID] = {
132*301d27d9SRadoslaw Biernacki 		.path = BL32_EXTRA2_IMAGE_NAME,
133*301d27d9SRadoslaw Biernacki 		.mode = FOPEN_MODE_RB
134*301d27d9SRadoslaw Biernacki 	},
135*301d27d9SRadoslaw Biernacki 	[BL33_IMAGE_ID] = {
136*301d27d9SRadoslaw Biernacki 		.path = BL33_IMAGE_NAME,
137*301d27d9SRadoslaw Biernacki 		.mode = FOPEN_MODE_RB
138*301d27d9SRadoslaw Biernacki 	},
139*301d27d9SRadoslaw Biernacki #if TRUSTED_BOARD_BOOT
140*301d27d9SRadoslaw Biernacki 	[TRUSTED_BOOT_FW_CERT_ID] = {
141*301d27d9SRadoslaw Biernacki 		.path = TRUSTED_BOOT_FW_CERT_NAME,
142*301d27d9SRadoslaw Biernacki 		.mode = FOPEN_MODE_RB
143*301d27d9SRadoslaw Biernacki 	},
144*301d27d9SRadoslaw Biernacki 	[TRUSTED_KEY_CERT_ID] = {
145*301d27d9SRadoslaw Biernacki 		.path = TRUSTED_KEY_CERT_NAME,
146*301d27d9SRadoslaw Biernacki 		.mode = FOPEN_MODE_RB
147*301d27d9SRadoslaw Biernacki 	},
148*301d27d9SRadoslaw Biernacki 	[SOC_FW_KEY_CERT_ID] = {
149*301d27d9SRadoslaw Biernacki 		.path = SOC_FW_KEY_CERT_NAME,
150*301d27d9SRadoslaw Biernacki 		.mode = FOPEN_MODE_RB
151*301d27d9SRadoslaw Biernacki 	},
152*301d27d9SRadoslaw Biernacki 	[TRUSTED_OS_FW_KEY_CERT_ID] = {
153*301d27d9SRadoslaw Biernacki 		.path = TOS_FW_KEY_CERT_NAME,
154*301d27d9SRadoslaw Biernacki 		.mode = FOPEN_MODE_RB
155*301d27d9SRadoslaw Biernacki 	},
156*301d27d9SRadoslaw Biernacki 	[NON_TRUSTED_FW_KEY_CERT_ID] = {
157*301d27d9SRadoslaw Biernacki 		.path = NT_FW_KEY_CERT_NAME,
158*301d27d9SRadoslaw Biernacki 		.mode = FOPEN_MODE_RB
159*301d27d9SRadoslaw Biernacki 	},
160*301d27d9SRadoslaw Biernacki 	[SOC_FW_CONTENT_CERT_ID] = {
161*301d27d9SRadoslaw Biernacki 		.path = SOC_FW_CONTENT_CERT_NAME,
162*301d27d9SRadoslaw Biernacki 		.mode = FOPEN_MODE_RB
163*301d27d9SRadoslaw Biernacki 	},
164*301d27d9SRadoslaw Biernacki 	[TRUSTED_OS_FW_CONTENT_CERT_ID] = {
165*301d27d9SRadoslaw Biernacki 		.path = TOS_FW_CONTENT_CERT_NAME,
166*301d27d9SRadoslaw Biernacki 		.mode = FOPEN_MODE_RB
167*301d27d9SRadoslaw Biernacki 	},
168*301d27d9SRadoslaw Biernacki 	[NON_TRUSTED_FW_CONTENT_CERT_ID] = {
169*301d27d9SRadoslaw Biernacki 		.path = NT_FW_CONTENT_CERT_NAME,
170*301d27d9SRadoslaw Biernacki 		.mode = FOPEN_MODE_RB
171*301d27d9SRadoslaw Biernacki 	},
172*301d27d9SRadoslaw Biernacki #endif /* TRUSTED_BOARD_BOOT */
173*301d27d9SRadoslaw Biernacki };
174*301d27d9SRadoslaw Biernacki 
175*301d27d9SRadoslaw Biernacki 
176*301d27d9SRadoslaw Biernacki 
177*301d27d9SRadoslaw Biernacki static int open_fip(const uintptr_t spec);
178*301d27d9SRadoslaw Biernacki static int open_memmap(const uintptr_t spec);
179*301d27d9SRadoslaw Biernacki 
180*301d27d9SRadoslaw Biernacki struct plat_io_policy {
181*301d27d9SRadoslaw Biernacki 	uintptr_t *dev_handle;
182*301d27d9SRadoslaw Biernacki 	uintptr_t image_spec;
183*301d27d9SRadoslaw Biernacki 	int (*check)(const uintptr_t spec);
184*301d27d9SRadoslaw Biernacki };
185*301d27d9SRadoslaw Biernacki 
186*301d27d9SRadoslaw Biernacki /* By default, ARM platforms load images from the FIP */
187*301d27d9SRadoslaw Biernacki static const struct plat_io_policy policies[] = {
188*301d27d9SRadoslaw Biernacki 	[FIP_IMAGE_ID] = {
189*301d27d9SRadoslaw Biernacki 		&memmap_dev_handle,
190*301d27d9SRadoslaw Biernacki 		(uintptr_t)&fip_block_spec,
191*301d27d9SRadoslaw Biernacki 		open_memmap
192*301d27d9SRadoslaw Biernacki 	},
193*301d27d9SRadoslaw Biernacki 	[BL2_IMAGE_ID] = {
194*301d27d9SRadoslaw Biernacki 		&fip_dev_handle,
195*301d27d9SRadoslaw Biernacki 		(uintptr_t)&bl2_uuid_spec,
196*301d27d9SRadoslaw Biernacki 		open_fip
197*301d27d9SRadoslaw Biernacki 	},
198*301d27d9SRadoslaw Biernacki 	[BL31_IMAGE_ID] = {
199*301d27d9SRadoslaw Biernacki 		&fip_dev_handle,
200*301d27d9SRadoslaw Biernacki 		(uintptr_t)&bl31_uuid_spec,
201*301d27d9SRadoslaw Biernacki 		open_fip
202*301d27d9SRadoslaw Biernacki 	},
203*301d27d9SRadoslaw Biernacki 	[BL32_IMAGE_ID] = {
204*301d27d9SRadoslaw Biernacki 		&fip_dev_handle,
205*301d27d9SRadoslaw Biernacki 		(uintptr_t)&bl32_uuid_spec,
206*301d27d9SRadoslaw Biernacki 		open_fip
207*301d27d9SRadoslaw Biernacki 	},
208*301d27d9SRadoslaw Biernacki 	[BL32_EXTRA1_IMAGE_ID] = {
209*301d27d9SRadoslaw Biernacki 		&fip_dev_handle,
210*301d27d9SRadoslaw Biernacki 		(uintptr_t)&bl32_extra1_uuid_spec,
211*301d27d9SRadoslaw Biernacki 		open_fip
212*301d27d9SRadoslaw Biernacki 	},
213*301d27d9SRadoslaw Biernacki 	[BL32_EXTRA2_IMAGE_ID] = {
214*301d27d9SRadoslaw Biernacki 		&fip_dev_handle,
215*301d27d9SRadoslaw Biernacki 		(uintptr_t)&bl32_extra2_uuid_spec,
216*301d27d9SRadoslaw Biernacki 		open_fip
217*301d27d9SRadoslaw Biernacki 	},
218*301d27d9SRadoslaw Biernacki 	[BL33_IMAGE_ID] = {
219*301d27d9SRadoslaw Biernacki 		&fip_dev_handle,
220*301d27d9SRadoslaw Biernacki 		(uintptr_t)&bl33_uuid_spec,
221*301d27d9SRadoslaw Biernacki 		open_fip
222*301d27d9SRadoslaw Biernacki 	},
223*301d27d9SRadoslaw Biernacki #if TRUSTED_BOARD_BOOT
224*301d27d9SRadoslaw Biernacki 	[TRUSTED_BOOT_FW_CERT_ID] = {
225*301d27d9SRadoslaw Biernacki 		&fip_dev_handle,
226*301d27d9SRadoslaw Biernacki 		(uintptr_t)&tb_fw_cert_uuid_spec,
227*301d27d9SRadoslaw Biernacki 		open_fip
228*301d27d9SRadoslaw Biernacki 	},
229*301d27d9SRadoslaw Biernacki 	[TRUSTED_KEY_CERT_ID] = {
230*301d27d9SRadoslaw Biernacki 		&fip_dev_handle,
231*301d27d9SRadoslaw Biernacki 		(uintptr_t)&trusted_key_cert_uuid_spec,
232*301d27d9SRadoslaw Biernacki 		open_fip
233*301d27d9SRadoslaw Biernacki 	},
234*301d27d9SRadoslaw Biernacki 	[SOC_FW_KEY_CERT_ID] = {
235*301d27d9SRadoslaw Biernacki 		&fip_dev_handle,
236*301d27d9SRadoslaw Biernacki 		(uintptr_t)&soc_fw_key_cert_uuid_spec,
237*301d27d9SRadoslaw Biernacki 		open_fip
238*301d27d9SRadoslaw Biernacki 	},
239*301d27d9SRadoslaw Biernacki 	[TRUSTED_OS_FW_KEY_CERT_ID] = {
240*301d27d9SRadoslaw Biernacki 		&fip_dev_handle,
241*301d27d9SRadoslaw Biernacki 		(uintptr_t)&tos_fw_key_cert_uuid_spec,
242*301d27d9SRadoslaw Biernacki 		open_fip
243*301d27d9SRadoslaw Biernacki 	},
244*301d27d9SRadoslaw Biernacki 	[NON_TRUSTED_FW_KEY_CERT_ID] = {
245*301d27d9SRadoslaw Biernacki 		&fip_dev_handle,
246*301d27d9SRadoslaw Biernacki 		(uintptr_t)&nt_fw_key_cert_uuid_spec,
247*301d27d9SRadoslaw Biernacki 		open_fip
248*301d27d9SRadoslaw Biernacki 	},
249*301d27d9SRadoslaw Biernacki 	[SOC_FW_CONTENT_CERT_ID] = {
250*301d27d9SRadoslaw Biernacki 		&fip_dev_handle,
251*301d27d9SRadoslaw Biernacki 		(uintptr_t)&soc_fw_cert_uuid_spec,
252*301d27d9SRadoslaw Biernacki 		open_fip
253*301d27d9SRadoslaw Biernacki 	},
254*301d27d9SRadoslaw Biernacki 	[TRUSTED_OS_FW_CONTENT_CERT_ID] = {
255*301d27d9SRadoslaw Biernacki 		&fip_dev_handle,
256*301d27d9SRadoslaw Biernacki 		(uintptr_t)&tos_fw_cert_uuid_spec,
257*301d27d9SRadoslaw Biernacki 		open_fip
258*301d27d9SRadoslaw Biernacki 	},
259*301d27d9SRadoslaw Biernacki 	[NON_TRUSTED_FW_CONTENT_CERT_ID] = {
260*301d27d9SRadoslaw Biernacki 		&fip_dev_handle,
261*301d27d9SRadoslaw Biernacki 		(uintptr_t)&nt_fw_cert_uuid_spec,
262*301d27d9SRadoslaw Biernacki 		open_fip
263*301d27d9SRadoslaw Biernacki 	},
264*301d27d9SRadoslaw Biernacki #endif /* TRUSTED_BOARD_BOOT */
265*301d27d9SRadoslaw Biernacki };
266*301d27d9SRadoslaw Biernacki 
267*301d27d9SRadoslaw Biernacki static int open_fip(const uintptr_t spec)
268*301d27d9SRadoslaw Biernacki {
269*301d27d9SRadoslaw Biernacki 	int result;
270*301d27d9SRadoslaw Biernacki 	uintptr_t local_image_handle;
271*301d27d9SRadoslaw Biernacki 
272*301d27d9SRadoslaw Biernacki 	/* See if a Firmware Image Package is available */
273*301d27d9SRadoslaw Biernacki 	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
274*301d27d9SRadoslaw Biernacki 	if (result == 0) {
275*301d27d9SRadoslaw Biernacki 		result = io_open(fip_dev_handle, spec, &local_image_handle);
276*301d27d9SRadoslaw Biernacki 		if (result == 0) {
277*301d27d9SRadoslaw Biernacki 			VERBOSE("Using FIP\n");
278*301d27d9SRadoslaw Biernacki 			io_close(local_image_handle);
279*301d27d9SRadoslaw Biernacki 		}
280*301d27d9SRadoslaw Biernacki 	}
281*301d27d9SRadoslaw Biernacki 	return result;
282*301d27d9SRadoslaw Biernacki }
283*301d27d9SRadoslaw Biernacki 
284*301d27d9SRadoslaw Biernacki static int open_memmap(const uintptr_t spec)
285*301d27d9SRadoslaw Biernacki {
286*301d27d9SRadoslaw Biernacki 	int result;
287*301d27d9SRadoslaw Biernacki 	uintptr_t local_image_handle;
288*301d27d9SRadoslaw Biernacki 
289*301d27d9SRadoslaw Biernacki 	result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
290*301d27d9SRadoslaw Biernacki 	if (result == 0) {
291*301d27d9SRadoslaw Biernacki 		result = io_open(memmap_dev_handle, spec, &local_image_handle);
292*301d27d9SRadoslaw Biernacki 		if (result == 0) {
293*301d27d9SRadoslaw Biernacki 			VERBOSE("Using Memmap\n");
294*301d27d9SRadoslaw Biernacki 			io_close(local_image_handle);
295*301d27d9SRadoslaw Biernacki 		}
296*301d27d9SRadoslaw Biernacki 	}
297*301d27d9SRadoslaw Biernacki 	return result;
298*301d27d9SRadoslaw Biernacki }
299*301d27d9SRadoslaw Biernacki 
300*301d27d9SRadoslaw Biernacki static int open_semihosting(const uintptr_t spec)
301*301d27d9SRadoslaw Biernacki {
302*301d27d9SRadoslaw Biernacki 	int result;
303*301d27d9SRadoslaw Biernacki 	uintptr_t local_image_handle;
304*301d27d9SRadoslaw Biernacki 
305*301d27d9SRadoslaw Biernacki 	/* See if the file exists on semi-hosting.*/
306*301d27d9SRadoslaw Biernacki 	result = io_dev_init(sh_dev_handle, (uintptr_t)NULL);
307*301d27d9SRadoslaw Biernacki 	if (result == 0) {
308*301d27d9SRadoslaw Biernacki 		result = io_open(sh_dev_handle, spec, &local_image_handle);
309*301d27d9SRadoslaw Biernacki 		if (result == 0) {
310*301d27d9SRadoslaw Biernacki 			VERBOSE("Using Semi-hosting IO\n");
311*301d27d9SRadoslaw Biernacki 			io_close(local_image_handle);
312*301d27d9SRadoslaw Biernacki 		}
313*301d27d9SRadoslaw Biernacki 	}
314*301d27d9SRadoslaw Biernacki 	return result;
315*301d27d9SRadoslaw Biernacki }
316*301d27d9SRadoslaw Biernacki 
317*301d27d9SRadoslaw Biernacki void plat_qemu_io_setup(void)
318*301d27d9SRadoslaw Biernacki {
319*301d27d9SRadoslaw Biernacki 	int io_result;
320*301d27d9SRadoslaw Biernacki 
321*301d27d9SRadoslaw Biernacki 	io_result = register_io_dev_fip(&fip_dev_con);
322*301d27d9SRadoslaw Biernacki 	assert(io_result == 0);
323*301d27d9SRadoslaw Biernacki 
324*301d27d9SRadoslaw Biernacki 	io_result = register_io_dev_memmap(&memmap_dev_con);
325*301d27d9SRadoslaw Biernacki 	assert(io_result == 0);
326*301d27d9SRadoslaw Biernacki 
327*301d27d9SRadoslaw Biernacki 	/* Open connections to devices and cache the handles */
328*301d27d9SRadoslaw Biernacki 	io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
329*301d27d9SRadoslaw Biernacki 				&fip_dev_handle);
330*301d27d9SRadoslaw Biernacki 	assert(io_result == 0);
331*301d27d9SRadoslaw Biernacki 
332*301d27d9SRadoslaw Biernacki 	io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
333*301d27d9SRadoslaw Biernacki 				&memmap_dev_handle);
334*301d27d9SRadoslaw Biernacki 	assert(io_result == 0);
335*301d27d9SRadoslaw Biernacki 
336*301d27d9SRadoslaw Biernacki 	/* Register the additional IO devices on this platform */
337*301d27d9SRadoslaw Biernacki 	io_result = register_io_dev_sh(&sh_dev_con);
338*301d27d9SRadoslaw Biernacki 	assert(io_result == 0);
339*301d27d9SRadoslaw Biernacki 
340*301d27d9SRadoslaw Biernacki 	/* Open connections to devices and cache the handles */
341*301d27d9SRadoslaw Biernacki 	io_result = io_dev_open(sh_dev_con, (uintptr_t)NULL, &sh_dev_handle);
342*301d27d9SRadoslaw Biernacki 	assert(io_result == 0);
343*301d27d9SRadoslaw Biernacki 
344*301d27d9SRadoslaw Biernacki 	/* Ignore improbable errors in release builds */
345*301d27d9SRadoslaw Biernacki 	(void)io_result;
346*301d27d9SRadoslaw Biernacki }
347*301d27d9SRadoslaw Biernacki 
348*301d27d9SRadoslaw Biernacki static int get_alt_image_source(unsigned int image_id, uintptr_t *dev_handle,
349*301d27d9SRadoslaw Biernacki 				  uintptr_t *image_spec)
350*301d27d9SRadoslaw Biernacki {
351*301d27d9SRadoslaw Biernacki 	int result = open_semihosting((const uintptr_t)&sh_file_spec[image_id]);
352*301d27d9SRadoslaw Biernacki 
353*301d27d9SRadoslaw Biernacki 	if (result == 0) {
354*301d27d9SRadoslaw Biernacki 		*dev_handle = sh_dev_handle;
355*301d27d9SRadoslaw Biernacki 		*image_spec = (uintptr_t)&sh_file_spec[image_id];
356*301d27d9SRadoslaw Biernacki 	}
357*301d27d9SRadoslaw Biernacki 
358*301d27d9SRadoslaw Biernacki 	return result;
359*301d27d9SRadoslaw Biernacki }
360*301d27d9SRadoslaw Biernacki 
361*301d27d9SRadoslaw Biernacki /*
362*301d27d9SRadoslaw Biernacki  * Return an IO device handle and specification which can be used to access
363*301d27d9SRadoslaw Biernacki  * an image. Use this to enforce platform load policy
364*301d27d9SRadoslaw Biernacki  */
365*301d27d9SRadoslaw Biernacki int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
366*301d27d9SRadoslaw Biernacki 			  uintptr_t *image_spec)
367*301d27d9SRadoslaw Biernacki {
368*301d27d9SRadoslaw Biernacki 	int result;
369*301d27d9SRadoslaw Biernacki 	const struct plat_io_policy *policy;
370*301d27d9SRadoslaw Biernacki 
371*301d27d9SRadoslaw Biernacki 	assert(image_id < ARRAY_SIZE(policies));
372*301d27d9SRadoslaw Biernacki 
373*301d27d9SRadoslaw Biernacki 	policy = &policies[image_id];
374*301d27d9SRadoslaw Biernacki 	result = policy->check(policy->image_spec);
375*301d27d9SRadoslaw Biernacki 	if (result == 0) {
376*301d27d9SRadoslaw Biernacki 		*image_spec = policy->image_spec;
377*301d27d9SRadoslaw Biernacki 		*dev_handle = *(policy->dev_handle);
378*301d27d9SRadoslaw Biernacki 	} else {
379*301d27d9SRadoslaw Biernacki 		VERBOSE("Trying alternative IO\n");
380*301d27d9SRadoslaw Biernacki 		result = get_alt_image_source(image_id, dev_handle, image_spec);
381*301d27d9SRadoslaw Biernacki 	}
382*301d27d9SRadoslaw Biernacki 
383*301d27d9SRadoslaw Biernacki 	return result;
384*301d27d9SRadoslaw Biernacki }
385