1 /*
2  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 
9 #include <platform_def.h>
10 
11 #include <common/debug.h>
12 #include <drivers/io/io_driver.h>
13 #include <drivers/io/io_fip.h>
14 #include <drivers/io/io_memmap.h>
15 #include <drivers/io/io_storage.h>
16 #include <tools_share/firmware_image_package.h>
17 
18 /* IO devices */
19 static const io_dev_connector_t *fip_dev_con;
20 static uintptr_t fip_dev_handle;
21 static const io_dev_connector_t *memmap_dev_con;
22 static uintptr_t memmap_dev_handle;
23 
24 static const io_block_spec_t fip_block_spec = {
25 	.offset = PLAT_LS_FIP_BASE,
26 	.length = PLAT_LS_FIP_MAX_SIZE
27 };
28 
29 static const io_uuid_spec_t bl2_uuid_spec = {
30 	.uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2,
31 };
32 
33 static const io_uuid_spec_t bl31_uuid_spec = {
34 	.uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31,
35 };
36 
37 static const io_uuid_spec_t bl32_uuid_spec = {
38 	.uuid = UUID_SECURE_PAYLOAD_BL32,
39 };
40 
41 static const io_uuid_spec_t bl33_uuid_spec = {
42 	.uuid = UUID_NON_TRUSTED_FIRMWARE_BL33,
43 };
44 
45 static int open_fip(const uintptr_t spec);
46 static int open_memmap(const uintptr_t spec);
47 
48 struct plat_io_policy {
49 	uintptr_t *dev_handle;
50 	uintptr_t image_spec;
51 	int (*check)(const uintptr_t spec);
52 };
53 
54 static const struct plat_io_policy policies[] = {
55 	[FIP_IMAGE_ID] = {
56 		&memmap_dev_handle,
57 		(uintptr_t)&fip_block_spec,
58 		open_memmap
59 	},
60 	[BL2_IMAGE_ID] = {
61 		&fip_dev_handle,
62 		(uintptr_t)&bl2_uuid_spec,
63 		open_fip
64 	},
65 	[BL31_IMAGE_ID] = {
66 		&fip_dev_handle,
67 		(uintptr_t)&bl31_uuid_spec,
68 		open_fip
69 	},
70 	[BL32_IMAGE_ID] = {
71 		&fip_dev_handle,
72 		(uintptr_t)&bl32_uuid_spec,
73 		open_fip
74 	},
75 	[BL33_IMAGE_ID] = {
76 		&fip_dev_handle,
77 		(uintptr_t)&bl33_uuid_spec,
78 		open_fip
79 	},
80 };
81 
open_fip(const uintptr_t spec)82 static int open_fip(const uintptr_t spec)
83 {
84 	int result;
85 	uintptr_t local_image_handle;
86 
87 	/* See if a Firmware Image Package is available */
88 	result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
89 	if (result == 0) {
90 		result = io_open(fip_dev_handle, spec, &local_image_handle);
91 		if (result == 0) {
92 			VERBOSE("Using FIP\n");
93 			io_close(local_image_handle);
94 		}
95 	}
96 	return result;
97 }
98 
99 
open_memmap(const uintptr_t spec)100 static int open_memmap(const uintptr_t spec)
101 {
102 	int result;
103 	uintptr_t local_image_handle;
104 
105 	result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL);
106 	if (result == 0) {
107 		result = io_open(memmap_dev_handle, spec, &local_image_handle);
108 		if (result == 0) {
109 			VERBOSE("Using Memmap\n");
110 			io_close(local_image_handle);
111 		}
112 	}
113 	return result;
114 }
115 
116 
ls_io_setup(void)117 void ls_io_setup(void)
118 {
119 	int io_result;
120 
121 	io_result = register_io_dev_fip(&fip_dev_con);
122 	assert(io_result == 0);
123 
124 	io_result = register_io_dev_memmap(&memmap_dev_con);
125 	assert(io_result == 0);
126 
127 	/* Open connections to devices and cache the handles */
128 	io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
129 				&fip_dev_handle);
130 	assert(io_result == 0);
131 
132 	io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
133 				&memmap_dev_handle);
134 	assert(io_result == 0);
135 
136 	/* Ignore improbable errors in release builds */
137 	(void)io_result;
138 }
139 
plat_ls_io_setup(void)140 void plat_ls_io_setup(void)
141 {
142 	ls_io_setup();
143 }
144 
plat_ls_get_alt_image_source(unsigned int image_id __unused,uintptr_t * dev_handle __unused,uintptr_t * image_spec __unused)145 int plat_ls_get_alt_image_source(
146 	unsigned int image_id __unused,
147 	uintptr_t *dev_handle __unused,
148 	uintptr_t *image_spec __unused)
149 {
150 	/* By default do not try an alternative */
151 	return -ENOENT;
152 }
153 
154 /*
155  * Return an IO device handle and specification which can be used to access
156  * an image. Use this to enforce platform load policy.
157  */
plat_get_image_source(unsigned int image_id,uintptr_t * dev_handle,uintptr_t * image_spec)158 int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
159 			  uintptr_t *image_spec)
160 {
161 	int result;
162 	const struct plat_io_policy *policy;
163 
164 	assert(image_id < ARRAY_SIZE(policies));
165 
166 	policy = &policies[image_id];
167 	result = policy->check(policy->image_spec);
168 	if (result == 0) {
169 		*image_spec = policy->image_spec;
170 		*dev_handle = *(policy->dev_handle);
171 	} else {
172 		VERBOSE("Trying alternative IO\n");
173 		result = plat_ls_get_alt_image_source(image_id, dev_handle,
174 						       image_spec);
175 	}
176 
177 	return result;
178 }
179