blob: 5c7c55247b799168b9ecaef7caa76e0aeefb93da [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>
Balint Dobszay4f9d8e32023-04-13 13:55:08 +020012#include <stdint.h>
Balint Dobszay286ff752022-03-04 15:57:19 +010013#include <string.h>
14#include <trace.h>
15
julhal0137e1aea2021-02-09 15:22:20 +000016#include "sp_config_loader.h"
17
Balint Dobszay286ff752022-03-04 15:57:19 +010018/*
Balint Dobszay4f9d8e32023-04-13 13:55:08 +020019 * According to the FF-A spec: in the SP manifest the size of device and
Balint Dobszay286ff752022-03-04 15:57:19 +010020 * memory regions is expressed as a count of 4K pages.
21 */
Balint Dobszay4f9d8e32023-04-13 13:55:08 +020022#define FFA_SP_MANIFEST_PAGE_SIZE UINT32_C(0x1000)
julhal0137e1aea2021-02-09 15:22:20 +000023
Imre Kisfe6521e2021-10-27 20:20:37 +020024struct sp_param_region {
julhal0137e1aea2021-02-09 15:22:20 +000025 char name[16];
26 uintptr_t location;
27 size_t size;
28};
29
Balint Dobszay4f9d8e32023-04-13 13:55:08 +020030static bool load_device_regions(const struct ffa_name_value_pair_v1_0 *value_pair)
Julian Hall7048d302021-06-03 16:07:28 +010031{
Imre Kisfe6521e2021-10-27 20:20:37 +020032 struct sp_param_region *d = (struct sp_param_region *)value_pair->value;
Julian Hall7048d302021-06-03 16:07:28 +010033
34 /* Iterate over the device regions */
35 while ((uintptr_t)d < (value_pair->value + value_pair->size)) {
36
37 struct device_region device_region;
38
Imre Kis06360812022-07-05 16:28:00 +020039 strncpy(device_region.dev_class, d->name,
40 sizeof(device_region.dev_class));
Julian Hall7048d302021-06-03 16:07:28 +010041 device_region.dev_instance = 0;
42 device_region.base_addr = d->location;
43 device_region.io_region_size = d->size;
44
Imre Kis06360812022-07-05 16:28:00 +020045 if (!config_store_add(CONFIG_CLASSIFIER_DEVICE_REGION,
46 device_region.dev_class,
47 device_region.dev_instance,
48 &device_region, sizeof(device_region))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +020049 EMSG("failed to add device region to config store");
Imre Kis06360812022-07-05 16:28:00 +020050 return false;
51 }
Julian Hall7048d302021-06-03 16:07:28 +010052
53 ++d;
54 }
Imre Kis06360812022-07-05 16:28:00 +020055
56 return true;
Julian Hall7048d302021-06-03 16:07:28 +010057}
58
Balint Dobszay4f9d8e32023-04-13 13:55:08 +020059static bool load_memory_regions(const struct ffa_name_value_pair_v1_0 *value_pair)
Julian Hall7048d302021-06-03 16:07:28 +010060{
Imre Kisfe6521e2021-10-27 20:20:37 +020061 struct sp_param_region *d = (struct sp_param_region *)value_pair->value;
62
63 /* Iterate over the device regions */
64 while ((uintptr_t)d < (value_pair->value + value_pair->size)) {
65
66 struct memory_region memory_region;
67
Imre Kis06360812022-07-05 16:28:00 +020068 strncpy(memory_region.region_name, d->name,
69 sizeof(memory_region.region_name));
Imre Kisfe6521e2021-10-27 20:20:37 +020070 memory_region.base_addr = d->location;
71 memory_region.region_size = d->size;
72
Imre Kis06360812022-07-05 16:28:00 +020073 if (!config_store_add(CONFIG_CLASSIFIER_MEMORY_REGION,
74 memory_region.region_name, 0,
75 &memory_region, sizeof(memory_region))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +020076 EMSG("failed to add memory region to config store");
Imre Kis06360812022-07-05 16:28:00 +020077 return false;
78 }
Imre Kisfe6521e2021-10-27 20:20:37 +020079
80 ++d;
81 }
Imre Kis06360812022-07-05 16:28:00 +020082
83 return true;
Julian Hall7048d302021-06-03 16:07:28 +010084}
85
Balint Dobszay4f9d8e32023-04-13 13:55:08 +020086static bool load_blob(const struct ffa_name_value_pair_v1_0 *value_pair)
Julian Hall7048d302021-06-03 16:07:28 +010087{
88 struct config_blob blob;
89
90 blob.data = (const void*)value_pair->value;
91 blob.data_len = value_pair->size;
92
Imre Kis06360812022-07-05 16:28:00 +020093 if (!config_store_add(CONFIG_CLASSIFIER_BLOB, (const char *)value_pair->name, 0,
94 &blob, sizeof(blob))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +020095 EMSG("failed to add blob to config store");
Imre Kis06360812022-07-05 16:28:00 +020096 return false;
97 }
98
99 return true;
Julian Hall7048d302021-06-03 16:07:28 +0100100}
Balint Dobszay286ff752022-03-04 15:57:19 +0100101
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200102static bool load_fdt(const void *fdt, size_t fdt_size)
Balint Dobszay286ff752022-03-04 15:57:19 +0100103{
Balint Dobszay286ff752022-03-04 15:57:19 +0100104 int root = -1, node = -1, subnode = -1, rc = -1;
Imre Kis06360812022-07-05 16:28:00 +0200105 static const char *ffa_manifest_compatible = "arm,ffa-manifest-1.0";
Balint Dobszay286ff752022-03-04 15:57:19 +0100106
107 /* Sanity check */
108 if (!fdt) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200109 EMSG("fdt NULL pointer");
Balint Dobszay286ff752022-03-04 15:57:19 +0100110 return false;
111 }
112
113 rc = fdt_check_full(fdt, fdt_size);
114 if (rc) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200115 EMSG("fdt_check_full(): %d", rc);
Balint Dobszay286ff752022-03-04 15:57:19 +0100116 return false;
117 }
118
119 /* Find root node */
120 root = fdt_path_offset(fdt, "/");
121 if (root < 0) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200122 EMSG("fdt_path_offset(): %d", root);
Balint Dobszay286ff752022-03-04 15:57:19 +0100123 return false;
124 }
125
126 /* Check if it's a valid SP manifest */
Imre Kis06360812022-07-05 16:28:00 +0200127 rc = fdt_node_check_compatible(fdt, root, ffa_manifest_compatible);
Balint Dobszay286ff752022-03-04 15:57:19 +0100128 if (rc) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200129 EMSG("fdt_node_check_compatible(%s): %d", ffa_manifest_compatible, rc);
Balint Dobszay286ff752022-03-04 15:57:19 +0100130 return false;
131 }
132
133 /* Find memory regions */
134 node = fdt_node_offset_by_compatible(fdt, root, "arm,ffa-manifest-memory-regions");
135 if (node >= 0) {
136 fdt_for_each_subnode(subnode, fdt, node) {
137 struct memory_region memory_region = {0};
138 uint64_t base_addr = 0;
139 uint32_t page_cnt = 0;
140 const char *subnode_name = fdt_get_name(fdt, subnode, NULL);
141
142 if (!subnode_name) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200143 EMSG("subnode name is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100144 return false;
145 }
146
147 if(!dt_get_u64(fdt, subnode, "base-address", &base_addr)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200148 EMSG("base-address is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100149 return false;
150 }
151
152 if(!dt_get_u32(fdt, subnode, "pages-count", &page_cnt)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200153 EMSG("pages-count is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100154 return false;
155 }
156
157 strncpy(memory_region.region_name, subnode_name,
158 sizeof(memory_region.region_name));
159 memory_region.base_addr = (uintptr_t)base_addr;
160 memory_region.region_size = page_cnt * FFA_SP_MANIFEST_PAGE_SIZE;
161
162 if (!config_store_add(CONFIG_CLASSIFIER_MEMORY_REGION,
163 memory_region.region_name, 0,
164 &memory_region, sizeof(memory_region))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200165 EMSG("failed to add memory region to config store");
Balint Dobszay286ff752022-03-04 15:57:19 +0100166 return false;
167 }
168 }
169 }
170
171 /* Find device regions */
172 node = fdt_node_offset_by_compatible(fdt, root, "arm,ffa-manifest-device-regions");
173 if (node >= 0) {
174 fdt_for_each_subnode(subnode, fdt, node) {
175 struct device_region device_region = {0};
176 uint64_t base_addr = 0;
177 uint32_t page_cnt = 0;
178 const char *subnode_name = fdt_get_name(fdt, subnode, NULL);
179
180 if (!subnode_name) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200181 EMSG("subnode name is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100182 return false;
183 }
184
185 if(!dt_get_u64(fdt, subnode, "base-address", &base_addr)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200186 EMSG("base-address is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100187 return false;
188 }
189
190 if (!dt_get_u32(fdt, subnode, "pages-count", &page_cnt)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200191 EMSG("pages-count is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100192 return false;
193 }
194
195 strncpy(device_region.dev_class, subnode_name,
196 sizeof(device_region.dev_class));
197 device_region.base_addr = base_addr;
198 device_region.io_region_size = page_cnt * FFA_SP_MANIFEST_PAGE_SIZE;
199 device_region.dev_instance = 0;
200
201 if (!config_store_add(CONFIG_CLASSIFIER_DEVICE_REGION,
202 device_region.dev_class, device_region.dev_instance,
203 &device_region, sizeof(device_region))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200204 EMSG("failed to add device region to config store");
Balint Dobszay286ff752022-03-04 15:57:19 +0100205 return false;
206 }
207 }
208 }
209
Imre Kisd40d6202022-03-22 19:20:14 +0100210 /* Find TPM event log */
211 node = fdt_node_offset_by_compatible(fdt, root, "arm,tpm_event_log");
212 if (node >= 0) {
213 uint64_t tpm_event_log_addr = 0;
214 uint32_t tpm_event_log_size = 0;
Imre Kise432e582022-07-07 16:35:45 +0200215 struct config_blob blob = { 0 };
Imre Kisd40d6202022-03-22 19:20:14 +0100216
Balint Dobszay43b7d982022-04-01 15:35:51 +0200217 if (!dt_get_u64(fdt, node, "tpm_event_log_addr", &tpm_event_log_addr)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200218 EMSG("tpm_event_log_addr is missing");
Imre Kisd40d6202022-03-22 19:20:14 +0100219 return false;
Balint Dobszay43b7d982022-04-01 15:35:51 +0200220 }
Imre Kisd40d6202022-03-22 19:20:14 +0100221
Balint Dobszay43b7d982022-04-01 15:35:51 +0200222 if (!dt_get_u32(fdt, node, "tpm_event_log_size", &tpm_event_log_size)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200223 EMSG("tpm_event_log_size is missing");
Imre Kisd40d6202022-03-22 19:20:14 +0100224 return false;
Balint Dobszay43b7d982022-04-01 15:35:51 +0200225 }
Imre Kisd40d6202022-03-22 19:20:14 +0100226
Imre Kise432e582022-07-07 16:35:45 +0200227 blob.data = (const void *)tpm_event_log_addr;
228 blob.data_len = tpm_event_log_size;
229
Imre Kisd40d6202022-03-22 19:20:14 +0100230 if (!config_store_add(CONFIG_CLASSIFIER_BLOB, "EVENT_LOG", 0,
Imre Kise432e582022-07-07 16:35:45 +0200231 (void *)&blob, sizeof(blob))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200232 EMSG("failed to add event log to config store");
Imre Kisd40d6202022-03-22 19:20:14 +0100233 return false;
234 }
235 }
236
Balint Dobszay9a747852023-04-18 18:08:49 +0200237 /* Find hardware features */
238 node = fdt_node_offset_by_compatible(fdt, root, "arm,hw-features");
239 if (node >= 0) {
240 const char *prop_name = NULL;
241 uint32_t prop_value = 0;
242 int prop_offset = 0;
243
244 fdt_for_each_property_offset(prop_offset, fdt, node) {
245 if (!dt_get_u32_by_offset(fdt, prop_offset, &prop_name, &prop_value)) {
246 /* skip other properties in the node, e.g. the compatible string */
247 DMSG("skipping non-u32 property '%s' in hw-features", prop_name);
248 continue;
249 }
250
251 if (!config_store_add(CONFIG_CLASSIFIER_HW_FEATURE, prop_name, 0,
252 &prop_value, sizeof(prop_value))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200253 EMSG("failed to add HW feature to config store");
Balint Dobszay9a747852023-04-18 18:08:49 +0200254 return false;
255 }
256 }
257 } else {
258 DMSG("arm,hw-features node not present in SP manifest");
259 }
260
Balint Dobszay286ff752022-03-04 15:57:19 +0100261 return true;
262}
Balint Dobszay8102ba72023-04-13 16:29:41 +0200263
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200264static bool sp_config_load_v1_0(struct ffa_boot_info_v1_0 *boot_info)
Balint Dobszay8102ba72023-04-13 16:29:41 +0200265{
266 /* Load deployment specific configuration */
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200267 for (size_t param_index = 0; param_index < boot_info->count; param_index++) {
268 const char *name = (const char *)boot_info->nvp[param_index].name;
269 const size_t name_max_size = sizeof(boot_info->nvp[param_index].name);
Balint Dobszay8102ba72023-04-13 16:29:41 +0200270
271 if (!strncmp(name, "DEVICE_REGIONS", name_max_size)) {
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200272 if (!load_device_regions(&boot_info->nvp[param_index])) {
Balint Dobszay8102ba72023-04-13 16:29:41 +0200273 EMSG("Failed to load device regions");
274 return false;
275 }
276 } else if (!strncmp(name, "MEMORY_REGIONS", name_max_size)) {
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200277 if (!load_memory_regions(&boot_info->nvp[param_index])) {
Balint Dobszay8102ba72023-04-13 16:29:41 +0200278 EMSG("Failed to load memory regions");
279 return false;
280 }
281 } else if (!memcmp(name, "TYPE_DT\0\0\0\0\0\0\0\0", name_max_size)) {
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200282 if (!load_fdt((void *)boot_info->nvp[param_index].value,
283 boot_info->nvp[param_index].size)) {
Balint Dobszay8102ba72023-04-13 16:29:41 +0200284 EMSG("Failed to load SP config from DT");
285 return false;
286 }
287 } else {
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200288 if (!load_blob(&boot_info->nvp[param_index])) {
Balint Dobszay8102ba72023-04-13 16:29:41 +0200289 EMSG("Failed to load blob");
290 return false;
291 }
292 }
293 }
294
295 return true;
296}
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200297
Balint Dobszay0100ddd2023-05-09 14:39:08 +0200298static bool sp_config_load_v1_1(struct ffa_boot_info_header_v1_1 *boot_info_header)
299{
300 size_t desc_end = 0;
301 size_t total_desc_size = 0;
302 struct ffa_boot_info_desc_v1_1 *boot_info_desc = NULL;
303 uint32_t expected_version = SHIFT_U32(1, FFA_VERSION_MAJOR_SHIFT) |
304 SHIFT_U32(1, FFA_VERSION_MINOR_SHIFT);
305
306 if (boot_info_header->version != expected_version) {
307 EMSG("Invalid FF-A boot info version");
308 return false;
309 }
310
311 if (boot_info_header->desc_size != sizeof(struct ffa_boot_info_desc_v1_1)) {
312 EMSG("Boot info descriptor size mismatch");
313 return false;
314 }
315
316 if (MUL_OVERFLOW(boot_info_header->desc_size, boot_info_header->desc_cnt,
317 &total_desc_size)) {
318 EMSG("Boot info descriptor overflow");
319 return false;
320 }
321
322 if (ADD_OVERFLOW(boot_info_header->desc_offs, total_desc_size, &desc_end) ||
323 boot_info_header->size < desc_end) {
324 EMSG("Boot info descriptor overflow");
325 return false;
326 }
327
328 boot_info_desc = (struct ffa_boot_info_desc_v1_1 *)((uintptr_t)boot_info_header +
329 boot_info_header->desc_offs);
330
331 for (unsigned int i = 0; i < boot_info_header->desc_cnt; i++) {
332 uint16_t flags = FFA_BOOT_INFO_CONTENT_FMT_ADDR << FFA_BOOT_INFO_CONTENT_FMT_SHIFT;
333 uint16_t type = FFA_BOOT_INFO_TYPE_STD << FFA_BOOT_INFO_TYPE_SHIFT |
334 FFA_BOOT_INFO_ID_STD_FDT << FFA_BOOT_INFO_ID_SHIFT;
335
336 if (boot_info_desc[i].flags == flags && boot_info_desc[i].type == type) {
337 if (!load_fdt((void *)boot_info_desc->contents, boot_info_desc->size)) {
338 EMSG("Failed to load SP config FDT");
339 return false;
340 }
341 }
342 }
343
344 return true;
345}
346
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200347bool sp_config_load(union ffa_boot_info *boot_info)
348{
349 if (!boot_info)
350 return false;
351
352 switch (boot_info->signature) {
353 case FFA_BOOT_INFO_SIGNATURE_V1_0:
354 return sp_config_load_v1_0((struct ffa_boot_info_v1_0 *)&boot_info->boot_info_v1_0);
Balint Dobszay0100ddd2023-05-09 14:39:08 +0200355 case FFA_BOOT_INFO_SIGNATURE_V1_1:
356 return sp_config_load_v1_1((struct ffa_boot_info_header_v1_1 *)
357 &boot_info->boot_info_v1_1);
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200358 default:
359 EMSG("Invalid FF-A boot info signature");
360 return false;
361 }
362
363 return false;
364}