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