blob: b4d81b4e25cc3d3bdc43d86adb31600f4de46e48 [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)
Julian Hall7048d302021-06-03 16:07:28 +010030{
Imre Kisfe6521e2021-10-27 20:20:37 +020031 struct sp_param_region *d = (struct sp_param_region *)value_pair->value;
Julian Hall7048d302021-06-03 16:07:28 +010032
33 /* Iterate over the device regions */
34 while ((uintptr_t)d < (value_pair->value + value_pair->size)) {
35
36 struct device_region device_region;
37
Imre Kis06360812022-07-05 16:28:00 +020038 strncpy(device_region.dev_class, d->name,
39 sizeof(device_region.dev_class));
Julian Hall7048d302021-06-03 16:07:28 +010040 device_region.dev_instance = 0;
41 device_region.base_addr = d->location;
42 device_region.io_region_size = d->size;
43
Imre Kis06360812022-07-05 16:28:00 +020044 if (!config_store_add(CONFIG_CLASSIFIER_DEVICE_REGION,
45 device_region.dev_class,
46 device_region.dev_instance,
47 &device_region, sizeof(device_region))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +020048 EMSG("failed to add device region to config store");
Imre Kis06360812022-07-05 16:28:00 +020049 return false;
50 }
Julian Hall7048d302021-06-03 16:07:28 +010051
52 ++d;
53 }
Imre Kis06360812022-07-05 16:28:00 +020054
55 return true;
Julian Hall7048d302021-06-03 16:07:28 +010056}
57
Imre Kis06360812022-07-05 16:28:00 +020058static bool load_memory_regions(const struct ffa_name_value_pair *value_pair)
Julian Hall7048d302021-06-03 16:07:28 +010059{
Imre Kisfe6521e2021-10-27 20:20:37 +020060 struct sp_param_region *d = (struct sp_param_region *)value_pair->value;
61
62 /* Iterate over the device regions */
63 while ((uintptr_t)d < (value_pair->value + value_pair->size)) {
64
65 struct memory_region memory_region;
66
Imre Kis06360812022-07-05 16:28:00 +020067 strncpy(memory_region.region_name, d->name,
68 sizeof(memory_region.region_name));
Imre Kisfe6521e2021-10-27 20:20:37 +020069 memory_region.base_addr = d->location;
70 memory_region.region_size = d->size;
71
Imre Kis06360812022-07-05 16:28:00 +020072 if (!config_store_add(CONFIG_CLASSIFIER_MEMORY_REGION,
73 memory_region.region_name, 0,
74 &memory_region, sizeof(memory_region))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +020075 EMSG("failed to add memory region to config store");
Imre Kis06360812022-07-05 16:28:00 +020076 return false;
77 }
Imre Kisfe6521e2021-10-27 20:20:37 +020078
79 ++d;
80 }
Imre Kis06360812022-07-05 16:28:00 +020081
82 return true;
Julian Hall7048d302021-06-03 16:07:28 +010083}
84
Imre Kis06360812022-07-05 16:28:00 +020085static bool load_blob(const struct ffa_name_value_pair *value_pair)
Julian Hall7048d302021-06-03 16:07:28 +010086{
87 struct config_blob blob;
88
89 blob.data = (const void*)value_pair->value;
90 blob.data_len = value_pair->size;
91
Imre Kis06360812022-07-05 16:28:00 +020092 if (!config_store_add(CONFIG_CLASSIFIER_BLOB, (const char *)value_pair->name, 0,
93 &blob, sizeof(blob))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +020094 EMSG("failed to add blob to config store");
Imre Kis06360812022-07-05 16:28:00 +020095 return false;
96 }
97
98 return true;
Julian Hall7048d302021-06-03 16:07:28 +010099}
Balint Dobszay286ff752022-03-04 15:57:19 +0100100
101static bool load_fdt(const struct ffa_name_value_pair *value_pair)
102{
103 const void *fdt = (const void *)value_pair->value;
104 size_t fdt_size = value_pair->size;
105 int root = -1, node = -1, subnode = -1, rc = -1;
Imre Kis06360812022-07-05 16:28:00 +0200106 static const char *ffa_manifest_compatible = "arm,ffa-manifest-1.0";
Balint Dobszay286ff752022-03-04 15:57:19 +0100107
108 /* Sanity check */
109 if (!fdt) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200110 EMSG("fdt NULL pointer");
Balint Dobszay286ff752022-03-04 15:57:19 +0100111 return false;
112 }
113
114 rc = fdt_check_full(fdt, fdt_size);
115 if (rc) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200116 EMSG("fdt_check_full(): %d", rc);
Balint Dobszay286ff752022-03-04 15:57:19 +0100117 return false;
118 }
119
120 /* Find root node */
121 root = fdt_path_offset(fdt, "/");
122 if (root < 0) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200123 EMSG("fdt_path_offset(): %d", root);
Balint Dobszay286ff752022-03-04 15:57:19 +0100124 return false;
125 }
126
127 /* Check if it's a valid SP manifest */
Imre Kis06360812022-07-05 16:28:00 +0200128 rc = fdt_node_check_compatible(fdt, root, ffa_manifest_compatible);
Balint Dobszay286ff752022-03-04 15:57:19 +0100129 if (rc) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200130 EMSG("fdt_node_check_compatible(%s): %d", ffa_manifest_compatible, rc);
Balint Dobszay286ff752022-03-04 15:57:19 +0100131 return false;
132 }
133
134 /* Find memory regions */
135 node = fdt_node_offset_by_compatible(fdt, root, "arm,ffa-manifest-memory-regions");
136 if (node >= 0) {
137 fdt_for_each_subnode(subnode, fdt, node) {
138 struct memory_region memory_region = {0};
139 uint64_t base_addr = 0;
140 uint32_t page_cnt = 0;
141 const char *subnode_name = fdt_get_name(fdt, subnode, NULL);
142
143 if (!subnode_name) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200144 EMSG("subnode name is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100145 return false;
146 }
147
148 if(!dt_get_u64(fdt, subnode, "base-address", &base_addr)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200149 EMSG("base-address is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100150 return false;
151 }
152
153 if(!dt_get_u32(fdt, subnode, "pages-count", &page_cnt)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200154 EMSG("pages-count is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100155 return false;
156 }
157
158 strncpy(memory_region.region_name, subnode_name,
159 sizeof(memory_region.region_name));
160 memory_region.base_addr = (uintptr_t)base_addr;
161 memory_region.region_size = page_cnt * FFA_SP_MANIFEST_PAGE_SIZE;
162
163 if (!config_store_add(CONFIG_CLASSIFIER_MEMORY_REGION,
164 memory_region.region_name, 0,
165 &memory_region, sizeof(memory_region))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200166 EMSG("failed to add memory region to config store");
Balint Dobszay286ff752022-03-04 15:57:19 +0100167 return false;
168 }
169 }
170 }
171
172 /* Find device regions */
173 node = fdt_node_offset_by_compatible(fdt, root, "arm,ffa-manifest-device-regions");
174 if (node >= 0) {
175 fdt_for_each_subnode(subnode, fdt, node) {
176 struct device_region device_region = {0};
177 uint64_t base_addr = 0;
178 uint32_t page_cnt = 0;
179 const char *subnode_name = fdt_get_name(fdt, subnode, NULL);
180
181 if (!subnode_name) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200182 EMSG("subnode name is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100183 return false;
184 }
185
186 if(!dt_get_u64(fdt, subnode, "base-address", &base_addr)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200187 EMSG("base-address is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100188 return false;
189 }
190
191 if (!dt_get_u32(fdt, subnode, "pages-count", &page_cnt)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200192 EMSG("pages-count is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100193 return false;
194 }
195
196 strncpy(device_region.dev_class, subnode_name,
197 sizeof(device_region.dev_class));
198 device_region.base_addr = base_addr;
199 device_region.io_region_size = page_cnt * FFA_SP_MANIFEST_PAGE_SIZE;
200 device_region.dev_instance = 0;
201
202 if (!config_store_add(CONFIG_CLASSIFIER_DEVICE_REGION,
203 device_region.dev_class, device_region.dev_instance,
204 &device_region, sizeof(device_region))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200205 EMSG("failed to add device region to config store");
Balint Dobszay286ff752022-03-04 15:57:19 +0100206 return false;
207 }
208 }
209 }
210
Imre Kisd40d6202022-03-22 19:20:14 +0100211 /* Find TPM event log */
212 node = fdt_node_offset_by_compatible(fdt, root, "arm,tpm_event_log");
213 if (node >= 0) {
214 uint64_t tpm_event_log_addr = 0;
215 uint32_t tpm_event_log_size = 0;
Imre Kise432e582022-07-07 16:35:45 +0200216 struct config_blob blob = { 0 };
Imre Kisd40d6202022-03-22 19:20:14 +0100217
Balint Dobszay43b7d982022-04-01 15:35:51 +0200218 if (!dt_get_u64(fdt, node, "tpm_event_log_addr", &tpm_event_log_addr)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200219 EMSG("tpm_event_log_addr is missing");
Imre Kisd40d6202022-03-22 19:20:14 +0100220 return false;
Balint Dobszay43b7d982022-04-01 15:35:51 +0200221 }
Imre Kisd40d6202022-03-22 19:20:14 +0100222
Balint Dobszay43b7d982022-04-01 15:35:51 +0200223 if (!dt_get_u32(fdt, node, "tpm_event_log_size", &tpm_event_log_size)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200224 EMSG("tpm_event_log_size is missing");
Imre Kisd40d6202022-03-22 19:20:14 +0100225 return false;
Balint Dobszay43b7d982022-04-01 15:35:51 +0200226 }
Imre Kisd40d6202022-03-22 19:20:14 +0100227
Imre Kise432e582022-07-07 16:35:45 +0200228 blob.data = (const void *)tpm_event_log_addr;
229 blob.data_len = tpm_event_log_size;
230
Imre Kisd40d6202022-03-22 19:20:14 +0100231 if (!config_store_add(CONFIG_CLASSIFIER_BLOB, "EVENT_LOG", 0,
Imre Kise432e582022-07-07 16:35:45 +0200232 (void *)&blob, sizeof(blob))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200233 EMSG("failed to add event log to config store");
Imre Kisd40d6202022-03-22 19:20:14 +0100234 return false;
235 }
236 }
237
Balint Dobszay9a747852023-04-18 18:08:49 +0200238 /* Find hardware features */
239 node = fdt_node_offset_by_compatible(fdt, root, "arm,hw-features");
240 if (node >= 0) {
241 const char *prop_name = NULL;
242 uint32_t prop_value = 0;
243 int prop_offset = 0;
244
245 fdt_for_each_property_offset(prop_offset, fdt, node) {
246 if (!dt_get_u32_by_offset(fdt, prop_offset, &prop_name, &prop_value)) {
247 /* skip other properties in the node, e.g. the compatible string */
248 DMSG("skipping non-u32 property '%s' in hw-features", prop_name);
249 continue;
250 }
251
252 if (!config_store_add(CONFIG_CLASSIFIER_HW_FEATURE, prop_name, 0,
253 &prop_value, sizeof(prop_value))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200254 EMSG("failed to add HW feature to config store");
Balint Dobszay9a747852023-04-18 18:08:49 +0200255 return false;
256 }
257 }
258 } else {
259 DMSG("arm,hw-features node not present in SP manifest");
260 }
261
Balint Dobszay286ff752022-03-04 15:57:19 +0100262 return true;
263}
Balint Dobszay8102ba72023-04-13 16:29:41 +0200264
265/**
266 * Loads externally provided configuration data passed into the SP via
267 * FFA initialisation parameters. Data can originate from
268 * the SP manifest, an external device tree or a dynamic configuration
269 * mechanism such as a handover block (HOB).
270 */
271bool sp_config_load(struct ffa_init_info *init_info)
272{
273 /* Load deployment specific configuration */
274 for (size_t param_index = 0; param_index < init_info->count; param_index++) {
275 const char *name = (const char *)init_info->nvp[param_index].name;
276 const size_t name_max_size = sizeof(init_info->nvp[param_index].name);
277
278 if (!strncmp(name, "DEVICE_REGIONS", name_max_size)) {
279 if (!load_device_regions(&init_info->nvp[param_index])) {
280 EMSG("Failed to load device regions");
281 return false;
282 }
283 } else if (!strncmp(name, "MEMORY_REGIONS", name_max_size)) {
284 if (!load_memory_regions(&init_info->nvp[param_index])) {
285 EMSG("Failed to load memory regions");
286 return false;
287 }
288 } else if (!memcmp(name, "TYPE_DT\0\0\0\0\0\0\0\0", name_max_size)) {
289 if (!load_fdt(&init_info->nvp[param_index])) {
290 EMSG("Failed to load SP config from DT");
291 return false;
292 }
293 } else {
294 if (!load_blob(&init_info->nvp[param_index])) {
295 EMSG("Failed to load blob");
296 return false;
297 }
298 }
299 }
300
301 return true;
302}