blob: a515cb2bc332025aceb0c2bdb22c8ab173fda915 [file] [log] [blame]
julhal0137e1aea2021-02-09 15:22:20 +00001// SPDX-License-Identifier: BSD-3-Clause
2/*
Balint Dobszay286ff752022-03-04 15:57:19 +01003 * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
julhal0137e1aea2021-02-09 15:22:20 +00004 */
5
Balint Dobszay286ff752022-03-04 15:57:19 +01006#include <common/fdt/fdt_helpers.h>
Julian Hall7048d302021-06-03 16:07:28 +01007#include <config/interface/config_store.h>
8#include <config/interface/config_blob.h>
julhal0137e1aea2021-02-09 15:22:20 +00009#include <platform/interface/device_region.h>
Balint Dobszay286ff752022-03-04 15:57:19 +010010#include <platform/interface/memory_region.h>
11#include <stdbool.h>
12#include <string.h>
13#include <trace.h>
14
julhal0137e1aea2021-02-09 15:22:20 +000015#include "sp_config_loader.h"
16
Balint Dobszay286ff752022-03-04 15:57:19 +010017/*
18 * According to the FF-A 1.0 spec: in the SP manifest the size of device and
19 * memory regions is expressed as a count of 4K pages.
20 */
21#define FFA_SP_MANIFEST_PAGE_SIZE 0x1000
julhal0137e1aea2021-02-09 15:22:20 +000022
Imre Kisfe6521e2021-10-27 20:20:37 +020023struct sp_param_region {
julhal0137e1aea2021-02-09 15:22:20 +000024 char name[16];
25 uintptr_t location;
26 size_t size;
27};
28
Imre Kis06360812022-07-05 16:28:00 +020029static bool load_device_regions(const struct ffa_name_value_pair *value_pair);
30static bool load_memory_regions(const struct ffa_name_value_pair *value_pair);
31static bool load_blob(const struct ffa_name_value_pair *value_pair);
Balint Dobszay286ff752022-03-04 15:57:19 +010032static bool load_fdt(const struct ffa_name_value_pair *value_pair);
Julian Hall7048d302021-06-03 16:07:28 +010033
julhal0137e1aea2021-02-09 15:22:20 +000034/**
Julian Hall7048d302021-06-03 16:07:28 +010035 * Loads externally provided configuration data passed into the SP via
36 * FFA initialisation parameters. Data can originate from
37 * the SP manifest, an external device tree or a dynamic configuration
38 * mechanism such as a handover block (HOB).
julhal0137e1aea2021-02-09 15:22:20 +000039 */
Imre Kis06360812022-07-05 16:28:00 +020040bool sp_config_load(struct ffa_init_info *init_info)
julhal0137e1aea2021-02-09 15:22:20 +000041{
42 /* Load deployment specific configuration */
43 for (size_t param_index = 0; param_index < init_info->count; param_index++) {
Imre Kis06360812022-07-05 16:28:00 +020044 const char *name = (const char *)init_info->nvp[param_index].name;
45 const size_t name_max_size = sizeof(init_info->nvp[param_index].name);
julhal0137e1aea2021-02-09 15:22:20 +000046
Imre Kis06360812022-07-05 16:28:00 +020047 if (!strncmp(name, "DEVICE_REGIONS", name_max_size)) {
48 if (!load_device_regions(&init_info->nvp[param_index])) {
49 EMSG("Failed to load device regions");
50 return false;
51 }
52 } else if (!strncmp(name, "MEMORY_REGIONS", name_max_size)) {
53 if (!load_memory_regions(&init_info->nvp[param_index])) {
54 EMSG("Failed to load memory regions");
55 return false;
56 }
57 } else if (!memcmp(name, "TYPE_DT\0\0\0\0\0\0\0\0", name_max_size)) {
58 if (!load_fdt(&init_info->nvp[param_index])) {
Balint Dobszay286ff752022-03-04 15:57:19 +010059 EMSG("Failed to load SP config from DT");
Imre Kis06360812022-07-05 16:28:00 +020060 return false;
61 }
62 } else {
63 if (!load_blob(&init_info->nvp[param_index])) {
64 EMSG("Failed to load blob");
65 return false;
66 }
julhal0137e1aea2021-02-09 15:22:20 +000067 }
68 }
Imre Kis06360812022-07-05 16:28:00 +020069
70 return true;
julhal0137e1aea2021-02-09 15:22:20 +000071}
Julian Hall7048d302021-06-03 16:07:28 +010072
Imre Kis06360812022-07-05 16:28:00 +020073static bool load_device_regions(const struct ffa_name_value_pair *value_pair)
Julian Hall7048d302021-06-03 16:07:28 +010074{
Imre Kisfe6521e2021-10-27 20:20:37 +020075 struct sp_param_region *d = (struct sp_param_region *)value_pair->value;
Julian Hall7048d302021-06-03 16:07:28 +010076
77 /* Iterate over the device regions */
78 while ((uintptr_t)d < (value_pair->value + value_pair->size)) {
79
80 struct device_region device_region;
81
Imre Kis06360812022-07-05 16:28:00 +020082 strncpy(device_region.dev_class, d->name,
83 sizeof(device_region.dev_class));
Julian Hall7048d302021-06-03 16:07:28 +010084 device_region.dev_instance = 0;
85 device_region.base_addr = d->location;
86 device_region.io_region_size = d->size;
87
Imre Kis06360812022-07-05 16:28:00 +020088 if (!config_store_add(CONFIG_CLASSIFIER_DEVICE_REGION,
89 device_region.dev_class,
90 device_region.dev_instance,
91 &device_region, sizeof(device_region))) {
92 DMSG("error: failed to add device region to config store");
93 return false;
94 }
Julian Hall7048d302021-06-03 16:07:28 +010095
96 ++d;
97 }
Imre Kis06360812022-07-05 16:28:00 +020098
99 return true;
Julian Hall7048d302021-06-03 16:07:28 +0100100}
101
Imre Kis06360812022-07-05 16:28:00 +0200102static bool load_memory_regions(const struct ffa_name_value_pair *value_pair)
Julian Hall7048d302021-06-03 16:07:28 +0100103{
Imre Kisfe6521e2021-10-27 20:20:37 +0200104 struct sp_param_region *d = (struct sp_param_region *)value_pair->value;
105
106 /* Iterate over the device regions */
107 while ((uintptr_t)d < (value_pair->value + value_pair->size)) {
108
109 struct memory_region memory_region;
110
Imre Kis06360812022-07-05 16:28:00 +0200111 strncpy(memory_region.region_name, d->name,
112 sizeof(memory_region.region_name));
Imre Kisfe6521e2021-10-27 20:20:37 +0200113 memory_region.base_addr = d->location;
114 memory_region.region_size = d->size;
115
Imre Kis06360812022-07-05 16:28:00 +0200116 if (!config_store_add(CONFIG_CLASSIFIER_MEMORY_REGION,
117 memory_region.region_name, 0,
118 &memory_region, sizeof(memory_region))) {
119 DMSG("error: failed to add memory region to config store");
120 return false;
121 }
Imre Kisfe6521e2021-10-27 20:20:37 +0200122
123 ++d;
124 }
Imre Kis06360812022-07-05 16:28:00 +0200125
126 return true;
Julian Hall7048d302021-06-03 16:07:28 +0100127}
128
Imre Kis06360812022-07-05 16:28:00 +0200129static bool load_blob(const struct ffa_name_value_pair *value_pair)
Julian Hall7048d302021-06-03 16:07:28 +0100130{
131 struct config_blob blob;
132
133 blob.data = (const void*)value_pair->value;
134 blob.data_len = value_pair->size;
135
Imre Kis06360812022-07-05 16:28:00 +0200136 if (!config_store_add(CONFIG_CLASSIFIER_BLOB, (const char *)value_pair->name, 0,
137 &blob, sizeof(blob))) {
138 DMSG("error: failed to add blob to config store");
139 return false;
140 }
141
142 return true;
Julian Hall7048d302021-06-03 16:07:28 +0100143}
Balint Dobszay286ff752022-03-04 15:57:19 +0100144
145static bool load_fdt(const struct ffa_name_value_pair *value_pair)
146{
147 const void *fdt = (const void *)value_pair->value;
148 size_t fdt_size = value_pair->size;
149 int root = -1, node = -1, subnode = -1, rc = -1;
Imre Kis06360812022-07-05 16:28:00 +0200150 static const char *ffa_manifest_compatible = "arm,ffa-manifest-1.0";
Balint Dobszay286ff752022-03-04 15:57:19 +0100151
152 /* Sanity check */
153 if (!fdt) {
154 DMSG("error: fdt NULL pointer");
155 return false;
156 }
157
158 rc = fdt_check_full(fdt, fdt_size);
159 if (rc) {
160 DMSG("error: fdt_check_full(): %d", rc);
161 return false;
162 }
163
164 /* Find root node */
165 root = fdt_path_offset(fdt, "/");
166 if (root < 0) {
167 DMSG("error: fdt_path_offset(): %d", root);
168 return false;
169 }
170
171 /* Check if it's a valid SP manifest */
Imre Kis06360812022-07-05 16:28:00 +0200172 rc = fdt_node_check_compatible(fdt, root, ffa_manifest_compatible);
Balint Dobszay286ff752022-03-04 15:57:19 +0100173 if (rc) {
Imre Kis06360812022-07-05 16:28:00 +0200174 DMSG("error: fdt_node_check_compatible(%s): %d", ffa_manifest_compatible, rc);
Balint Dobszay286ff752022-03-04 15:57:19 +0100175 return false;
176 }
177
178 /* Find memory regions */
179 node = fdt_node_offset_by_compatible(fdt, root, "arm,ffa-manifest-memory-regions");
180 if (node >= 0) {
181 fdt_for_each_subnode(subnode, fdt, node) {
182 struct memory_region memory_region = {0};
183 uint64_t base_addr = 0;
184 uint32_t page_cnt = 0;
185 const char *subnode_name = fdt_get_name(fdt, subnode, NULL);
186
187 if (!subnode_name) {
188 DMSG("error: subnode name is missing");
189 return false;
190 }
191
192 if(!dt_get_u64(fdt, subnode, "base-address", &base_addr)) {
193 DMSG("error: base-address is missing");
194 return false;
195 }
196
197 if(!dt_get_u32(fdt, subnode, "pages-count", &page_cnt)) {
198 DMSG("error: pages-count is missing");
199 return false;
200 }
201
202 strncpy(memory_region.region_name, subnode_name,
203 sizeof(memory_region.region_name));
204 memory_region.base_addr = (uintptr_t)base_addr;
205 memory_region.region_size = page_cnt * FFA_SP_MANIFEST_PAGE_SIZE;
206
207 if (!config_store_add(CONFIG_CLASSIFIER_MEMORY_REGION,
208 memory_region.region_name, 0,
209 &memory_region, sizeof(memory_region))) {
210 DMSG("error: failed to add memory region to config store");
211 return false;
212 }
213 }
214 }
215
216 /* Find device regions */
217 node = fdt_node_offset_by_compatible(fdt, root, "arm,ffa-manifest-device-regions");
218 if (node >= 0) {
219 fdt_for_each_subnode(subnode, fdt, node) {
220 struct device_region device_region = {0};
221 uint64_t base_addr = 0;
222 uint32_t page_cnt = 0;
223 const char *subnode_name = fdt_get_name(fdt, subnode, NULL);
224
225 if (!subnode_name) {
226 DMSG("error: subnode name is missing");
227 return false;
228 }
229
230 if(!dt_get_u64(fdt, subnode, "base-address", &base_addr)) {
231 DMSG("error: base-address is missing");
232 return false;
233 }
234
235 if (!dt_get_u32(fdt, subnode, "pages-count", &page_cnt)) {
236 DMSG("error: pages-count is missing");
237 return false;
238 }
239
240 strncpy(device_region.dev_class, subnode_name,
241 sizeof(device_region.dev_class));
242 device_region.base_addr = base_addr;
243 device_region.io_region_size = page_cnt * FFA_SP_MANIFEST_PAGE_SIZE;
244 device_region.dev_instance = 0;
245
246 if (!config_store_add(CONFIG_CLASSIFIER_DEVICE_REGION,
247 device_region.dev_class, device_region.dev_instance,
248 &device_region, sizeof(device_region))) {
249 DMSG("error: failed to add device region to config store");
250 return false;
251 }
252 }
253 }
254
Imre Kisd40d6202022-03-22 19:20:14 +0100255 /* Find TPM event log */
256 node = fdt_node_offset_by_compatible(fdt, root, "arm,tpm_event_log");
257 if (node >= 0) {
258 uint64_t tpm_event_log_addr = 0;
259 uint32_t tpm_event_log_size = 0;
Imre Kise432e582022-07-07 16:35:45 +0200260 struct config_blob blob = { 0 };
Imre Kisd40d6202022-03-22 19:20:14 +0100261
Balint Dobszay43b7d982022-04-01 15:35:51 +0200262 if (!dt_get_u64(fdt, node, "tpm_event_log_addr", &tpm_event_log_addr)) {
263 DMSG("error: tpm_event_log_addr is missing");
Imre Kisd40d6202022-03-22 19:20:14 +0100264 return false;
Balint Dobszay43b7d982022-04-01 15:35:51 +0200265 }
Imre Kisd40d6202022-03-22 19:20:14 +0100266
Balint Dobszay43b7d982022-04-01 15:35:51 +0200267 if (!dt_get_u32(fdt, node, "tpm_event_log_size", &tpm_event_log_size)) {
268 DMSG("error: tpm_event_log_size is missing");
Imre Kisd40d6202022-03-22 19:20:14 +0100269 return false;
Balint Dobszay43b7d982022-04-01 15:35:51 +0200270 }
Imre Kisd40d6202022-03-22 19:20:14 +0100271
Imre Kise432e582022-07-07 16:35:45 +0200272 blob.data = (const void *)tpm_event_log_addr;
273 blob.data_len = tpm_event_log_size;
274
Imre Kisd40d6202022-03-22 19:20:14 +0100275 if (!config_store_add(CONFIG_CLASSIFIER_BLOB, "EVENT_LOG", 0,
Imre Kise432e582022-07-07 16:35:45 +0200276 (void *)&blob, sizeof(blob))) {
Balint Dobszay43b7d982022-04-01 15:35:51 +0200277 DMSG("error: failed to add event log to config store");
Imre Kisd40d6202022-03-22 19:20:14 +0100278 return false;
279 }
280 }
281
Balint Dobszay286ff752022-03-04 15:57:19 +0100282 return true;
283}