blob: 371f5671938691868f7d24a002902f7f7192f26e [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>
Dan Handley714a0d22014-04-09 13:13:04 +010033#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_... */
38#include <io_fip.h>
39#include <io_memmap.h>
40#include <debug.h>
James Morrissey9d72b4e2014-02-10 17:04:32 +000041
James Morrissey9d72b4e2014-02-10 17:04:32 +000042/* IO devices */
Dan Handleye2712bc2014-04-10 15:37:22 +010043static io_plat_data_t io_data;
44static io_dev_connector_t *sh_dev_con;
James Morrissey9d72b4e2014-02-10 17:04:32 +000045static void *const sh_dev_spec;
46static void *const sh_init_params;
47static io_dev_handle sh_dev_handle;
Dan Handleye2712bc2014-04-10 15:37:22 +010048static io_dev_connector_t *fip_dev_con;
Harry Liebel561cd332014-02-14 14:42:48 +000049static void *const fip_dev_spec;
50static io_dev_handle fip_dev_handle;
Dan Handleye2712bc2014-04-10 15:37:22 +010051static io_dev_connector_t *memmap_dev_con;
Harry Liebel561cd332014-02-14 14:42:48 +000052static void *const memmap_dev_spec;
53static void *const memmap_init_params;
54static io_dev_handle memmap_dev_handle;
55
Dan Handleye2712bc2014-04-10 15:37:22 +010056static io_block_spec_t fip_block_spec = {
Harry Liebel561cd332014-02-14 14:42:48 +000057 .offset = FLASH0_BASE,
58 .length = FLASH0_SIZE
59};
60
Dan Handleye2712bc2014-04-10 15:37:22 +010061static io_file_spec_t bl2_file_spec = {
James Morrissey9d72b4e2014-02-10 17:04:32 +000062 .path = BL2_IMAGE_NAME,
Sandrine Bailleuxa9de1bb2014-03-20 15:51:02 +000063 .mode = FOPEN_MODE_RB
James Morrissey9d72b4e2014-02-10 17:04:32 +000064};
65
Dan Handleye2712bc2014-04-10 15:37:22 +010066static io_file_spec_t bl31_file_spec = {
James Morrissey9d72b4e2014-02-10 17:04:32 +000067 .path = BL31_IMAGE_NAME,
Sandrine Bailleuxa9de1bb2014-03-20 15:51:02 +000068 .mode = FOPEN_MODE_RB
James Morrissey9d72b4e2014-02-10 17:04:32 +000069};
70
Dan Handleye2712bc2014-04-10 15:37:22 +010071static io_file_spec_t bl32_file_spec = {
Achin Gupta375f5382014-02-18 18:12:48 +000072 .path = BL32_IMAGE_NAME,
Sandrine Bailleuxa9de1bb2014-03-20 15:51:02 +000073 .mode = FOPEN_MODE_RB
Achin Gupta375f5382014-02-18 18:12:48 +000074};
75
Dan Handleye2712bc2014-04-10 15:37:22 +010076static io_file_spec_t bl33_file_spec = {
Harry Liebel561cd332014-02-14 14:42:48 +000077 .path = BL33_IMAGE_NAME,
Sandrine Bailleuxa9de1bb2014-03-20 15:51:02 +000078 .mode = FOPEN_MODE_RB
Harry Liebel561cd332014-02-14 14:42:48 +000079};
80
Ryan Harkin1bf80fc2014-02-18 17:40:24 +000081static int open_fip(void *spec);
82static int open_memmap(void *spec);
83
84struct plat_io_policy {
85 char *image_name;
86 io_dev_handle *dev_handle;
87 void *image_spec;
88 int (*check)(void *spec);
89};
90
91static struct plat_io_policy policies[] = {
92 { FIP_IMAGE_NAME, &memmap_dev_handle, &fip_block_spec, open_memmap },
93 { BL2_IMAGE_NAME, &fip_dev_handle, &bl2_file_spec, open_fip },
94 { BL31_IMAGE_NAME, &fip_dev_handle, &bl31_file_spec, open_fip },
95 { BL32_IMAGE_NAME, &fip_dev_handle, &bl32_file_spec, open_fip },
96 { BL33_IMAGE_NAME, &fip_dev_handle, &bl33_file_spec, open_fip },
97 {0, 0, 0 }
Harry Liebel561cd332014-02-14 14:42:48 +000098};
99
100
101static int open_fip(void *spec)
102{
103 int result = IO_FAIL;
104
105 /* See if a Firmware Image Package is available */
106 result = io_dev_init(fip_dev_handle, (void *)FIP_IMAGE_NAME);
107 if (result == IO_SUCCESS) {
108 INFO("Using FIP\n");
109 /*TODO: Check image defined in spec is present in FIP. */
110 }
111 return result;
112}
113
114
115static int open_memmap(void *spec)
116{
117 int result = IO_FAIL;
118 io_handle local_image_handle;
119
120 result = io_dev_init(memmap_dev_handle, memmap_init_params);
121 if (result == IO_SUCCESS) {
122 result = io_open(memmap_dev_handle, spec, &local_image_handle);
123 if (result == IO_SUCCESS) {
124 /* INFO("Using Memmap IO\n"); */
125 io_close(local_image_handle);
126 }
127 }
128 return result;
129}
130
131
132static int open_semihosting(void *spec)
133{
134 int result = IO_FAIL;
135 io_handle local_image_handle;
136
137 /* See if the file exists on semi-hosting.*/
138 result = io_dev_init(sh_dev_handle, sh_init_params);
139 if (result == IO_SUCCESS) {
140 result = io_open(sh_dev_handle, spec, &local_image_handle);
141 if (result == IO_SUCCESS) {
142 INFO("Using Semi-hosting IO\n");
143 io_close(local_image_handle);
144 }
145 }
146 return result;
147}
148
Harry Liebel561cd332014-02-14 14:42:48 +0000149void io_setup (void)
150{
151 int io_result = IO_FAIL;
152
James Morrissey9d72b4e2014-02-10 17:04:32 +0000153 /* Initialise the IO layer */
154 io_init(&io_data);
155
Harry Liebel561cd332014-02-14 14:42:48 +0000156 /* Register the IO devices on this platform */
157 io_result = register_io_dev_sh(&sh_dev_con);
James Morrissey9d72b4e2014-02-10 17:04:32 +0000158 assert(io_result == IO_SUCCESS);
159
Harry Liebel561cd332014-02-14 14:42:48 +0000160 io_result = register_io_dev_fip(&fip_dev_con);
161 assert(io_result == IO_SUCCESS);
162
163 io_result = register_io_dev_memmap(&memmap_dev_con);
164 assert(io_result == IO_SUCCESS);
165
166 /* Open connections to devices and cache the handles */
James Morrissey9d72b4e2014-02-10 17:04:32 +0000167 io_result = io_dev_open(sh_dev_con, sh_dev_spec, &sh_dev_handle);
168 assert(io_result == IO_SUCCESS);
169
Harry Liebel561cd332014-02-14 14:42:48 +0000170 io_result = io_dev_open(fip_dev_con, fip_dev_spec, &fip_dev_handle);
171 assert(io_result == IO_SUCCESS);
172
173 io_result = io_dev_open(memmap_dev_con, memmap_dev_spec,
174 &memmap_dev_handle);
175 assert(io_result == IO_SUCCESS);
176
James Morrissey9d72b4e2014-02-10 17:04:32 +0000177 /* Ignore improbable errors in release builds */
178 (void)io_result;
179}
180
181
182/* Return an IO device handle and specification which can be used to access
Harry Liebel561cd332014-02-14 14:42:48 +0000183 * an image. Use this to enforce platform load policy */
James Morrissey9d72b4e2014-02-10 17:04:32 +0000184int plat_get_image_source(const char *image_name, io_dev_handle *dev_handle,
Harry Liebel561cd332014-02-14 14:42:48 +0000185 void **image_spec)
James Morrissey9d72b4e2014-02-10 17:04:32 +0000186{
187 int result = IO_FAIL;
Ryan Harkin1bf80fc2014-02-18 17:40:24 +0000188 struct plat_io_policy *policy;
James Morrissey9d72b4e2014-02-10 17:04:32 +0000189
Ryan Harkin1bf80fc2014-02-18 17:40:24 +0000190 if ((image_name != NULL) && (dev_handle != NULL) &&
191 (image_spec != NULL)) {
192 policy = policies;
193 while (policy->image_name != NULL) {
194 if (strcmp(policy->image_name, image_name) == 0) {
195 result = policy->check(policy->image_spec);
196 if (result == IO_SUCCESS) {
Dan Handleye2712bc2014-04-10 15:37:22 +0100197 *(io_file_spec_t **)image_spec =
Ryan Harkin1bf80fc2014-02-18 17:40:24 +0000198 policy->image_spec;
199 *dev_handle = *(policy->dev_handle);
200 break;
201 } else {
202 result = open_semihosting(
203 policy->image_spec);
204 if (result == IO_SUCCESS) {
205 *dev_handle = sh_dev_handle;
Dan Handleye2712bc2014-04-10 15:37:22 +0100206 *(io_file_spec_t **)image_spec =
Ryan Harkin1bf80fc2014-02-18 17:40:24 +0000207 policy->image_spec;
208 }
209 }
210 }
211 policy++;
Harry Liebel561cd332014-02-14 14:42:48 +0000212 }
Ryan Harkin1bf80fc2014-02-18 17:40:24 +0000213 } else {
214 result = IO_FAIL;
Harry Liebel561cd332014-02-14 14:42:48 +0000215 }
James Morrissey9d72b4e2014-02-10 17:04:32 +0000216 return result;
217}