blob: 760326bb3cf34539f87bfad2151e10f3c2a04244 [file] [log] [blame]
julhal0137e1aea2021-02-09 15:22:20 +00001// SPDX-License-Identifier: BSD-3-Clause
2/*
Imre Kis2d4d29f2024-04-26 12:57:22 +02003 * Copyright (c) 2021-2024, 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
Imre Kis2d4d29f2024-04-26 12:57:22 +020037 struct device_region device_region = { 0 };
Julian Hall7048d302021-06-03 16:07:28 +010038
Imre Kis06360812022-07-05 16:28:00 +020039 strncpy(device_region.dev_class, d->name,
Imre Kis2d4d29f2024-04-26 12:57:22 +020040 sizeof(device_region.dev_class) - 1);
41 device_region.dev_class[sizeof(device_region.dev_class) - 1] = '\0';
Julian Hall7048d302021-06-03 16:07:28 +010042 device_region.dev_instance = 0;
43 device_region.base_addr = d->location;
44 device_region.io_region_size = d->size;
45
Imre Kis06360812022-07-05 16:28:00 +020046 if (!config_store_add(CONFIG_CLASSIFIER_DEVICE_REGION,
47 device_region.dev_class,
48 device_region.dev_instance,
49 &device_region, sizeof(device_region))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +020050 EMSG("failed to add device region to config store");
Imre Kis06360812022-07-05 16:28:00 +020051 return false;
52 }
Julian Hall7048d302021-06-03 16:07:28 +010053
54 ++d;
55 }
Imre Kis06360812022-07-05 16:28:00 +020056
57 return true;
Julian Hall7048d302021-06-03 16:07:28 +010058}
59
Balint Dobszay4f9d8e32023-04-13 13:55:08 +020060static bool load_memory_regions(const struct ffa_name_value_pair_v1_0 *value_pair)
Julian Hall7048d302021-06-03 16:07:28 +010061{
Imre Kisfe6521e2021-10-27 20:20:37 +020062 struct sp_param_region *d = (struct sp_param_region *)value_pair->value;
63
64 /* Iterate over the device regions */
65 while ((uintptr_t)d < (value_pair->value + value_pair->size)) {
66
Imre Kis2d4d29f2024-04-26 12:57:22 +020067 struct memory_region memory_region = { 0 };
Imre Kisfe6521e2021-10-27 20:20:37 +020068
Imre Kis06360812022-07-05 16:28:00 +020069 strncpy(memory_region.region_name, d->name,
Imre Kis2d4d29f2024-04-26 12:57:22 +020070 sizeof(memory_region.region_name) - 1);
71 memory_region.region_name[sizeof(memory_region.region_name) - 1] = '\0';
Imre Kisfe6521e2021-10-27 20:20:37 +020072 memory_region.base_addr = d->location;
73 memory_region.region_size = d->size;
74
Imre Kis06360812022-07-05 16:28:00 +020075 if (!config_store_add(CONFIG_CLASSIFIER_MEMORY_REGION,
76 memory_region.region_name, 0,
77 &memory_region, sizeof(memory_region))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +020078 EMSG("failed to add memory region to config store");
Imre Kis06360812022-07-05 16:28:00 +020079 return false;
80 }
Imre Kisfe6521e2021-10-27 20:20:37 +020081
82 ++d;
83 }
Imre Kis06360812022-07-05 16:28:00 +020084
85 return true;
Julian Hall7048d302021-06-03 16:07:28 +010086}
87
Balint Dobszay4f9d8e32023-04-13 13:55:08 +020088static bool load_blob(const struct ffa_name_value_pair_v1_0 *value_pair)
Julian Hall7048d302021-06-03 16:07:28 +010089{
90 struct config_blob blob;
91
92 blob.data = (const void*)value_pair->value;
93 blob.data_len = value_pair->size;
94
Imre Kis06360812022-07-05 16:28:00 +020095 if (!config_store_add(CONFIG_CLASSIFIER_BLOB, (const char *)value_pair->name, 0,
96 &blob, sizeof(blob))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +020097 EMSG("failed to add blob to config store");
Imre Kis06360812022-07-05 16:28:00 +020098 return false;
99 }
100
101 return true;
Julian Hall7048d302021-06-03 16:07:28 +0100102}
Balint Dobszay286ff752022-03-04 15:57:19 +0100103
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200104static bool load_fdt(const void *fdt, size_t fdt_size)
Balint Dobszay286ff752022-03-04 15:57:19 +0100105{
Balint Dobszay286ff752022-03-04 15:57:19 +0100106 int root = -1, node = -1, subnode = -1, rc = -1;
Imre Kis06360812022-07-05 16:28:00 +0200107 static const char *ffa_manifest_compatible = "arm,ffa-manifest-1.0";
Balint Dobszay286ff752022-03-04 15:57:19 +0100108
109 /* Sanity check */
110 if (!fdt) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200111 EMSG("fdt NULL pointer");
Balint Dobszay286ff752022-03-04 15:57:19 +0100112 return false;
113 }
114
115 rc = fdt_check_full(fdt, fdt_size);
116 if (rc) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200117 EMSG("fdt_check_full(): %d", rc);
Balint Dobszay286ff752022-03-04 15:57:19 +0100118 return false;
119 }
120
121 /* Find root node */
122 root = fdt_path_offset(fdt, "/");
123 if (root < 0) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200124 EMSG("fdt_path_offset(): %d", root);
Balint Dobszay286ff752022-03-04 15:57:19 +0100125 return false;
126 }
127
128 /* Check if it's a valid SP manifest */
Imre Kis06360812022-07-05 16:28:00 +0200129 rc = fdt_node_check_compatible(fdt, root, ffa_manifest_compatible);
Balint Dobszay286ff752022-03-04 15:57:19 +0100130 if (rc) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200131 EMSG("fdt_node_check_compatible(%s): %d", ffa_manifest_compatible, rc);
Balint Dobszay286ff752022-03-04 15:57:19 +0100132 return false;
133 }
134
135 /* Find memory regions */
136 node = fdt_node_offset_by_compatible(fdt, root, "arm,ffa-manifest-memory-regions");
137 if (node >= 0) {
138 fdt_for_each_subnode(subnode, fdt, node) {
139 struct memory_region memory_region = {0};
140 uint64_t base_addr = 0;
141 uint32_t page_cnt = 0;
142 const char *subnode_name = fdt_get_name(fdt, subnode, NULL);
143
144 if (!subnode_name) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200145 EMSG("subnode name is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100146 return false;
147 }
148
149 if(!dt_get_u64(fdt, subnode, "base-address", &base_addr)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200150 EMSG("base-address is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100151 return false;
152 }
153
154 if(!dt_get_u32(fdt, subnode, "pages-count", &page_cnt)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200155 EMSG("pages-count is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100156 return false;
157 }
158
159 strncpy(memory_region.region_name, subnode_name,
Imre Kis2d4d29f2024-04-26 12:57:22 +0200160 sizeof(memory_region.region_name) - 1);
161 memory_region.region_name[sizeof(memory_region.region_name) - 1] = '\0';
Balint Dobszay286ff752022-03-04 15:57:19 +0100162 memory_region.base_addr = (uintptr_t)base_addr;
163 memory_region.region_size = page_cnt * FFA_SP_MANIFEST_PAGE_SIZE;
164
165 if (!config_store_add(CONFIG_CLASSIFIER_MEMORY_REGION,
166 memory_region.region_name, 0,
167 &memory_region, sizeof(memory_region))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200168 EMSG("failed to add memory region to config store");
Balint Dobszay286ff752022-03-04 15:57:19 +0100169 return false;
170 }
171 }
172 }
173
174 /* Find device regions */
175 node = fdt_node_offset_by_compatible(fdt, root, "arm,ffa-manifest-device-regions");
176 if (node >= 0) {
177 fdt_for_each_subnode(subnode, fdt, node) {
178 struct device_region device_region = {0};
179 uint64_t base_addr = 0;
180 uint32_t page_cnt = 0;
181 const char *subnode_name = fdt_get_name(fdt, subnode, NULL);
182
183 if (!subnode_name) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200184 EMSG("subnode name is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100185 return false;
186 }
187
188 if(!dt_get_u64(fdt, subnode, "base-address", &base_addr)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200189 EMSG("base-address is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100190 return false;
191 }
192
193 if (!dt_get_u32(fdt, subnode, "pages-count", &page_cnt)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200194 EMSG("pages-count is missing");
Balint Dobszay286ff752022-03-04 15:57:19 +0100195 return false;
196 }
197
198 strncpy(device_region.dev_class, subnode_name,
Imre Kis2d4d29f2024-04-26 12:57:22 +0200199 sizeof(device_region.dev_class) - 1);
200 device_region.dev_class[sizeof(device_region.dev_class) - 1] = '\0';
Balint Dobszay286ff752022-03-04 15:57:19 +0100201 device_region.base_addr = base_addr;
202 device_region.io_region_size = page_cnt * FFA_SP_MANIFEST_PAGE_SIZE;
203 device_region.dev_instance = 0;
204
205 if (!config_store_add(CONFIG_CLASSIFIER_DEVICE_REGION,
206 device_region.dev_class, device_region.dev_instance,
207 &device_region, sizeof(device_region))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200208 EMSG("failed to add device region to config store");
Balint Dobszay286ff752022-03-04 15:57:19 +0100209 return false;
210 }
211 }
212 }
213
Imre Kisd40d6202022-03-22 19:20:14 +0100214 /* Find TPM event log */
215 node = fdt_node_offset_by_compatible(fdt, root, "arm,tpm_event_log");
216 if (node >= 0) {
217 uint64_t tpm_event_log_addr = 0;
218 uint32_t tpm_event_log_size = 0;
Imre Kise432e582022-07-07 16:35:45 +0200219 struct config_blob blob = { 0 };
Imre Kisd40d6202022-03-22 19:20:14 +0100220
Balint Dobszay43b7d982022-04-01 15:35:51 +0200221 if (!dt_get_u64(fdt, node, "tpm_event_log_addr", &tpm_event_log_addr)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200222 EMSG("tpm_event_log_addr is missing");
Imre Kisd40d6202022-03-22 19:20:14 +0100223 return false;
Balint Dobszay43b7d982022-04-01 15:35:51 +0200224 }
Imre Kisd40d6202022-03-22 19:20:14 +0100225
Balint Dobszay43b7d982022-04-01 15:35:51 +0200226 if (!dt_get_u32(fdt, node, "tpm_event_log_size", &tpm_event_log_size)) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200227 EMSG("tpm_event_log_size is missing");
Imre Kisd40d6202022-03-22 19:20:14 +0100228 return false;
Balint Dobszay43b7d982022-04-01 15:35:51 +0200229 }
Imre Kisd40d6202022-03-22 19:20:14 +0100230
Imre Kise432e582022-07-07 16:35:45 +0200231 blob.data = (const void *)tpm_event_log_addr;
232 blob.data_len = tpm_event_log_size;
233
Imre Kisd40d6202022-03-22 19:20:14 +0100234 if (!config_store_add(CONFIG_CLASSIFIER_BLOB, "EVENT_LOG", 0,
Imre Kise432e582022-07-07 16:35:45 +0200235 (void *)&blob, sizeof(blob))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200236 EMSG("failed to add event log to config store");
Imre Kisd40d6202022-03-22 19:20:14 +0100237 return false;
238 }
239 }
240
Balint Dobszay9a747852023-04-18 18:08:49 +0200241 /* Find hardware features */
242 node = fdt_node_offset_by_compatible(fdt, root, "arm,hw-features");
243 if (node >= 0) {
244 const char *prop_name = NULL;
245 uint32_t prop_value = 0;
246 int prop_offset = 0;
247
248 fdt_for_each_property_offset(prop_offset, fdt, node) {
249 if (!dt_get_u32_by_offset(fdt, prop_offset, &prop_name, &prop_value)) {
250 /* skip other properties in the node, e.g. the compatible string */
251 DMSG("skipping non-u32 property '%s' in hw-features", prop_name);
252 continue;
253 }
254
255 if (!config_store_add(CONFIG_CLASSIFIER_HW_FEATURE, prop_name, 0,
256 &prop_value, sizeof(prop_value))) {
Balint Dobszay3d1c5742023-04-24 10:40:26 +0200257 EMSG("failed to add HW feature to config store");
Balint Dobszay9a747852023-04-18 18:08:49 +0200258 return false;
259 }
260 }
261 } else {
262 DMSG("arm,hw-features node not present in SP manifest");
263 }
264
Balint Dobszay286ff752022-03-04 15:57:19 +0100265 return true;
266}
Balint Dobszay8102ba72023-04-13 16:29:41 +0200267
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200268static bool sp_config_load_v1_0(struct ffa_boot_info_v1_0 *boot_info)
Balint Dobszay8102ba72023-04-13 16:29:41 +0200269{
270 /* Load deployment specific configuration */
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200271 for (size_t param_index = 0; param_index < boot_info->count; param_index++) {
272 const char *name = (const char *)boot_info->nvp[param_index].name;
273 const size_t name_max_size = sizeof(boot_info->nvp[param_index].name);
Balint Dobszay8102ba72023-04-13 16:29:41 +0200274
275 if (!strncmp(name, "DEVICE_REGIONS", name_max_size)) {
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200276 if (!load_device_regions(&boot_info->nvp[param_index])) {
Balint Dobszay8102ba72023-04-13 16:29:41 +0200277 EMSG("Failed to load device regions");
278 return false;
279 }
280 } else if (!strncmp(name, "MEMORY_REGIONS", name_max_size)) {
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200281 if (!load_memory_regions(&boot_info->nvp[param_index])) {
Balint Dobszay8102ba72023-04-13 16:29:41 +0200282 EMSG("Failed to load memory regions");
283 return false;
284 }
285 } else if (!memcmp(name, "TYPE_DT\0\0\0\0\0\0\0\0", name_max_size)) {
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200286 if (!load_fdt((void *)boot_info->nvp[param_index].value,
287 boot_info->nvp[param_index].size)) {
Balint Dobszay8102ba72023-04-13 16:29:41 +0200288 EMSG("Failed to load SP config from DT");
289 return false;
290 }
291 } else {
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200292 if (!load_blob(&boot_info->nvp[param_index])) {
Balint Dobszay8102ba72023-04-13 16:29:41 +0200293 EMSG("Failed to load blob");
294 return false;
295 }
296 }
297 }
298
299 return true;
300}
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200301
Balint Dobszay0100ddd2023-05-09 14:39:08 +0200302static bool sp_config_load_v1_1(struct ffa_boot_info_header_v1_1 *boot_info_header)
303{
304 size_t desc_end = 0;
305 size_t total_desc_size = 0;
306 struct ffa_boot_info_desc_v1_1 *boot_info_desc = NULL;
307 uint32_t expected_version = SHIFT_U32(1, FFA_VERSION_MAJOR_SHIFT) |
308 SHIFT_U32(1, FFA_VERSION_MINOR_SHIFT);
309
310 if (boot_info_header->version != expected_version) {
311 EMSG("Invalid FF-A boot info version");
312 return false;
313 }
314
315 if (boot_info_header->desc_size != sizeof(struct ffa_boot_info_desc_v1_1)) {
316 EMSG("Boot info descriptor size mismatch");
317 return false;
318 }
319
320 if (MUL_OVERFLOW(boot_info_header->desc_size, boot_info_header->desc_cnt,
321 &total_desc_size)) {
322 EMSG("Boot info descriptor overflow");
323 return false;
324 }
325
326 if (ADD_OVERFLOW(boot_info_header->desc_offs, total_desc_size, &desc_end) ||
327 boot_info_header->size < desc_end) {
328 EMSG("Boot info descriptor overflow");
329 return false;
330 }
331
332 boot_info_desc = (struct ffa_boot_info_desc_v1_1 *)((uintptr_t)boot_info_header +
333 boot_info_header->desc_offs);
334
335 for (unsigned int i = 0; i < boot_info_header->desc_cnt; i++) {
336 uint16_t flags = FFA_BOOT_INFO_CONTENT_FMT_ADDR << FFA_BOOT_INFO_CONTENT_FMT_SHIFT;
337 uint16_t type = FFA_BOOT_INFO_TYPE_STD << FFA_BOOT_INFO_TYPE_SHIFT |
338 FFA_BOOT_INFO_ID_STD_FDT << FFA_BOOT_INFO_ID_SHIFT;
339
340 if (boot_info_desc[i].flags == flags && boot_info_desc[i].type == type) {
341 if (!load_fdt((void *)boot_info_desc->contents, boot_info_desc->size)) {
342 EMSG("Failed to load SP config FDT");
343 return false;
344 }
345 }
346 }
347
348 return true;
349}
350
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200351bool sp_config_load(union ffa_boot_info *boot_info)
352{
353 if (!boot_info)
354 return false;
355
356 switch (boot_info->signature) {
357 case FFA_BOOT_INFO_SIGNATURE_V1_0:
358 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 +0200359 case FFA_BOOT_INFO_SIGNATURE_V1_1:
360 return sp_config_load_v1_1((struct ffa_boot_info_header_v1_1 *)
361 &boot_info->boot_info_v1_1);
Balint Dobszay4f9d8e32023-04-13 13:55:08 +0200362 default:
363 EMSG("Invalid FF-A boot info signature");
364 return false;
365 }
366
367 return false;
368}