1 /*
2  * Copyright (C) 2018 Marvell International Ltd.
3  *
4  * SPDX-License-Identifier:     BSD-3-Clause
5  * https://spdx.org/licenses
6  */
7 
8 #include <assert.h>
9 #include <string.h>
10 
11 #include <platform_def.h>
12 
13 #include <common/bl_common.h>
14 #include <common/debug.h>
15 #include <drivers/io/io_driver.h>
16 #include <drivers/io/io_fip.h>
17 #include <drivers/io/io_memmap.h>
18 #include <drivers/io/io_storage.h>
19 #include <tools_share/firmware_image_package.h>
20 
21 /* IO devices */
22 static const io_dev_connector_t *fip_dev_con;
23 static uintptr_t fip_dev_handle;
24 static const io_dev_connector_t *memmap_dev_con;
25 static uintptr_t memmap_dev_handle;
26 
27 static const io_block_spec_t fip_block_spec = {
28 	.offset = PLAT_MARVELL_FIP_BASE,
29 	.length = PLAT_MARVELL_FIP_MAX_SIZE
30 };
31 
32 static const io_uuid_spec_t bl2_uuid_spec = {
33 	.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
34 };
35 
36 static const io_uuid_spec_t scp_bl2_uuid_spec = {
37 	.uuid = UUID_SCP_FIRMWARE_SCP_BL2,
38 };
39 
40 static const io_uuid_spec_t bl31_uuid_spec = {
41 	.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
42 };
43 static const io_uuid_spec_t bl32_uuid_spec = {
44 	.uuid = UUID_SECURE_PAYLOAD_BL32,
45 };
46 
47 static const io_uuid_spec_t bl32_extra1_uuid_spec = {
48 	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
49 };
50 
51 static const io_uuid_spec_t bl32_extra2_uuid_spec = {
52 	.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2,
53 };
54 
55 static const io_uuid_spec_t bl33_uuid_spec = {
56 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
57 };
58 
59 static int open_fip(const uintptr_t spec);
60 static int open_memmap(const uintptr_t spec);
61 
62 struct plat_io_policy {
63 	uintptr_t *dev_handle;
64 	uintptr_t image_spec;
65 	int (*check)(const uintptr_t spec);
66 };
67 
68 /* By default, Marvell platforms load images from the FIP */
69 static const struct plat_io_policy policies[] = {
70 	[FIP_IMAGE_ID] = {
71 		&memmap_dev_handle,
72 		(uintptr_t)&fip_block_spec,
73 		open_memmap
74 	},
75 	[BL2_IMAGE_ID] = {
76 		&fip_dev_handle,
77 		(uintptr_t)&bl2_uuid_spec,
78 		open_fip
79 	},
80 	[SCP_BL2_IMAGE_ID] = {
81 		&fip_dev_handle,
82 		(uintptr_t)&scp_bl2_uuid_spec,
83 		open_fip
84 	},
85 	[BL31_IMAGE_ID] = {
86 		&fip_dev_handle,
87 		(uintptr_t)&bl31_uuid_spec,
88 		open_fip
89 	},
90 	[BL32_IMAGE_ID] = {
91 		&fip_dev_handle,
92 		(uintptr_t)&bl32_uuid_spec,
93 		open_fip
94 	},
95 	[BL32_EXTRA1_IMAGE_ID] = {
96 		&fip_dev_handle,
97 		(uintptr_t)&bl32_extra1_uuid_spec,
98 		open_fip
99 	},
100 	[BL32_EXTRA2_IMAGE_ID] = {
101 		&fip_dev_handle,
102 		(uintptr_t)&bl32_extra2_uuid_spec,
103 		open_fip
104 	},
105 	[BL33_IMAGE_ID] = {
106 		&fip_dev_handle,
107 		(uintptr_t)&bl33_uuid_spec,
108 		open_fip
109 	},
110 };
111 
112 
113 /* Weak definitions may be overridden in specific ARM standard platform */
114 #pragma weak plat_marvell_io_setup
115 #pragma weak plat_marvell_get_alt_image_source
116 
117 
open_fip(const uintptr_t spec)118 static int open_fip(const uintptr_t spec)
119 {
120 	int result;
121 	uintptr_t local_image_handle;
122 
123 	/* See if a Firmware Image Package is available */
124 	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
125 	if (result == 0) {
126 		result = io_open(fip_dev_handle, spec, &local_image_handle);
127 		if (result == 0) {
128 			VERBOSE("Using FIP\n");
129 			io_close(local_image_handle);
130 		}
131 	}
132 	return result;
133 }
134 
135 
open_memmap(const uintptr_t spec)136 static int open_memmap(const uintptr_t spec)
137 {
138 	int result;
139 	uintptr_t local_image_handle;
140 
141 	result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
142 	if (result == 0) {
143 		result = io_open(memmap_dev_handle, spec, &local_image_handle);
144 		if (result == 0) {
145 			VERBOSE("Using Memmap\n");
146 			io_close(local_image_handle);
147 		}
148 	}
149 	return result;
150 }
151 
152 
marvell_io_setup(void)153 void marvell_io_setup(void)
154 {
155 	int io_result;
156 
157 	io_result = register_io_dev_fip(&fip_dev_con);
158 	assert(io_result == 0);
159 
160 	io_result = register_io_dev_memmap(&memmap_dev_con);
161 	assert(io_result == 0);
162 
163 	/* Open connections to devices and cache the handles */
164 	io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
165 				&fip_dev_handle);
166 	assert(io_result == 0);
167 
168 	io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
169 				&memmap_dev_handle);
170 	assert(io_result == 0);
171 
172 	/* Ignore improbable errors in release builds */
173 	(void)io_result;
174 }
175 
plat_marvell_io_setup(void)176 void plat_marvell_io_setup(void)
177 {
178 	marvell_io_setup();
179 }
180 
plat_marvell_get_alt_image_source(unsigned int image_id,uintptr_t * dev_handle,uintptr_t * image_spec)181 int plat_marvell_get_alt_image_source(
182 	unsigned int image_id __attribute__((unused)),
183 	uintptr_t *dev_handle __attribute__((unused)),
184 	uintptr_t *image_spec __attribute__((unused)))
185 {
186 	/* By default do not try an alternative */
187 	return -ENOENT;
188 }
189 
190 /*
191  * Return an IO device handle and specification which can be used to access
192  * an image. Use this to enforce platform load policy
193  */
plat_get_image_source(unsigned int image_id,uintptr_t * dev_handle,uintptr_t * image_spec)194 int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
195 			  uintptr_t *image_spec)
196 {
197 	int result;
198 	const struct plat_io_policy *policy;
199 
200 	assert(image_id < ARRAY_SIZE(policies));
201 
202 	policy = &policies[image_id];
203 	result = policy->check(policy->image_spec);
204 	if (result == 0) {
205 		*image_spec = policy->image_spec;
206 		*dev_handle = *(policy->dev_handle);
207 	} else {
208 		VERBOSE("Trying alternative IO\n");
209 		result = plat_marvell_get_alt_image_source(image_id, dev_handle,
210 						       image_spec);
211 	}
212 
213 	return result;
214 }
215 
216 /*
217  * See if a Firmware Image Package is available,
218  * by checking if TOC is valid or not.
219  */
marvell_io_is_toc_valid(void)220 int marvell_io_is_toc_valid(void)
221 {
222 	int result;
223 
224 	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
225 
226 	return result == 0;
227 }
228