Enable loading SP config from devicetree
Extend the SP config loader component to load device and memory region
information from the SP manifest.
Signed-off-by: Balint Dobszay <balint.dobszay@arm.com>
Change-Id: I72a701751b4070944a08bc6d005061f17b69cc10
diff --git a/components/config/loader/sp/sp_config_loader.c b/components/config/loader/sp/sp_config_loader.c
index fd052f4..94c2e0b 100644
--- a/components/config/loader/sp/sp_config_loader.c
+++ b/components/config/loader/sp/sp_config_loader.c
@@ -1,15 +1,24 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
*/
-#include <string.h>
+#include <common/fdt/fdt_helpers.h>
#include <config/interface/config_store.h>
#include <config/interface/config_blob.h>
#include <platform/interface/device_region.h>
-#include "platform/interface/memory_region.h"
+#include <platform/interface/memory_region.h>
+#include <stdbool.h>
+#include <string.h>
+#include <trace.h>
+
#include "sp_config_loader.h"
+/*
+ * According to the FF-A 1.0 spec: in the SP manifest the size of device and
+ * memory regions is expressed as a count of 4K pages.
+ */
+#define FFA_SP_MANIFEST_PAGE_SIZE 0x1000
struct sp_param_region {
char name[16];
@@ -20,6 +29,7 @@
static void load_device_regions(const struct ffa_name_value_pair *value_pair);
static void load_memory_regions(const struct ffa_name_value_pair *value_pair);
static void load_blob(const struct ffa_name_value_pair *value_pair);
+static bool load_fdt(const struct ffa_name_value_pair *value_pair);
/**
* Loads externally provided configuration data passed into the SP via
@@ -40,6 +50,11 @@
load_memory_regions(&init_info->nvp[param_index]);
}
+ else if (!memcmp(init_info->nvp[param_index].name,"TYPE_DT\0\0\0\0\0\0\0\0",
+ sizeof(init_info->nvp[param_index].name))) {
+ if (!load_fdt(&init_info->nvp[param_index]))
+ EMSG("Failed to load SP config from DT");
+ }
else {
load_blob(&init_info->nvp[param_index]);
@@ -101,3 +116,115 @@
(const char *)value_pair->name, 0,
&blob, sizeof(blob));
}
+
+static bool load_fdt(const struct ffa_name_value_pair *value_pair)
+{
+ const void *fdt = (const void *)value_pair->value;
+ size_t fdt_size = value_pair->size;
+ int root = -1, node = -1, subnode = -1, rc = -1;
+
+ /* Sanity check */
+ if (!fdt) {
+ DMSG("error: fdt NULL pointer");
+ return false;
+ }
+
+ rc = fdt_check_full(fdt, fdt_size);
+ if (rc) {
+ DMSG("error: fdt_check_full(): %d", rc);
+ return false;
+ }
+
+ /* Find root node */
+ root = fdt_path_offset(fdt, "/");
+ if (root < 0) {
+ DMSG("error: fdt_path_offset(): %d", root);
+ return false;
+ }
+
+ /* Check if it's a valid SP manifest */
+ rc = fdt_node_check_compatible(fdt, root, "arm,ffa-manifest-1.0");
+ if (rc) {
+ DMSG("error: fdt_node_check_compatible(): %d", rc);
+ return false;
+ }
+
+ /* Find memory regions */
+ node = fdt_node_offset_by_compatible(fdt, root, "arm,ffa-manifest-memory-regions");
+ if (node >= 0) {
+ fdt_for_each_subnode(subnode, fdt, node) {
+ struct memory_region memory_region = {0};
+ uint64_t base_addr = 0;
+ uint32_t page_cnt = 0;
+ const char *subnode_name = fdt_get_name(fdt, subnode, NULL);
+
+ if (!subnode_name) {
+ DMSG("error: subnode name is missing");
+ return false;
+ }
+
+ if(!dt_get_u64(fdt, subnode, "base-address", &base_addr)) {
+ DMSG("error: base-address is missing");
+ return false;
+ }
+
+ if(!dt_get_u32(fdt, subnode, "pages-count", &page_cnt)) {
+ DMSG("error: pages-count is missing");
+ return false;
+ }
+
+ strncpy(memory_region.region_name, subnode_name,
+ sizeof(memory_region.region_name));
+ memory_region.base_addr = (uintptr_t)base_addr;
+ memory_region.region_size = page_cnt * FFA_SP_MANIFEST_PAGE_SIZE;
+
+ if (!config_store_add(CONFIG_CLASSIFIER_MEMORY_REGION,
+ memory_region.region_name, 0,
+ &memory_region, sizeof(memory_region))) {
+ DMSG("error: failed to add memory region to config store");
+ return false;
+ }
+ }
+ }
+
+ /* Find device regions */
+ node = fdt_node_offset_by_compatible(fdt, root, "arm,ffa-manifest-device-regions");
+ if (node >= 0) {
+ fdt_for_each_subnode(subnode, fdt, node) {
+ struct device_region device_region = {0};
+ uint64_t base_addr = 0;
+ uint32_t page_cnt = 0;
+ const char *subnode_name = fdt_get_name(fdt, subnode, NULL);
+
+ if (!subnode_name) {
+ DMSG("error: subnode name is missing");
+ return false;
+ }
+
+ if(!dt_get_u64(fdt, subnode, "base-address", &base_addr)) {
+ DMSG("error: base-address is missing");
+ return false;
+ }
+
+ if (!dt_get_u32(fdt, subnode, "pages-count", &page_cnt)) {
+ DMSG("error: pages-count is missing");
+ return false;
+ }
+
+ strncpy(device_region.dev_class, subnode_name,
+ sizeof(device_region.dev_class));
+ device_region.base_addr = base_addr;
+ device_region.io_region_size = page_cnt * FFA_SP_MANIFEST_PAGE_SIZE;
+ device_region.dev_instance = 0;
+
+ if (!config_store_add(CONFIG_CLASSIFIER_DEVICE_REGION,
+ device_region.dev_class, device_region.dev_instance,
+ &device_region, sizeof(device_region))) {
+ DMSG("error: failed to add device region to config store");
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
diff --git a/deployments/attestation/opteesp/CMakeLists.txt b/deployments/attestation/opteesp/CMakeLists.txt
index 6e22648..351914a 100644
--- a/deployments/attestation/opteesp/CMakeLists.txt
+++ b/deployments/attestation/opteesp/CMakeLists.txt
@@ -37,6 +37,7 @@
add_components(TARGET "attestation"
BASE_DIR ${TS_ROOT}
COMPONENTS
+ "components/common/fdt"
"components/common/tlv"
"components/common/trace"
"components/common/utils"
diff --git a/deployments/crypto/opteesp/CMakeLists.txt b/deployments/crypto/opteesp/CMakeLists.txt
index 8276e67..b06301a 100644
--- a/deployments/crypto/opteesp/CMakeLists.txt
+++ b/deployments/crypto/opteesp/CMakeLists.txt
@@ -31,6 +31,7 @@
add_components(TARGET "crypto-sp"
BASE_DIR ${TS_ROOT}
COMPONENTS
+ "components/common/fdt"
"components/common/tlv"
"components/common/trace"
"components/common/utils"
diff --git a/deployments/env-test/opteesp/CMakeLists.txt b/deployments/env-test/opteesp/CMakeLists.txt
index 5377961..04732ac 100644
--- a/deployments/env-test/opteesp/CMakeLists.txt
+++ b/deployments/env-test/opteesp/CMakeLists.txt
@@ -32,6 +32,7 @@
add_components(TARGET "env-test"
BASE_DIR ${TS_ROOT}
COMPONENTS
+ "components/common/fdt"
"components/common/trace"
"components/common/utils"
"components/config/loader/sp"
diff --git a/deployments/se-proxy/opteesp/CMakeLists.txt b/deployments/se-proxy/opteesp/CMakeLists.txt
index 1d75963..eae1d38 100644
--- a/deployments/se-proxy/opteesp/CMakeLists.txt
+++ b/deployments/se-proxy/opteesp/CMakeLists.txt
@@ -31,6 +31,7 @@
add_components(TARGET "se-proxy"
BASE_DIR ${TS_ROOT}
COMPONENTS
+ "components/common/fdt"
"components/common/trace"
"components/common/utils"
"protocols/rpc/common/packed-c"
diff --git a/deployments/smm-gateway/opteesp/CMakeLists.txt b/deployments/smm-gateway/opteesp/CMakeLists.txt
index 4a4d7ff..5f682b5 100644
--- a/deployments/smm-gateway/opteesp/CMakeLists.txt
+++ b/deployments/smm-gateway/opteesp/CMakeLists.txt
@@ -34,6 +34,7 @@
add_components(TARGET "smm-gateway"
BASE_DIR ${TS_ROOT}
COMPONENTS
+ "components/common/fdt"
"components/common/trace"
"components/common/utils"
"components/common/uuid"