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