xref: /rk3399_ARM-atf/plat/common/plat_spmd_manifest.c (revision 8c829a9240109dd7a66a3c26f734f23477b12551)
10cb64d01SAchin Gupta /*
2*8c829a92SManish V Badarkhe  * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
30cb64d01SAchin Gupta  *
40cb64d01SAchin Gupta  * SPDX-License-Identifier: BSD-3-Clause
50cb64d01SAchin Gupta  */
60cb64d01SAchin Gupta 
70cb64d01SAchin Gupta #include <assert.h>
852696946SOlivier Deprez #include <errno.h>
94ce3e99aSScott Branden #include <inttypes.h>
100cb64d01SAchin Gupta #include <libfdt.h>
114ce3e99aSScott Branden #include <stdint.h>
124ce3e99aSScott Branden #include <string.h>
130cb64d01SAchin Gupta 
14cb7b9db1SVarun Wadekar #include <common/bl_common.h>
150cb64d01SAchin Gupta #include <common/debug.h>
160cb64d01SAchin Gupta #include <common/fdt_wrappers.h>
1723d5ba86SOlivier Deprez #include <lib/xlat_tables/xlat_tables_v2.h>
180cb64d01SAchin Gupta #include <platform_def.h>
190cb64d01SAchin Gupta #include <services/spm_core_manifest.h>
200cb64d01SAchin Gupta 
2152696946SOlivier Deprez #define ATTRIBUTE_ROOT_NODE_STR "attribute"
2252696946SOlivier Deprez 
230cb64d01SAchin Gupta /*******************************************************************************
2452696946SOlivier Deprez  * SPMC attribute node parser
250cb64d01SAchin Gupta  ******************************************************************************/
2652696946SOlivier Deprez static int manifest_parse_attribute(spmc_manifest_attribute_t *attr,
270cb64d01SAchin Gupta 				    const void *fdt,
280cb64d01SAchin Gupta 				    int node)
290cb64d01SAchin Gupta {
30ff4e6c35SAndre Przywara 	uint32_t val32;
3152696946SOlivier Deprez 	int rc;
320cb64d01SAchin Gupta 
3352696946SOlivier Deprez 	assert((attr != NULL) && (fdt != NULL));
340cb64d01SAchin Gupta 
35ff4e6c35SAndre Przywara 	rc = fdt_read_uint32(fdt, node, "maj_ver", &attr->major_version);
3652696946SOlivier Deprez 	if (rc != 0) {
37662af36dSJ-Alves 		ERROR("Missing FFA %s version in SPM Core manifest.\n",
3852696946SOlivier Deprez 			"major");
3952696946SOlivier Deprez 		return rc;
400cb64d01SAchin Gupta 	}
410cb64d01SAchin Gupta 
42ff4e6c35SAndre Przywara 	rc = fdt_read_uint32(fdt, node, "min_ver", &attr->minor_version);
4352696946SOlivier Deprez 	if (rc != 0) {
44662af36dSJ-Alves 		ERROR("Missing FFA %s version in SPM Core manifest.\n",
4552696946SOlivier Deprez 			"minor");
4652696946SOlivier Deprez 		return rc;
470cb64d01SAchin Gupta 	}
480cb64d01SAchin Gupta 
49ff4e6c35SAndre Przywara 	rc = fdt_read_uint32(fdt, node, "spmc_id", &val32);
5052696946SOlivier Deprez 	if (rc != 0) {
51ac03ac5eSMax Shvetsov 		ERROR("Missing SPMC ID in manifest.\n");
5252696946SOlivier Deprez 		return rc;
53ac03ac5eSMax Shvetsov 	}
5452696946SOlivier Deprez 
5552696946SOlivier Deprez 	attr->spmc_id = val32 & 0xffff;
56ac03ac5eSMax Shvetsov 
57ff4e6c35SAndre Przywara 	rc = fdt_read_uint32(fdt, node, "exec_state", &attr->exec_state);
5852696946SOlivier Deprez 	if (rc != 0) {
5952696946SOlivier Deprez 		NOTICE("%s not specified in SPM Core manifest.\n",
6052696946SOlivier Deprez 			"Execution state");
6152696946SOlivier Deprez 	}
620cb64d01SAchin Gupta 
63ff4e6c35SAndre Przywara 	rc = fdt_read_uint32(fdt, node, "binary_size", &attr->binary_size);
6452696946SOlivier Deprez 	if (rc != 0) {
6552696946SOlivier Deprez 		NOTICE("%s not specified in SPM Core manifest.\n",
6652696946SOlivier Deprez 			"Binary size");
6752696946SOlivier Deprez 	}
680cb64d01SAchin Gupta 
69ff4e6c35SAndre Przywara 	rc = fdt_read_uint64(fdt, node, "load_address", &attr->load_address);
7052696946SOlivier Deprez 	if (rc != 0) {
7152696946SOlivier Deprez 		NOTICE("%s not specified in SPM Core manifest.\n",
7252696946SOlivier Deprez 			"Load address");
7352696946SOlivier Deprez 	}
740cb64d01SAchin Gupta 
75ff4e6c35SAndre Przywara 	rc = fdt_read_uint64(fdt, node, "entrypoint", &attr->entrypoint);
7652696946SOlivier Deprez 	if (rc != 0) {
7752696946SOlivier Deprez 		NOTICE("%s not specified in SPM Core manifest.\n",
7852696946SOlivier Deprez 			"Entry point");
7952696946SOlivier Deprez 	}
800cb64d01SAchin Gupta 
8152696946SOlivier Deprez 	VERBOSE("SPM Core manifest attribute section:\n");
8252696946SOlivier Deprez 	VERBOSE("  version: %u.%u\n", attr->major_version, attr->minor_version);
8352696946SOlivier Deprez 	VERBOSE("  spmc_id: 0x%x\n", attr->spmc_id);
840cb64d01SAchin Gupta 	VERBOSE("  binary_size: 0x%x\n", attr->binary_size);
854ce3e99aSScott Branden 	VERBOSE("  load_address: 0x%" PRIx64 "\n", attr->load_address);
864ce3e99aSScott Branden 	VERBOSE("  entrypoint: 0x%" PRIx64 "\n", attr->entrypoint);
870cb64d01SAchin Gupta 
880cb64d01SAchin Gupta 	return 0;
890cb64d01SAchin Gupta }
900cb64d01SAchin Gupta 
910cb64d01SAchin Gupta /*******************************************************************************
920cb64d01SAchin Gupta  * Root node handler
930cb64d01SAchin Gupta  ******************************************************************************/
9452696946SOlivier Deprez static int manifest_parse_root(spmc_manifest_attribute_t *manifest,
950cb64d01SAchin Gupta 			       const void *fdt,
960cb64d01SAchin Gupta 			       int root)
970cb64d01SAchin Gupta {
980cb64d01SAchin Gupta 	int node;
990cb64d01SAchin Gupta 
10052696946SOlivier Deprez 	assert(manifest != NULL);
10152696946SOlivier Deprez 
10252696946SOlivier Deprez 	node = fdt_subnode_offset_namelen(fdt, root, ATTRIBUTE_ROOT_NODE_STR,
10352696946SOlivier Deprez 		sizeof(ATTRIBUTE_ROOT_NODE_STR) - 1);
1040cb64d01SAchin Gupta 	if (node < 0) {
10552696946SOlivier Deprez 		ERROR("Root node doesn't contain subnode '%s'\n",
10652696946SOlivier Deprez 			ATTRIBUTE_ROOT_NODE_STR);
10752696946SOlivier Deprez 		return node;
1080cb64d01SAchin Gupta 	}
1090cb64d01SAchin Gupta 
1100cb64d01SAchin Gupta 	return manifest_parse_attribute(manifest, fdt, node);
1110cb64d01SAchin Gupta }
1120cb64d01SAchin Gupta 
1130cb64d01SAchin Gupta /*******************************************************************************
11452696946SOlivier Deprez  * Platform handler to parse a SPM Core manifest.
1150cb64d01SAchin Gupta  ******************************************************************************/
11652696946SOlivier Deprez int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest,
11723d5ba86SOlivier Deprez 				const void *pm_addr)
1180cb64d01SAchin Gupta {
11923d5ba86SOlivier Deprez 	int rc, unmap_ret;
12023d5ba86SOlivier Deprez 	uintptr_t pm_base, pm_base_align;
12123d5ba86SOlivier Deprez 	size_t mapped_size;
1220cb64d01SAchin Gupta 
1230cb64d01SAchin Gupta 	assert(manifest != NULL);
12423d5ba86SOlivier Deprez 	assert(pm_addr != NULL);
1250cb64d01SAchin Gupta 
12623d5ba86SOlivier Deprez 	/*
12723d5ba86SOlivier Deprez 	 * Assume TOS_FW_CONFIG is not necessarily aligned to a page
12823d5ba86SOlivier Deprez 	 * boundary, thus calculate the remaining space between SPMC
12923d5ba86SOlivier Deprez 	 * manifest start address and upper page limit.
13023d5ba86SOlivier Deprez 	 *
13123d5ba86SOlivier Deprez 	 */
13223d5ba86SOlivier Deprez 	pm_base = (uintptr_t)pm_addr;
13323d5ba86SOlivier Deprez 	pm_base_align = page_align(pm_base, UP);
134fdd5f9e6SManish Pandey 
135fdd5f9e6SManish Pandey 	if (pm_base == pm_base_align) {
136fdd5f9e6SManish Pandey 		/* Page aligned */
137fdd5f9e6SManish Pandey 		mapped_size = PAGE_SIZE;
138fdd5f9e6SManish Pandey 	} else {
13923d5ba86SOlivier Deprez 		mapped_size = pm_base_align - pm_base;
140fdd5f9e6SManish Pandey 	}
1410cb64d01SAchin Gupta 
14223d5ba86SOlivier Deprez 	/* Check space within the page at least maps the FDT header */
14323d5ba86SOlivier Deprez 	if (mapped_size < sizeof(struct fdt_header)) {
14423d5ba86SOlivier Deprez 		ERROR("Error while mapping SPM Core manifest.\n");
14523d5ba86SOlivier Deprez 		return -EINVAL;
14623d5ba86SOlivier Deprez 	}
14723d5ba86SOlivier Deprez 
14823d5ba86SOlivier Deprez 	/* Map first SPMC manifest page in the SPMD translation regime */
14923d5ba86SOlivier Deprez 	pm_base_align = page_align(pm_base, DOWN);
15023d5ba86SOlivier Deprez 	rc = mmap_add_dynamic_region((unsigned long long)pm_base_align,
15123d5ba86SOlivier Deprez 				     pm_base_align,
15223d5ba86SOlivier Deprez 				     PAGE_SIZE,
153*8c829a92SManish V Badarkhe 				     MT_RO_DATA | EL3_PAS);
1540cb64d01SAchin Gupta 	if (rc != 0) {
15523d5ba86SOlivier Deprez 		ERROR("Error while mapping SPM Core manifest (%d).\n", rc);
15652696946SOlivier Deprez 		return rc;
1570cb64d01SAchin Gupta 	}
1580cb64d01SAchin Gupta 
15923d5ba86SOlivier Deprez 	rc = fdt_check_header(pm_addr);
16023d5ba86SOlivier Deprez 	if (rc != 0) {
16123d5ba86SOlivier Deprez 		ERROR("Wrong format for SPM Core manifest (%d).\n", rc);
16223d5ba86SOlivier Deprez 		goto exit_unmap;
16323d5ba86SOlivier Deprez 	}
16423d5ba86SOlivier Deprez 
16523d5ba86SOlivier Deprez 	/* Check SPMC manifest fits within the upper mapped page boundary */
16623d5ba86SOlivier Deprez 	if (mapped_size < fdt_totalsize(pm_addr)) {
16723d5ba86SOlivier Deprez 		ERROR("SPM Core manifest too large.\n");
16823d5ba86SOlivier Deprez 		rc = -EINVAL;
16923d5ba86SOlivier Deprez 		goto exit_unmap;
17023d5ba86SOlivier Deprez 	}
17123d5ba86SOlivier Deprez 
17223d5ba86SOlivier Deprez 	VERBOSE("Reading SPM Core manifest at address %p\n", pm_addr);
17323d5ba86SOlivier Deprez 
17423d5ba86SOlivier Deprez 	rc = fdt_node_offset_by_compatible(pm_addr, -1,
175662af36dSJ-Alves 				"arm,ffa-core-manifest-1.0");
17652696946SOlivier Deprez 	if (rc < 0) {
17752696946SOlivier Deprez 		ERROR("Unrecognized SPM Core manifest\n");
17823d5ba86SOlivier Deprez 		goto exit_unmap;
1790cb64d01SAchin Gupta 	}
1800cb64d01SAchin Gupta 
18123d5ba86SOlivier Deprez 	rc = manifest_parse_root(manifest, pm_addr, rc);
18223d5ba86SOlivier Deprez 
18323d5ba86SOlivier Deprez exit_unmap:
18423d5ba86SOlivier Deprez 	unmap_ret = mmap_remove_dynamic_region(pm_base_align, PAGE_SIZE);
18523d5ba86SOlivier Deprez 	if (unmap_ret != 0) {
18623d5ba86SOlivier Deprez 		ERROR("Error while unmapping SPM Core manifest (%d).\n",
18723d5ba86SOlivier Deprez 			unmap_ret);
18823d5ba86SOlivier Deprez 		if (rc == 0) {
18923d5ba86SOlivier Deprez 			rc = unmap_ret;
19023d5ba86SOlivier Deprez 		}
19123d5ba86SOlivier Deprez 	}
19223d5ba86SOlivier Deprez 
19323d5ba86SOlivier Deprez 	return rc;
1940cb64d01SAchin Gupta }
195