blob: 768c3c52b5fca2c2827f0c6801ca9a8894bca3ed [file] [log] [blame]
James Morrissey9d72b4e2014-02-10 17:04:32 +00001/*
2 * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <assert.h>
32#include <string.h>
33#include "platform.h"
34#include "io_storage.h"
35#include "io_driver.h"
36#include "io_semihosting.h"
37#include "semihosting.h" /* For FOPEN_MODE_... */
Harry Liebel561cd332014-02-14 14:42:48 +000038#include "io_fip.h"
39#include "io_memmap.h"
James Morrissey9d72b4e2014-02-10 17:04:32 +000040#include "debug.h"
41
42
Harry Liebel561cd332014-02-14 14:42:48 +000043typedef struct {
44 char *image_name;
45 int (*image_policy)(io_dev_handle *dev_handle, void **image_spec);
46} plat_io_policy;
47
48
James Morrissey9d72b4e2014-02-10 17:04:32 +000049/* IO devices */
50static struct io_plat_data io_data;
51static struct io_dev_connector *sh_dev_con;
52static void *const sh_dev_spec;
53static void *const sh_init_params;
54static io_dev_handle sh_dev_handle;
Harry Liebel561cd332014-02-14 14:42:48 +000055static struct io_dev_connector *fip_dev_con;
56static void *const fip_dev_spec;
57static io_dev_handle fip_dev_handle;
58static struct io_dev_connector *memmap_dev_con;
59static void *const memmap_dev_spec;
60static void *const memmap_init_params;
61static io_dev_handle memmap_dev_handle;
James Morrissey9d72b4e2014-02-10 17:04:32 +000062
Harry Liebel561cd332014-02-14 14:42:48 +000063static int fvp_bl2_policy(io_dev_handle *dev_handle, void **image_spec);
64static int fvp_bl31_policy(io_dev_handle *dev_handle, void **image_spec);
Achin Gupta375f5382014-02-18 18:12:48 +000065static int fvp_bl32_policy(io_dev_handle *dev_handle, void **image_spec);
Harry Liebel561cd332014-02-14 14:42:48 +000066static int fvp_bl33_policy(io_dev_handle *dev_handle, void **image_spec);
67static int fvp_fip_policy(io_dev_handle *dev_handle, void **image_spec);
68
69
70static io_block_spec fip_block_spec = {
71 .offset = FLASH0_BASE,
72 .length = FLASH0_SIZE
73};
74
75static io_file_spec bl2_file_spec = {
James Morrissey9d72b4e2014-02-10 17:04:32 +000076 .path = BL2_IMAGE_NAME,
77 .mode = FOPEN_MODE_R
78};
79
Harry Liebel561cd332014-02-14 14:42:48 +000080static io_file_spec bl31_file_spec = {
James Morrissey9d72b4e2014-02-10 17:04:32 +000081 .path = BL31_IMAGE_NAME,
82 .mode = FOPEN_MODE_R
83};
84
Achin Gupta375f5382014-02-18 18:12:48 +000085static io_file_spec bl32_file_spec = {
86 .path = BL32_IMAGE_NAME,
87 .mode = FOPEN_MODE_R
88};
89
Harry Liebel561cd332014-02-14 14:42:48 +000090static io_file_spec bl33_file_spec = {
91 .path = BL33_IMAGE_NAME,
92 .mode = FOPEN_MODE_R
93};
James Morrissey9d72b4e2014-02-10 17:04:32 +000094
Harry Liebel561cd332014-02-14 14:42:48 +000095static plat_io_policy fvp_policy[] = {
96 {BL2_IMAGE_NAME, fvp_bl2_policy},
97 {BL31_IMAGE_NAME, fvp_bl31_policy},
Achin Gupta375f5382014-02-18 18:12:48 +000098 {BL32_IMAGE_NAME, fvp_bl32_policy},
Harry Liebel561cd332014-02-14 14:42:48 +000099 {BL33_IMAGE_NAME, fvp_bl33_policy},
100 {FIP_IMAGE_NAME, fvp_fip_policy},
101 {NULL, NULL}
102};
103
104
105static int open_fip(void *spec)
James Morrissey9d72b4e2014-02-10 17:04:32 +0000106{
Harry Liebel561cd332014-02-14 14:42:48 +0000107 int result = IO_FAIL;
108
109 /* See if a Firmware Image Package is available */
110 result = io_dev_init(fip_dev_handle, (void *)FIP_IMAGE_NAME);
111 if (result == IO_SUCCESS) {
112 INFO("Using FIP\n");
113 /*TODO: Check image defined in spec is present in FIP. */
114 }
115 return result;
116}
117
118
119static int open_memmap(void *spec)
120{
121 int result = IO_FAIL;
122 io_handle local_image_handle;
123
124 result = io_dev_init(memmap_dev_handle, memmap_init_params);
125 if (result == IO_SUCCESS) {
126 result = io_open(memmap_dev_handle, spec, &local_image_handle);
127 if (result == IO_SUCCESS) {
128 /* INFO("Using Memmap IO\n"); */
129 io_close(local_image_handle);
130 }
131 }
132 return result;
133}
134
135
136static int open_semihosting(void *spec)
137{
138 int result = IO_FAIL;
139 io_handle local_image_handle;
140
141 /* See if the file exists on semi-hosting.*/
142 result = io_dev_init(sh_dev_handle, sh_init_params);
143 if (result == IO_SUCCESS) {
144 result = io_open(sh_dev_handle, spec, &local_image_handle);
145 if (result == IO_SUCCESS) {
146 INFO("Using Semi-hosting IO\n");
147 io_close(local_image_handle);
148 }
149 }
150 return result;
151}
152
153
154/* Try to load BL2 from Firmware Image Package in FLASH first. If there is no
155 * FIP in FLASH or it is broken, try to load the file from semi-hosting.
156 */
157static int fvp_bl2_policy(io_dev_handle *dev_handle, void **image_spec)
158{
159 int result = IO_FAIL;
160 void *local_image_spec = &bl2_file_spec;
161
162 INFO("Loading BL2\n");
163 /* FIP first then fall back to semi-hosting */
164 result = open_fip(local_image_spec);
165 if (result == IO_SUCCESS) {
166 *dev_handle = fip_dev_handle;
167 *(io_file_spec **)image_spec = local_image_spec;
168 } else {
169 result = open_semihosting(local_image_spec);
170 if (result == IO_SUCCESS) {
171 *dev_handle = sh_dev_handle;
172 *(io_file_spec **)image_spec = local_image_spec;
173 }
174 }
175 return result;
176}
177
178
179/* Try to load BL31 from Firmware Image Package in FLASH first. If there is no
180 * FIP in FLASH or it is broken, try to load the file from semi-hosting.
181 */
182static int fvp_bl31_policy(io_dev_handle *dev_handle, void **image_spec)
183{
184 int result = IO_FAIL;
185 void *local_image_spec = &bl31_file_spec;
186
187 INFO("Loading BL31\n");
188 /* FIP first then fall back to semi-hosting */
189 result = open_fip(local_image_spec);
190 if (result == IO_SUCCESS) {
191 *dev_handle = fip_dev_handle;
192 *(io_file_spec **)image_spec = local_image_spec;
193 } else {
194 result = open_semihosting(local_image_spec);
195 if (result == IO_SUCCESS) {
196 *dev_handle = sh_dev_handle;
197 *(io_file_spec **)image_spec = local_image_spec;
198 }
199 }
200 return result;
201}
202
203
Achin Gupta375f5382014-02-18 18:12:48 +0000204/* Try to load BL32 from Firmware Image Package in FLASH first. If there is no
205 * FIP in FLASH or it is broken, try to load the file from semi-hosting.
206 */
207static int fvp_bl32_policy(io_dev_handle *dev_handle, void **image_spec)
208{
209 int result = IO_FAIL;
210 void *local_image_spec = &bl32_file_spec;
211
212 INFO("Loading BL32\n");
213 /* FIP first then fall back to semi-hosting */
214 result = open_fip(local_image_spec);
215 if (result == IO_SUCCESS) {
216 *dev_handle = fip_dev_handle;
217 *(io_file_spec **)image_spec = local_image_spec;
218 } else {
219 result = open_semihosting(local_image_spec);
220 if (result == IO_SUCCESS) {
221 *dev_handle = sh_dev_handle;
222 *(io_file_spec **)image_spec = local_image_spec;
223 }
224 }
225 return result;
226}
227
228
Harry Liebel561cd332014-02-14 14:42:48 +0000229/* Try to load BL33 from Firmware Image Package in FLASH first. If there is no
230 * FIP in FLASH or it is broken, try to load the file from semi-hosting.
231 */
232static int fvp_bl33_policy(io_dev_handle *dev_handle, void **image_spec)
233{
234 int result = IO_FAIL;
235 void *local_image_spec = &bl33_file_spec;
236
237 INFO("Loading BL33 (UEFI)\n");
238 /* FIP first then fall back to semi-hosting */
239 result = open_fip(local_image_spec);
240 if (result == IO_SUCCESS) {
241 *dev_handle = fip_dev_handle;
242 *(io_file_spec **)image_spec = local_image_spec;
243 } else {
244 result = open_semihosting(local_image_spec);
245 if (result == IO_SUCCESS) {
246 *dev_handle = sh_dev_handle;
247 *(io_file_spec **)image_spec = local_image_spec;
248 }
249 }
250 return result;
251}
252
253
254/* Try to find FIP on NOR FLASH */
255static int fvp_fip_policy(io_dev_handle *dev_handle, void **image_spec)
256{
257 int result = IO_FAIL;
258 void *local_image_spec = &fip_block_spec;
259
260 result = open_memmap(local_image_spec);
261 if (result == IO_SUCCESS) {
262 *dev_handle = memmap_dev_handle;
263 *(io_file_spec **)image_spec = local_image_spec;
264 }
265 return result;
266}
267
268
269void io_setup (void)
270{
271 int io_result = IO_FAIL;
272
James Morrissey9d72b4e2014-02-10 17:04:32 +0000273 /* Initialise the IO layer */
274 io_init(&io_data);
275
Harry Liebel561cd332014-02-14 14:42:48 +0000276 /* Register the IO devices on this platform */
277 io_result = register_io_dev_sh(&sh_dev_con);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000278 assert(io_result == IO_SUCCESS);
279
Harry Liebel561cd332014-02-14 14:42:48 +0000280 io_result = register_io_dev_fip(&fip_dev_con);
281 assert(io_result == IO_SUCCESS);
282
283 io_result = register_io_dev_memmap(&memmap_dev_con);
284 assert(io_result == IO_SUCCESS);
285
286 /* Open connections to devices and cache the handles */
James Morrissey9d72b4e2014-02-10 17:04:32 +0000287 io_result = io_dev_open(sh_dev_con, sh_dev_spec, &sh_dev_handle);
288 assert(io_result == IO_SUCCESS);
289
Harry Liebel561cd332014-02-14 14:42:48 +0000290 io_result = io_dev_open(fip_dev_con, fip_dev_spec, &fip_dev_handle);
291 assert(io_result == IO_SUCCESS);
292
293 io_result = io_dev_open(memmap_dev_con, memmap_dev_spec,
294 &memmap_dev_handle);
295 assert(io_result == IO_SUCCESS);
296
James Morrissey9d72b4e2014-02-10 17:04:32 +0000297 /* Ignore improbable errors in release builds */
298 (void)io_result;
299}
300
301
302/* Return an IO device handle and specification which can be used to access
Harry Liebel561cd332014-02-14 14:42:48 +0000303 * an image. Use this to enforce platform load policy */
James Morrissey9d72b4e2014-02-10 17:04:32 +0000304int plat_get_image_source(const char *image_name, io_dev_handle *dev_handle,
Harry Liebel561cd332014-02-14 14:42:48 +0000305 void **image_spec)
James Morrissey9d72b4e2014-02-10 17:04:32 +0000306{
307 int result = IO_FAIL;
Harry Liebel561cd332014-02-14 14:42:48 +0000308 plat_io_policy *policy;
James Morrissey9d72b4e2014-02-10 17:04:32 +0000309
Harry Liebel561cd332014-02-14 14:42:48 +0000310 assert(image_name != NULL);
311 assert(dev_handle != NULL);
312 assert(image_spec != NULL);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000313
Harry Liebel561cd332014-02-14 14:42:48 +0000314 policy = fvp_policy;
315 while ((policy->image_name != NULL) &&
316 (policy->image_policy != NULL)) {
317 result = strcmp(policy->image_name, image_name);
318 if (result == 0) {
319 result = policy->image_policy(dev_handle, image_spec);
320 break;
321 }
322 policy++;
323 }
James Morrissey9d72b4e2014-02-10 17:04:32 +0000324 return result;
325}