xref: /rk3399_ARM-atf/plat/common/plat_spmd_manifest.c (revision 773a310fce2954c630cf645c33c099ec0de70c29)
10cb64d01SAchin Gupta /*
28c829a92SManish 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  ******************************************************************************/
manifest_parse_attribute(spmc_manifest_attribute_t * attr,const void * fdt,int node)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  ******************************************************************************/
manifest_parse_root(spmc_manifest_attribute_t * manifest,const void * fdt,int root)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  ******************************************************************************/
plat_spm_core_manifest_load(spmc_manifest_attribute_t * manifest,const void * pm_addr)11652696946SOlivier Deprez int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest,
11723d5ba86SOlivier Deprez 				const void *pm_addr)
1180cb64d01SAchin Gupta {
119*55fd56d7SYeoreum Yun #if TRANSFER_LIST && !RESET_TO_BL31
120*55fd56d7SYeoreum Yun 	int rc;
121*55fd56d7SYeoreum Yun 
122*55fd56d7SYeoreum Yun 	assert(manifest != NULL);
123*55fd56d7SYeoreum Yun 	assert(pm_addr != NULL);
124*55fd56d7SYeoreum Yun 
125*55fd56d7SYeoreum Yun 	/*
126*55fd56d7SYeoreum Yun 	 * NOTE:
127*55fd56d7SYeoreum Yun 	 *   If spmc_manifest is delivered via TRANSFER_LIST,
128*55fd56d7SYeoreum Yun 	 *   the spmc_manifest address is already mapped.
129*55fd56d7SYeoreum Yun 	 *   So, @pm_addr can be accessed directly.
130*55fd56d7SYeoreum Yun 	 */
131*55fd56d7SYeoreum Yun 
132*55fd56d7SYeoreum Yun 	rc = fdt_check_header(pm_addr);
133*55fd56d7SYeoreum Yun 	if (rc != 0) {
134*55fd56d7SYeoreum Yun 		ERROR("Wrong format for SPM Core manifest (%d).\n", rc);
135*55fd56d7SYeoreum Yun 		return rc;
136*55fd56d7SYeoreum Yun 	}
137*55fd56d7SYeoreum Yun 
138*55fd56d7SYeoreum Yun 	VERBOSE("Reading SPM Core manifest at address %p\n", pm_addr);
139*55fd56d7SYeoreum Yun 
140*55fd56d7SYeoreum Yun 	rc = fdt_node_offset_by_compatible(pm_addr, -1,
141*55fd56d7SYeoreum Yun 				"arm,ffa-core-manifest-1.0");
142*55fd56d7SYeoreum Yun 	if (rc < 0) {
143*55fd56d7SYeoreum Yun 		ERROR("Unrecognized SPM Core manifest\n");
144*55fd56d7SYeoreum Yun 		return rc;
145*55fd56d7SYeoreum Yun 	}
146*55fd56d7SYeoreum Yun 
147*55fd56d7SYeoreum Yun 	rc = manifest_parse_root(manifest, pm_addr, rc);
148*55fd56d7SYeoreum Yun 
149*55fd56d7SYeoreum Yun 	return rc;
150*55fd56d7SYeoreum Yun #else
15123d5ba86SOlivier Deprez 	int rc, unmap_ret;
15223d5ba86SOlivier Deprez 	uintptr_t pm_base, pm_base_align;
15323d5ba86SOlivier Deprez 	size_t mapped_size;
1540cb64d01SAchin Gupta 
1550cb64d01SAchin Gupta 	assert(manifest != NULL);
15623d5ba86SOlivier Deprez 	assert(pm_addr != NULL);
1570cb64d01SAchin Gupta 
15823d5ba86SOlivier Deprez 	/*
15923d5ba86SOlivier Deprez 	 * Assume TOS_FW_CONFIG is not necessarily aligned to a page
16023d5ba86SOlivier Deprez 	 * boundary, thus calculate the remaining space between SPMC
16123d5ba86SOlivier Deprez 	 * manifest start address and upper page limit.
16223d5ba86SOlivier Deprez 	 *
16323d5ba86SOlivier Deprez 	 */
16423d5ba86SOlivier Deprez 	pm_base = (uintptr_t)pm_addr;
16523d5ba86SOlivier Deprez 	pm_base_align = page_align(pm_base, UP);
166fdd5f9e6SManish Pandey 
167fdd5f9e6SManish Pandey 	if (pm_base == pm_base_align) {
168fdd5f9e6SManish Pandey 		/* Page aligned */
169fdd5f9e6SManish Pandey 		mapped_size = PAGE_SIZE;
170fdd5f9e6SManish Pandey 	} else {
17123d5ba86SOlivier Deprez 		mapped_size = pm_base_align - pm_base;
172fdd5f9e6SManish Pandey 	}
1730cb64d01SAchin Gupta 
17423d5ba86SOlivier Deprez 	/* Check space within the page at least maps the FDT header */
17523d5ba86SOlivier Deprez 	if (mapped_size < sizeof(struct fdt_header)) {
17623d5ba86SOlivier Deprez 		ERROR("Error while mapping SPM Core manifest.\n");
17723d5ba86SOlivier Deprez 		return -EINVAL;
17823d5ba86SOlivier Deprez 	}
17923d5ba86SOlivier Deprez 
18023d5ba86SOlivier Deprez 	/* Map first SPMC manifest page in the SPMD translation regime */
18123d5ba86SOlivier Deprez 	pm_base_align = page_align(pm_base, DOWN);
18223d5ba86SOlivier Deprez 	rc = mmap_add_dynamic_region((unsigned long long)pm_base_align,
18323d5ba86SOlivier Deprez 				     pm_base_align,
18423d5ba86SOlivier Deprez 				     PAGE_SIZE,
1858c829a92SManish V Badarkhe 				     MT_RO_DATA | EL3_PAS);
1860cb64d01SAchin Gupta 	if (rc != 0) {
18723d5ba86SOlivier Deprez 		ERROR("Error while mapping SPM Core manifest (%d).\n", rc);
18852696946SOlivier Deprez 		return rc;
1890cb64d01SAchin Gupta 	}
1900cb64d01SAchin Gupta 
19123d5ba86SOlivier Deprez 	rc = fdt_check_header(pm_addr);
19223d5ba86SOlivier Deprez 	if (rc != 0) {
19323d5ba86SOlivier Deprez 		ERROR("Wrong format for SPM Core manifest (%d).\n", rc);
19423d5ba86SOlivier Deprez 		goto exit_unmap;
19523d5ba86SOlivier Deprez 	}
19623d5ba86SOlivier Deprez 
19723d5ba86SOlivier Deprez 	/* Check SPMC manifest fits within the upper mapped page boundary */
19823d5ba86SOlivier Deprez 	if (mapped_size < fdt_totalsize(pm_addr)) {
19923d5ba86SOlivier Deprez 		ERROR("SPM Core manifest too large.\n");
20023d5ba86SOlivier Deprez 		rc = -EINVAL;
20123d5ba86SOlivier Deprez 		goto exit_unmap;
20223d5ba86SOlivier Deprez 	}
20323d5ba86SOlivier Deprez 
20423d5ba86SOlivier Deprez 	VERBOSE("Reading SPM Core manifest at address %p\n", pm_addr);
20523d5ba86SOlivier Deprez 
20623d5ba86SOlivier Deprez 	rc = fdt_node_offset_by_compatible(pm_addr, -1,
207662af36dSJ-Alves 				"arm,ffa-core-manifest-1.0");
20852696946SOlivier Deprez 	if (rc < 0) {
20952696946SOlivier Deprez 		ERROR("Unrecognized SPM Core manifest\n");
21023d5ba86SOlivier Deprez 		goto exit_unmap;
2110cb64d01SAchin Gupta 	}
2120cb64d01SAchin Gupta 
21323d5ba86SOlivier Deprez 	rc = manifest_parse_root(manifest, pm_addr, rc);
21423d5ba86SOlivier Deprez 
21523d5ba86SOlivier Deprez exit_unmap:
21623d5ba86SOlivier Deprez 	unmap_ret = mmap_remove_dynamic_region(pm_base_align, PAGE_SIZE);
21723d5ba86SOlivier Deprez 	if (unmap_ret != 0) {
21823d5ba86SOlivier Deprez 		ERROR("Error while unmapping SPM Core manifest (%d).\n",
21923d5ba86SOlivier Deprez 			unmap_ret);
22023d5ba86SOlivier Deprez 		if (rc == 0) {
22123d5ba86SOlivier Deprez 			rc = unmap_ret;
22223d5ba86SOlivier Deprez 		}
22323d5ba86SOlivier Deprez 	}
22423d5ba86SOlivier Deprez 
22523d5ba86SOlivier Deprez 	return rc;
226*55fd56d7SYeoreum Yun #endif
2270cb64d01SAchin Gupta }
228