xref: /rk3399_ARM-atf/plat/common/plat_spmd_manifest.c (revision cb7b9db19db5750d38762ad7a11219a57a740d17)
10cb64d01SAchin Gupta /*
20cb64d01SAchin Gupta  * Copyright (c) 2020, 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>
90cb64d01SAchin Gupta #include <string.h>
100cb64d01SAchin Gupta #include <libfdt.h>
110cb64d01SAchin Gupta 
12*cb7b9db1SVarun Wadekar #include <common/bl_common.h>
130cb64d01SAchin Gupta #include <common/debug.h>
140cb64d01SAchin Gupta #include <common/fdt_wrappers.h>
1523d5ba86SOlivier Deprez #include <lib/xlat_tables/xlat_tables_v2.h>
160cb64d01SAchin Gupta #include <platform_def.h>
170cb64d01SAchin Gupta #include <services/spm_core_manifest.h>
180cb64d01SAchin Gupta 
1952696946SOlivier Deprez #define ATTRIBUTE_ROOT_NODE_STR "attribute"
2052696946SOlivier Deprez 
210cb64d01SAchin Gupta /*******************************************************************************
2252696946SOlivier Deprez  * SPMC attribute node parser
230cb64d01SAchin Gupta  ******************************************************************************/
2452696946SOlivier Deprez static int manifest_parse_attribute(spmc_manifest_attribute_t *attr,
250cb64d01SAchin Gupta 				    const void *fdt,
260cb64d01SAchin Gupta 				    int node)
270cb64d01SAchin Gupta {
28ff4e6c35SAndre Przywara 	uint32_t val32;
2952696946SOlivier Deprez 	int rc;
300cb64d01SAchin Gupta 
3152696946SOlivier Deprez 	assert((attr != NULL) && (fdt != NULL));
320cb64d01SAchin Gupta 
33ff4e6c35SAndre Przywara 	rc = fdt_read_uint32(fdt, node, "maj_ver", &attr->major_version);
3452696946SOlivier Deprez 	if (rc != 0) {
35662af36dSJ-Alves 		ERROR("Missing FFA %s version in SPM Core manifest.\n",
3652696946SOlivier Deprez 			"major");
3752696946SOlivier Deprez 		return rc;
380cb64d01SAchin Gupta 	}
390cb64d01SAchin Gupta 
40ff4e6c35SAndre Przywara 	rc = fdt_read_uint32(fdt, node, "min_ver", &attr->minor_version);
4152696946SOlivier Deprez 	if (rc != 0) {
42662af36dSJ-Alves 		ERROR("Missing FFA %s version in SPM Core manifest.\n",
4352696946SOlivier Deprez 			"minor");
4452696946SOlivier Deprez 		return rc;
450cb64d01SAchin Gupta 	}
460cb64d01SAchin Gupta 
47ff4e6c35SAndre Przywara 	rc = fdt_read_uint32(fdt, node, "spmc_id", &val32);
4852696946SOlivier Deprez 	if (rc != 0) {
49ac03ac5eSMax Shvetsov 		ERROR("Missing SPMC ID in manifest.\n");
5052696946SOlivier Deprez 		return rc;
51ac03ac5eSMax Shvetsov 	}
5252696946SOlivier Deprez 
5352696946SOlivier Deprez 	attr->spmc_id = val32 & 0xffff;
54ac03ac5eSMax Shvetsov 
55ff4e6c35SAndre Przywara 	rc = fdt_read_uint32(fdt, node, "exec_state", &attr->exec_state);
5652696946SOlivier Deprez 	if (rc != 0) {
5752696946SOlivier Deprez 		NOTICE("%s not specified in SPM Core manifest.\n",
5852696946SOlivier Deprez 			"Execution state");
5952696946SOlivier Deprez 	}
600cb64d01SAchin Gupta 
61ff4e6c35SAndre Przywara 	rc = fdt_read_uint32(fdt, node, "binary_size", &attr->binary_size);
6252696946SOlivier Deprez 	if (rc != 0) {
6352696946SOlivier Deprez 		NOTICE("%s not specified in SPM Core manifest.\n",
6452696946SOlivier Deprez 			"Binary size");
6552696946SOlivier Deprez 	}
660cb64d01SAchin Gupta 
67ff4e6c35SAndre Przywara 	rc = fdt_read_uint64(fdt, node, "load_address", &attr->load_address);
6852696946SOlivier Deprez 	if (rc != 0) {
6952696946SOlivier Deprez 		NOTICE("%s not specified in SPM Core manifest.\n",
7052696946SOlivier Deprez 			"Load address");
7152696946SOlivier Deprez 	}
720cb64d01SAchin Gupta 
73ff4e6c35SAndre Przywara 	rc = fdt_read_uint64(fdt, node, "entrypoint", &attr->entrypoint);
7452696946SOlivier Deprez 	if (rc != 0) {
7552696946SOlivier Deprez 		NOTICE("%s not specified in SPM Core manifest.\n",
7652696946SOlivier Deprez 			"Entry point");
7752696946SOlivier Deprez 	}
780cb64d01SAchin Gupta 
7952696946SOlivier Deprez 	VERBOSE("SPM Core manifest attribute section:\n");
8052696946SOlivier Deprez 	VERBOSE("  version: %u.%u\n", attr->major_version, attr->minor_version);
8152696946SOlivier Deprez 	VERBOSE("  spmc_id: 0x%x\n", attr->spmc_id);
820cb64d01SAchin Gupta 	VERBOSE("  binary_size: 0x%x\n", attr->binary_size);
830cb64d01SAchin Gupta 	VERBOSE("  load_address: 0x%llx\n", attr->load_address);
840cb64d01SAchin Gupta 	VERBOSE("  entrypoint: 0x%llx\n", attr->entrypoint);
850cb64d01SAchin Gupta 
860cb64d01SAchin Gupta 	return 0;
870cb64d01SAchin Gupta }
880cb64d01SAchin Gupta 
890cb64d01SAchin Gupta /*******************************************************************************
900cb64d01SAchin Gupta  * Root node handler
910cb64d01SAchin Gupta  ******************************************************************************/
9252696946SOlivier Deprez static int manifest_parse_root(spmc_manifest_attribute_t *manifest,
930cb64d01SAchin Gupta 			       const void *fdt,
940cb64d01SAchin Gupta 			       int root)
950cb64d01SAchin Gupta {
960cb64d01SAchin Gupta 	int node;
970cb64d01SAchin Gupta 
9852696946SOlivier Deprez 	assert(manifest != NULL);
9952696946SOlivier Deprez 
10052696946SOlivier Deprez 	node = fdt_subnode_offset_namelen(fdt, root, ATTRIBUTE_ROOT_NODE_STR,
10152696946SOlivier Deprez 		sizeof(ATTRIBUTE_ROOT_NODE_STR) - 1);
1020cb64d01SAchin Gupta 	if (node < 0) {
10352696946SOlivier Deprez 		ERROR("Root node doesn't contain subnode '%s'\n",
10452696946SOlivier Deprez 			ATTRIBUTE_ROOT_NODE_STR);
10552696946SOlivier Deprez 		return node;
1060cb64d01SAchin Gupta 	}
1070cb64d01SAchin Gupta 
1080cb64d01SAchin Gupta 	return manifest_parse_attribute(manifest, fdt, node);
1090cb64d01SAchin Gupta }
1100cb64d01SAchin Gupta 
1110cb64d01SAchin Gupta /*******************************************************************************
11252696946SOlivier Deprez  * Platform handler to parse a SPM Core manifest.
1130cb64d01SAchin Gupta  ******************************************************************************/
11452696946SOlivier Deprez int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest,
11523d5ba86SOlivier Deprez 				const void *pm_addr)
1160cb64d01SAchin Gupta {
11723d5ba86SOlivier Deprez 	int rc, unmap_ret;
11823d5ba86SOlivier Deprez 	uintptr_t pm_base, pm_base_align;
11923d5ba86SOlivier Deprez 	size_t mapped_size;
1200cb64d01SAchin Gupta 
1210cb64d01SAchin Gupta 	assert(manifest != NULL);
12223d5ba86SOlivier Deprez 	assert(pm_addr != NULL);
1230cb64d01SAchin Gupta 
12423d5ba86SOlivier Deprez 	/*
12523d5ba86SOlivier Deprez 	 * Assume TOS_FW_CONFIG is not necessarily aligned to a page
12623d5ba86SOlivier Deprez 	 * boundary, thus calculate the remaining space between SPMC
12723d5ba86SOlivier Deprez 	 * manifest start address and upper page limit.
12823d5ba86SOlivier Deprez 	 *
12923d5ba86SOlivier Deprez 	 */
13023d5ba86SOlivier Deprez 	pm_base = (uintptr_t)pm_addr;
13123d5ba86SOlivier Deprez 	pm_base_align = page_align(pm_base, UP);
132fdd5f9e6SManish Pandey 
133fdd5f9e6SManish Pandey 	if (pm_base == pm_base_align) {
134fdd5f9e6SManish Pandey 		/* Page aligned */
135fdd5f9e6SManish Pandey 		mapped_size = PAGE_SIZE;
136fdd5f9e6SManish Pandey 	} else {
13723d5ba86SOlivier Deprez 		mapped_size = pm_base_align - pm_base;
138fdd5f9e6SManish Pandey 	}
1390cb64d01SAchin Gupta 
14023d5ba86SOlivier Deprez 	/* Check space within the page at least maps the FDT header */
14123d5ba86SOlivier Deprez 	if (mapped_size < sizeof(struct fdt_header)) {
14223d5ba86SOlivier Deprez 		ERROR("Error while mapping SPM Core manifest.\n");
14323d5ba86SOlivier Deprez 		return -EINVAL;
14423d5ba86SOlivier Deprez 	}
14523d5ba86SOlivier Deprez 
14623d5ba86SOlivier Deprez 	/* Map first SPMC manifest page in the SPMD translation regime */
14723d5ba86SOlivier Deprez 	pm_base_align = page_align(pm_base, DOWN);
14823d5ba86SOlivier Deprez 	rc = mmap_add_dynamic_region((unsigned long long)pm_base_align,
14923d5ba86SOlivier Deprez 				     pm_base_align,
15023d5ba86SOlivier Deprez 				     PAGE_SIZE,
15123d5ba86SOlivier Deprez 				     MT_RO_DATA);
1520cb64d01SAchin Gupta 	if (rc != 0) {
15323d5ba86SOlivier Deprez 		ERROR("Error while mapping SPM Core manifest (%d).\n", rc);
15452696946SOlivier Deprez 		return rc;
1550cb64d01SAchin Gupta 	}
1560cb64d01SAchin Gupta 
15723d5ba86SOlivier Deprez 	rc = fdt_check_header(pm_addr);
15823d5ba86SOlivier Deprez 	if (rc != 0) {
15923d5ba86SOlivier Deprez 		ERROR("Wrong format for SPM Core manifest (%d).\n", rc);
16023d5ba86SOlivier Deprez 		goto exit_unmap;
16123d5ba86SOlivier Deprez 	}
16223d5ba86SOlivier Deprez 
16323d5ba86SOlivier Deprez 	/* Check SPMC manifest fits within the upper mapped page boundary */
16423d5ba86SOlivier Deprez 	if (mapped_size < fdt_totalsize(pm_addr)) {
16523d5ba86SOlivier Deprez 		ERROR("SPM Core manifest too large.\n");
16623d5ba86SOlivier Deprez 		rc = -EINVAL;
16723d5ba86SOlivier Deprez 		goto exit_unmap;
16823d5ba86SOlivier Deprez 	}
16923d5ba86SOlivier Deprez 
17023d5ba86SOlivier Deprez 	VERBOSE("Reading SPM Core manifest at address %p\n", pm_addr);
17123d5ba86SOlivier Deprez 
17223d5ba86SOlivier Deprez 	rc = fdt_node_offset_by_compatible(pm_addr, -1,
173662af36dSJ-Alves 				"arm,ffa-core-manifest-1.0");
17452696946SOlivier Deprez 	if (rc < 0) {
17552696946SOlivier Deprez 		ERROR("Unrecognized SPM Core manifest\n");
17623d5ba86SOlivier Deprez 		goto exit_unmap;
1770cb64d01SAchin Gupta 	}
1780cb64d01SAchin Gupta 
17923d5ba86SOlivier Deprez 	rc = manifest_parse_root(manifest, pm_addr, rc);
18023d5ba86SOlivier Deprez 
18123d5ba86SOlivier Deprez exit_unmap:
18223d5ba86SOlivier Deprez 	unmap_ret = mmap_remove_dynamic_region(pm_base_align, PAGE_SIZE);
18323d5ba86SOlivier Deprez 	if (unmap_ret != 0) {
18423d5ba86SOlivier Deprez 		ERROR("Error while unmapping SPM Core manifest (%d).\n",
18523d5ba86SOlivier Deprez 			unmap_ret);
18623d5ba86SOlivier Deprez 		if (rc == 0) {
18723d5ba86SOlivier Deprez 			rc = unmap_ret;
18823d5ba86SOlivier Deprez 		}
18923d5ba86SOlivier Deprez 	}
19023d5ba86SOlivier Deprez 
19123d5ba86SOlivier Deprez 	return rc;
1920cb64d01SAchin Gupta }
193