blob: 0b8e71670416c8dc89ca30520d9cde3b22c42294 [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
Julian Hall7048d302021-06-03 16:07:28 +010029static void load_device_regions(const struct ffa_name_value_pair *value_pair);
30static void load_memory_regions(const struct ffa_name_value_pair *value_pair);
31static void 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 */
40void sp_config_load(struct ffa_init_info *init_info)
41{
42 /* Load deployment specific configuration */
43 for (size_t param_index = 0; param_index < init_info->count; param_index++) {
44
45 if (!strcmp((const char *)init_info->nvp[param_index].name,"DEVICE_REGIONS")) {
46
Julian Hall7048d302021-06-03 16:07:28 +010047 load_device_regions(&init_info->nvp[param_index]);
48 }
49 else if (!strcmp((const char *)init_info->nvp[param_index].name,"MEMORY_REGIONS")) {
julhal0137e1aea2021-02-09 15:22:20 +000050
Julian Hall7048d302021-06-03 16:07:28 +010051 load_memory_regions(&init_info->nvp[param_index]);
52 }
Balint Dobszay286ff752022-03-04 15:57:19 +010053 else if (!memcmp(init_info->nvp[param_index].name,"TYPE_DT\0\0\0\0\0\0\0\0",
54 sizeof(init_info->nvp[param_index].name))) {
55 if (!load_fdt(&init_info->nvp[param_index]))
56 EMSG("Failed to load SP config from DT");
57 }
Julian Hall7048d302021-06-03 16:07:28 +010058 else {
julhal0137e1aea2021-02-09 15:22:20 +000059
Julian Hall7048d302021-06-03 16:07:28 +010060 load_blob(&init_info->nvp[param_index]);
julhal0137e1aea2021-02-09 15:22:20 +000061 }
62 }
63}
Julian Hall7048d302021-06-03 16:07:28 +010064
65static void load_device_regions(const struct ffa_name_value_pair *value_pair)
66{
Imre Kisfe6521e2021-10-27 20:20:37 +020067 struct sp_param_region *d = (struct sp_param_region *)value_pair->value;
Julian Hall7048d302021-06-03 16:07:28 +010068
69 /* Iterate over the device regions */
70 while ((uintptr_t)d < (value_pair->value + value_pair->size)) {
71
72 struct device_region device_region;
73
74 strcpy(device_region.dev_class, d->name);
75 device_region.dev_instance = 0;
76 device_region.base_addr = d->location;
77 device_region.io_region_size = d->size;
78
79 config_store_add(CONFIG_CLASSIFIER_DEVICE_REGION,
80 device_region.dev_class, device_region.dev_instance,
81 &device_region, sizeof(device_region));
82
83 ++d;
84 }
85}
86
87static void load_memory_regions(const struct ffa_name_value_pair *value_pair)
88{
Imre Kisfe6521e2021-10-27 20:20:37 +020089 struct sp_param_region *d = (struct sp_param_region *)value_pair->value;
90
91 /* Iterate over the device regions */
92 while ((uintptr_t)d < (value_pair->value + value_pair->size)) {
93
94 struct memory_region memory_region;
95
96 strcpy(memory_region.region_name, d->name);
97 memory_region.base_addr = d->location;
98 memory_region.region_size = d->size;
99
100 config_store_add(CONFIG_CLASSIFIER_MEMORY_REGION,
101 memory_region.region_name, 0,
102 &memory_region, sizeof(memory_region));
103
104 ++d;
105 }
Julian Hall7048d302021-06-03 16:07:28 +0100106}
107
108static void load_blob(const struct ffa_name_value_pair *value_pair)
109{
110 struct config_blob blob;
111
112 blob.data = (const void*)value_pair->value;
113 blob.data_len = value_pair->size;
114
115 config_store_add(CONFIG_CLASSIFIER_BLOB,
116 (const char *)value_pair->name, 0,
117 &blob, sizeof(blob));
118}
Balint Dobszay286ff752022-03-04 15:57:19 +0100119
120static bool load_fdt(const struct ffa_name_value_pair *value_pair)
121{
122 const void *fdt = (const void *)value_pair->value;
123 size_t fdt_size = value_pair->size;
124 int root = -1, node = -1, subnode = -1, rc = -1;
125
126 /* Sanity check */
127 if (!fdt) {
128 DMSG("error: fdt NULL pointer");
129 return false;
130 }
131
132 rc = fdt_check_full(fdt, fdt_size);
133 if (rc) {
134 DMSG("error: fdt_check_full(): %d", rc);
135 return false;
136 }
137
138 /* Find root node */
139 root = fdt_path_offset(fdt, "/");
140 if (root < 0) {
141 DMSG("error: fdt_path_offset(): %d", root);
142 return false;
143 }
144
145 /* Check if it's a valid SP manifest */
146 rc = fdt_node_check_compatible(fdt, root, "arm,ffa-manifest-1.0");
147 if (rc) {
148 DMSG("error: fdt_node_check_compatible(): %d", rc);
149 return false;
150 }
151
152 /* Find memory regions */
153 node = fdt_node_offset_by_compatible(fdt, root, "arm,ffa-manifest-memory-regions");
154 if (node >= 0) {
155 fdt_for_each_subnode(subnode, fdt, node) {
156 struct memory_region memory_region = {0};
157 uint64_t base_addr = 0;
158 uint32_t page_cnt = 0;
159 const char *subnode_name = fdt_get_name(fdt, subnode, NULL);
160
161 if (!subnode_name) {
162 DMSG("error: subnode name is missing");
163 return false;
164 }
165
166 if(!dt_get_u64(fdt, subnode, "base-address", &base_addr)) {
167 DMSG("error: base-address is missing");
168 return false;
169 }
170
171 if(!dt_get_u32(fdt, subnode, "pages-count", &page_cnt)) {
172 DMSG("error: pages-count is missing");
173 return false;
174 }
175
176 strncpy(memory_region.region_name, subnode_name,
177 sizeof(memory_region.region_name));
178 memory_region.base_addr = (uintptr_t)base_addr;
179 memory_region.region_size = page_cnt * FFA_SP_MANIFEST_PAGE_SIZE;
180
181 if (!config_store_add(CONFIG_CLASSIFIER_MEMORY_REGION,
182 memory_region.region_name, 0,
183 &memory_region, sizeof(memory_region))) {
184 DMSG("error: failed to add memory region to config store");
185 return false;
186 }
187 }
188 }
189
190 /* Find device regions */
191 node = fdt_node_offset_by_compatible(fdt, root, "arm,ffa-manifest-device-regions");
192 if (node >= 0) {
193 fdt_for_each_subnode(subnode, fdt, node) {
194 struct device_region device_region = {0};
195 uint64_t base_addr = 0;
196 uint32_t page_cnt = 0;
197 const char *subnode_name = fdt_get_name(fdt, subnode, NULL);
198
199 if (!subnode_name) {
200 DMSG("error: subnode name is missing");
201 return false;
202 }
203
204 if(!dt_get_u64(fdt, subnode, "base-address", &base_addr)) {
205 DMSG("error: base-address is missing");
206 return false;
207 }
208
209 if (!dt_get_u32(fdt, subnode, "pages-count", &page_cnt)) {
210 DMSG("error: pages-count is missing");
211 return false;
212 }
213
214 strncpy(device_region.dev_class, subnode_name,
215 sizeof(device_region.dev_class));
216 device_region.base_addr = base_addr;
217 device_region.io_region_size = page_cnt * FFA_SP_MANIFEST_PAGE_SIZE;
218 device_region.dev_instance = 0;
219
220 if (!config_store_add(CONFIG_CLASSIFIER_DEVICE_REGION,
221 device_region.dev_class, device_region.dev_instance,
222 &device_region, sizeof(device_region))) {
223 DMSG("error: failed to add device region to config store");
224 return false;
225 }
226 }
227 }
228
Imre Kisd40d6202022-03-22 19:20:14 +0100229 /* Find TPM event log */
230 node = fdt_node_offset_by_compatible(fdt, root, "arm,tpm_event_log");
231 if (node >= 0) {
232 uint64_t tpm_event_log_addr = 0;
233 uint32_t tpm_event_log_size = 0;
234
235 rc = dt_get_u64(fdt, node, "tpm_event_log_addr", &tpm_event_log_addr);
236 if (rc)
237 return false;
238
239 rc = dt_get_u32(fdt, node, "tpm_event_log_size", &tpm_event_log_size);
240 if (rc)
241 return false;
242
243 if (!config_store_add(CONFIG_CLASSIFIER_BLOB, "EVENT_LOG", 0,
244 (void *)tpm_event_log_addr, tpm_event_log_size)) {
245 return false;
246 }
247 }
248
Balint Dobszay286ff752022-03-04 15:57:19 +0100249 return true;
250}