blob: fd2d2b28e860859899ffd72c9af664784f995abc [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;
62
63static 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);
65static int fvp_bl33_policy(io_dev_handle *dev_handle, void **image_spec);
66static int fvp_fip_policy(io_dev_handle *dev_handle, void **image_spec);
James Morrissey9d72b4e2014-02-10 17:04:32 +000067
Harry Liebel561cd332014-02-14 14:42:48 +000068
69static io_block_spec fip_block_spec = {
70 .offset = FLASH0_BASE,
71 .length = FLASH0_SIZE
72};
73
74static io_file_spec bl2_file_spec = {
James Morrissey9d72b4e2014-02-10 17:04:32 +000075 .path = BL2_IMAGE_NAME,
76 .mode = FOPEN_MODE_R
77};
78
Harry Liebel561cd332014-02-14 14:42:48 +000079static io_file_spec bl31_file_spec = {
James Morrissey9d72b4e2014-02-10 17:04:32 +000080 .path = BL31_IMAGE_NAME,
81 .mode = FOPEN_MODE_R
82};
83
Harry Liebel561cd332014-02-14 14:42:48 +000084static io_file_spec bl33_file_spec = {
85 .path = BL33_IMAGE_NAME,
86 .mode = FOPEN_MODE_R
87};
88
89static plat_io_policy fvp_policy[] = {
90 {BL2_IMAGE_NAME, fvp_bl2_policy},
91 {BL31_IMAGE_NAME, fvp_bl31_policy},
92 {BL33_IMAGE_NAME, fvp_bl33_policy},
93 {FIP_IMAGE_NAME, fvp_fip_policy},
94 {NULL, NULL}
95};
96
97
98static int open_fip(void *spec)
99{
100 int result = IO_FAIL;
101
102 /* See if a Firmware Image Package is available */
103 result = io_dev_init(fip_dev_handle, (void *)FIP_IMAGE_NAME);
104 if (result == IO_SUCCESS) {
105 INFO("Using FIP\n");
106 /*TODO: Check image defined in spec is present in FIP. */
107 }
108 return result;
109}
110
111
112static int open_memmap(void *spec)
113{
114 int result = IO_FAIL;
115 io_handle local_image_handle;
116
117 result = io_dev_init(memmap_dev_handle, memmap_init_params);
118 if (result == IO_SUCCESS) {
119 result = io_open(memmap_dev_handle, spec, &local_image_handle);
120 if (result == IO_SUCCESS) {
121 /* INFO("Using Memmap IO\n"); */
122 io_close(local_image_handle);
123 }
124 }
125 return result;
126}
127
128
129static int open_semihosting(void *spec)
130{
131 int result = IO_FAIL;
132 io_handle local_image_handle;
133
134 /* See if the file exists on semi-hosting.*/
135 result = io_dev_init(sh_dev_handle, sh_init_params);
136 if (result == IO_SUCCESS) {
137 result = io_open(sh_dev_handle, spec, &local_image_handle);
138 if (result == IO_SUCCESS) {
139 INFO("Using Semi-hosting IO\n");
140 io_close(local_image_handle);
141 }
142 }
143 return result;
144}
145
146
147/* Try to load BL2 from Firmware Image Package in FLASH first. If there is no
148 * FIP in FLASH or it is broken, try to load the file from semi-hosting.
149 */
150static int fvp_bl2_policy(io_dev_handle *dev_handle, void **image_spec)
151{
152 int result = IO_FAIL;
153 void *local_image_spec = &bl2_file_spec;
154
155 INFO("Loading BL2\n");
156 /* FIP first then fall back to semi-hosting */
157 result = open_fip(local_image_spec);
158 if (result == IO_SUCCESS) {
159 *dev_handle = fip_dev_handle;
160 *(io_file_spec **)image_spec = local_image_spec;
161 } else {
162 result = open_semihosting(local_image_spec);
163 if (result == IO_SUCCESS) {
164 *dev_handle = sh_dev_handle;
165 *(io_file_spec **)image_spec = local_image_spec;
166 }
167 }
168 return result;
169}
170
James Morrissey9d72b4e2014-02-10 17:04:32 +0000171
Harry Liebel561cd332014-02-14 14:42:48 +0000172/* Try to load BL31 from Firmware Image Package in FLASH first. If there is no
173 * FIP in FLASH or it is broken, try to load the file from semi-hosting.
174 */
175static int fvp_bl31_policy(io_dev_handle *dev_handle, void **image_spec)
James Morrissey9d72b4e2014-02-10 17:04:32 +0000176{
Harry Liebel561cd332014-02-14 14:42:48 +0000177 int result = IO_FAIL;
178 void *local_image_spec = &bl31_file_spec;
179
180 INFO("Loading BL31\n");
181 /* FIP first then fall back to semi-hosting */
182 result = open_fip(local_image_spec);
183 if (result == IO_SUCCESS) {
184 *dev_handle = fip_dev_handle;
185 *(io_file_spec **)image_spec = local_image_spec;
186 } else {
187 result = open_semihosting(local_image_spec);
188 if (result == IO_SUCCESS) {
189 *dev_handle = sh_dev_handle;
190 *(io_file_spec **)image_spec = local_image_spec;
191 }
192 }
193 return result;
194}
195
196
197/* Try to load BL33 from Firmware Image Package in FLASH first. If there is no
198 * FIP in FLASH or it is broken, try to load the file from semi-hosting.
199 */
200static int fvp_bl33_policy(io_dev_handle *dev_handle, void **image_spec)
201{
202 int result = IO_FAIL;
203 void *local_image_spec = &bl33_file_spec;
204
205 INFO("Loading BL33 (UEFI)\n");
206 /* FIP first then fall back to semi-hosting */
207 result = open_fip(local_image_spec);
208 if (result == IO_SUCCESS) {
209 *dev_handle = fip_dev_handle;
210 *(io_file_spec **)image_spec = local_image_spec;
211 } else {
212 result = open_semihosting(local_image_spec);
213 if (result == IO_SUCCESS) {
214 *dev_handle = sh_dev_handle;
215 *(io_file_spec **)image_spec = local_image_spec;
216 }
217 }
218 return result;
219}
220
221
222/* Try to find FIP on NOR FLASH */
223static int fvp_fip_policy(io_dev_handle *dev_handle, void **image_spec)
224{
225 int result = IO_FAIL;
226 void *local_image_spec = &fip_block_spec;
227
228 result = open_memmap(local_image_spec);
229 if (result == IO_SUCCESS) {
230 *dev_handle = memmap_dev_handle;
231 *(io_file_spec **)image_spec = local_image_spec;
232 }
233 return result;
234}
235
236
237void io_setup (void)
238{
239 int io_result = IO_FAIL;
240
James Morrissey9d72b4e2014-02-10 17:04:32 +0000241 /* Initialise the IO layer */
242 io_init(&io_data);
243
Harry Liebel561cd332014-02-14 14:42:48 +0000244 /* Register the IO devices on this platform */
245 io_result = register_io_dev_sh(&sh_dev_con);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000246 assert(io_result == IO_SUCCESS);
247
Harry Liebel561cd332014-02-14 14:42:48 +0000248 io_result = register_io_dev_fip(&fip_dev_con);
249 assert(io_result == IO_SUCCESS);
250
251 io_result = register_io_dev_memmap(&memmap_dev_con);
252 assert(io_result == IO_SUCCESS);
253
254 /* Open connections to devices and cache the handles */
James Morrissey9d72b4e2014-02-10 17:04:32 +0000255 io_result = io_dev_open(sh_dev_con, sh_dev_spec, &sh_dev_handle);
256 assert(io_result == IO_SUCCESS);
257
Harry Liebel561cd332014-02-14 14:42:48 +0000258 io_result = io_dev_open(fip_dev_con, fip_dev_spec, &fip_dev_handle);
259 assert(io_result == IO_SUCCESS);
260
261 io_result = io_dev_open(memmap_dev_con, memmap_dev_spec,
262 &memmap_dev_handle);
263 assert(io_result == IO_SUCCESS);
264
James Morrissey9d72b4e2014-02-10 17:04:32 +0000265 /* Ignore improbable errors in release builds */
266 (void)io_result;
267}
268
269
270/* Return an IO device handle and specification which can be used to access
Harry Liebel561cd332014-02-14 14:42:48 +0000271 * an image. Use this to enforce platform load policy */
James Morrissey9d72b4e2014-02-10 17:04:32 +0000272int plat_get_image_source(const char *image_name, io_dev_handle *dev_handle,
Harry Liebel561cd332014-02-14 14:42:48 +0000273 void **image_spec)
James Morrissey9d72b4e2014-02-10 17:04:32 +0000274{
275 int result = IO_FAIL;
Harry Liebel561cd332014-02-14 14:42:48 +0000276 plat_io_policy *policy;
James Morrissey9d72b4e2014-02-10 17:04:32 +0000277
Harry Liebel561cd332014-02-14 14:42:48 +0000278 assert(image_name != NULL);
279 assert(dev_handle != NULL);
280 assert(image_spec != NULL);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000281
Harry Liebel561cd332014-02-14 14:42:48 +0000282 policy = fvp_policy;
283 while ((policy->image_name != NULL) &&
284 (policy->image_policy != NULL)) {
285 result = strcmp(policy->image_name, image_name);
286 if (result == 0) {
287 result = policy->image_policy(dev_handle, image_spec);
288 break;
289 }
290 policy++;
291 }
James Morrissey9d72b4e2014-02-10 17:04:32 +0000292 return result;
293}