xref: /aosp_15_r20/external/arm-trusted-firmware/plat/common/plat_spmd_manifest.c (revision 54fd6939e177f8ff529b10183254802c76df6d08)
1*54fd6939SJiyong Park /*
2*54fd6939SJiyong Park  * Copyright (c) 2020, Arm Limited. All rights reserved.
3*54fd6939SJiyong Park  *
4*54fd6939SJiyong Park  * SPDX-License-Identifier: BSD-3-Clause
5*54fd6939SJiyong Park  */
6*54fd6939SJiyong Park 
7*54fd6939SJiyong Park #include <assert.h>
8*54fd6939SJiyong Park #include <errno.h>
9*54fd6939SJiyong Park #include <inttypes.h>
10*54fd6939SJiyong Park #include <libfdt.h>
11*54fd6939SJiyong Park #include <stdint.h>
12*54fd6939SJiyong Park #include <string.h>
13*54fd6939SJiyong Park 
14*54fd6939SJiyong Park #include <common/bl_common.h>
15*54fd6939SJiyong Park #include <common/debug.h>
16*54fd6939SJiyong Park #include <common/fdt_wrappers.h>
17*54fd6939SJiyong Park #include <lib/xlat_tables/xlat_tables_v2.h>
18*54fd6939SJiyong Park #include <platform_def.h>
19*54fd6939SJiyong Park #include <services/spm_core_manifest.h>
20*54fd6939SJiyong Park 
21*54fd6939SJiyong Park #define ATTRIBUTE_ROOT_NODE_STR "attribute"
22*54fd6939SJiyong Park 
23*54fd6939SJiyong Park /*******************************************************************************
24*54fd6939SJiyong Park  * SPMC attribute node parser
25*54fd6939SJiyong Park  ******************************************************************************/
manifest_parse_attribute(spmc_manifest_attribute_t * attr,const void * fdt,int node)26*54fd6939SJiyong Park static int manifest_parse_attribute(spmc_manifest_attribute_t *attr,
27*54fd6939SJiyong Park 				    const void *fdt,
28*54fd6939SJiyong Park 				    int node)
29*54fd6939SJiyong Park {
30*54fd6939SJiyong Park 	uint32_t val32;
31*54fd6939SJiyong Park 	int rc;
32*54fd6939SJiyong Park 
33*54fd6939SJiyong Park 	assert((attr != NULL) && (fdt != NULL));
34*54fd6939SJiyong Park 
35*54fd6939SJiyong Park 	rc = fdt_read_uint32(fdt, node, "maj_ver", &attr->major_version);
36*54fd6939SJiyong Park 	if (rc != 0) {
37*54fd6939SJiyong Park 		ERROR("Missing FFA %s version in SPM Core manifest.\n",
38*54fd6939SJiyong Park 			"major");
39*54fd6939SJiyong Park 		return rc;
40*54fd6939SJiyong Park 	}
41*54fd6939SJiyong Park 
42*54fd6939SJiyong Park 	rc = fdt_read_uint32(fdt, node, "min_ver", &attr->minor_version);
43*54fd6939SJiyong Park 	if (rc != 0) {
44*54fd6939SJiyong Park 		ERROR("Missing FFA %s version in SPM Core manifest.\n",
45*54fd6939SJiyong Park 			"minor");
46*54fd6939SJiyong Park 		return rc;
47*54fd6939SJiyong Park 	}
48*54fd6939SJiyong Park 
49*54fd6939SJiyong Park 	rc = fdt_read_uint32(fdt, node, "spmc_id", &val32);
50*54fd6939SJiyong Park 	if (rc != 0) {
51*54fd6939SJiyong Park 		ERROR("Missing SPMC ID in manifest.\n");
52*54fd6939SJiyong Park 		return rc;
53*54fd6939SJiyong Park 	}
54*54fd6939SJiyong Park 
55*54fd6939SJiyong Park 	attr->spmc_id = val32 & 0xffff;
56*54fd6939SJiyong Park 
57*54fd6939SJiyong Park 	rc = fdt_read_uint32(fdt, node, "exec_state", &attr->exec_state);
58*54fd6939SJiyong Park 	if (rc != 0) {
59*54fd6939SJiyong Park 		NOTICE("%s not specified in SPM Core manifest.\n",
60*54fd6939SJiyong Park 			"Execution state");
61*54fd6939SJiyong Park 	}
62*54fd6939SJiyong Park 
63*54fd6939SJiyong Park 	rc = fdt_read_uint32(fdt, node, "binary_size", &attr->binary_size);
64*54fd6939SJiyong Park 	if (rc != 0) {
65*54fd6939SJiyong Park 		NOTICE("%s not specified in SPM Core manifest.\n",
66*54fd6939SJiyong Park 			"Binary size");
67*54fd6939SJiyong Park 	}
68*54fd6939SJiyong Park 
69*54fd6939SJiyong Park 	rc = fdt_read_uint64(fdt, node, "load_address", &attr->load_address);
70*54fd6939SJiyong Park 	if (rc != 0) {
71*54fd6939SJiyong Park 		NOTICE("%s not specified in SPM Core manifest.\n",
72*54fd6939SJiyong Park 			"Load address");
73*54fd6939SJiyong Park 	}
74*54fd6939SJiyong Park 
75*54fd6939SJiyong Park 	rc = fdt_read_uint64(fdt, node, "entrypoint", &attr->entrypoint);
76*54fd6939SJiyong Park 	if (rc != 0) {
77*54fd6939SJiyong Park 		NOTICE("%s not specified in SPM Core manifest.\n",
78*54fd6939SJiyong Park 			"Entry point");
79*54fd6939SJiyong Park 	}
80*54fd6939SJiyong Park 
81*54fd6939SJiyong Park 	VERBOSE("SPM Core manifest attribute section:\n");
82*54fd6939SJiyong Park 	VERBOSE("  version: %u.%u\n", attr->major_version, attr->minor_version);
83*54fd6939SJiyong Park 	VERBOSE("  spmc_id: 0x%x\n", attr->spmc_id);
84*54fd6939SJiyong Park 	VERBOSE("  binary_size: 0x%x\n", attr->binary_size);
85*54fd6939SJiyong Park 	VERBOSE("  load_address: 0x%" PRIx64 "\n", attr->load_address);
86*54fd6939SJiyong Park 	VERBOSE("  entrypoint: 0x%" PRIx64 "\n", attr->entrypoint);
87*54fd6939SJiyong Park 
88*54fd6939SJiyong Park 	return 0;
89*54fd6939SJiyong Park }
90*54fd6939SJiyong Park 
91*54fd6939SJiyong Park /*******************************************************************************
92*54fd6939SJiyong Park  * Root node handler
93*54fd6939SJiyong Park  ******************************************************************************/
manifest_parse_root(spmc_manifest_attribute_t * manifest,const void * fdt,int root)94*54fd6939SJiyong Park static int manifest_parse_root(spmc_manifest_attribute_t *manifest,
95*54fd6939SJiyong Park 			       const void *fdt,
96*54fd6939SJiyong Park 			       int root)
97*54fd6939SJiyong Park {
98*54fd6939SJiyong Park 	int node;
99*54fd6939SJiyong Park 
100*54fd6939SJiyong Park 	assert(manifest != NULL);
101*54fd6939SJiyong Park 
102*54fd6939SJiyong Park 	node = fdt_subnode_offset_namelen(fdt, root, ATTRIBUTE_ROOT_NODE_STR,
103*54fd6939SJiyong Park 		sizeof(ATTRIBUTE_ROOT_NODE_STR) - 1);
104*54fd6939SJiyong Park 	if (node < 0) {
105*54fd6939SJiyong Park 		ERROR("Root node doesn't contain subnode '%s'\n",
106*54fd6939SJiyong Park 			ATTRIBUTE_ROOT_NODE_STR);
107*54fd6939SJiyong Park 		return node;
108*54fd6939SJiyong Park 	}
109*54fd6939SJiyong Park 
110*54fd6939SJiyong Park 	return manifest_parse_attribute(manifest, fdt, node);
111*54fd6939SJiyong Park }
112*54fd6939SJiyong Park 
113*54fd6939SJiyong Park /*******************************************************************************
114*54fd6939SJiyong Park  * Platform handler to parse a SPM Core manifest.
115*54fd6939SJiyong Park  ******************************************************************************/
plat_spm_core_manifest_load(spmc_manifest_attribute_t * manifest,const void * pm_addr)116*54fd6939SJiyong Park int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest,
117*54fd6939SJiyong Park 				const void *pm_addr)
118*54fd6939SJiyong Park {
119*54fd6939SJiyong Park 	int rc, unmap_ret;
120*54fd6939SJiyong Park 	uintptr_t pm_base, pm_base_align;
121*54fd6939SJiyong Park 	size_t mapped_size;
122*54fd6939SJiyong Park 
123*54fd6939SJiyong Park 	assert(manifest != NULL);
124*54fd6939SJiyong Park 	assert(pm_addr != NULL);
125*54fd6939SJiyong Park 
126*54fd6939SJiyong Park 	/*
127*54fd6939SJiyong Park 	 * Assume TOS_FW_CONFIG is not necessarily aligned to a page
128*54fd6939SJiyong Park 	 * boundary, thus calculate the remaining space between SPMC
129*54fd6939SJiyong Park 	 * manifest start address and upper page limit.
130*54fd6939SJiyong Park 	 *
131*54fd6939SJiyong Park 	 */
132*54fd6939SJiyong Park 	pm_base = (uintptr_t)pm_addr;
133*54fd6939SJiyong Park 	pm_base_align = page_align(pm_base, UP);
134*54fd6939SJiyong Park 
135*54fd6939SJiyong Park 	if (pm_base == pm_base_align) {
136*54fd6939SJiyong Park 		/* Page aligned */
137*54fd6939SJiyong Park 		mapped_size = PAGE_SIZE;
138*54fd6939SJiyong Park 	} else {
139*54fd6939SJiyong Park 		mapped_size = pm_base_align - pm_base;
140*54fd6939SJiyong Park 	}
141*54fd6939SJiyong Park 
142*54fd6939SJiyong Park 	/* Check space within the page at least maps the FDT header */
143*54fd6939SJiyong Park 	if (mapped_size < sizeof(struct fdt_header)) {
144*54fd6939SJiyong Park 		ERROR("Error while mapping SPM Core manifest.\n");
145*54fd6939SJiyong Park 		return -EINVAL;
146*54fd6939SJiyong Park 	}
147*54fd6939SJiyong Park 
148*54fd6939SJiyong Park 	/* Map first SPMC manifest page in the SPMD translation regime */
149*54fd6939SJiyong Park 	pm_base_align = page_align(pm_base, DOWN);
150*54fd6939SJiyong Park 	rc = mmap_add_dynamic_region((unsigned long long)pm_base_align,
151*54fd6939SJiyong Park 				     pm_base_align,
152*54fd6939SJiyong Park 				     PAGE_SIZE,
153*54fd6939SJiyong Park 				     MT_RO_DATA);
154*54fd6939SJiyong Park 	if (rc != 0) {
155*54fd6939SJiyong Park 		ERROR("Error while mapping SPM Core manifest (%d).\n", rc);
156*54fd6939SJiyong Park 		return rc;
157*54fd6939SJiyong Park 	}
158*54fd6939SJiyong Park 
159*54fd6939SJiyong Park 	rc = fdt_check_header(pm_addr);
160*54fd6939SJiyong Park 	if (rc != 0) {
161*54fd6939SJiyong Park 		ERROR("Wrong format for SPM Core manifest (%d).\n", rc);
162*54fd6939SJiyong Park 		goto exit_unmap;
163*54fd6939SJiyong Park 	}
164*54fd6939SJiyong Park 
165*54fd6939SJiyong Park 	/* Check SPMC manifest fits within the upper mapped page boundary */
166*54fd6939SJiyong Park 	if (mapped_size < fdt_totalsize(pm_addr)) {
167*54fd6939SJiyong Park 		ERROR("SPM Core manifest too large.\n");
168*54fd6939SJiyong Park 		rc = -EINVAL;
169*54fd6939SJiyong Park 		goto exit_unmap;
170*54fd6939SJiyong Park 	}
171*54fd6939SJiyong Park 
172*54fd6939SJiyong Park 	VERBOSE("Reading SPM Core manifest at address %p\n", pm_addr);
173*54fd6939SJiyong Park 
174*54fd6939SJiyong Park 	rc = fdt_node_offset_by_compatible(pm_addr, -1,
175*54fd6939SJiyong Park 				"arm,ffa-core-manifest-1.0");
176*54fd6939SJiyong Park 	if (rc < 0) {
177*54fd6939SJiyong Park 		ERROR("Unrecognized SPM Core manifest\n");
178*54fd6939SJiyong Park 		goto exit_unmap;
179*54fd6939SJiyong Park 	}
180*54fd6939SJiyong Park 
181*54fd6939SJiyong Park 	rc = manifest_parse_root(manifest, pm_addr, rc);
182*54fd6939SJiyong Park 
183*54fd6939SJiyong Park exit_unmap:
184*54fd6939SJiyong Park 	unmap_ret = mmap_remove_dynamic_region(pm_base_align, PAGE_SIZE);
185*54fd6939SJiyong Park 	if (unmap_ret != 0) {
186*54fd6939SJiyong Park 		ERROR("Error while unmapping SPM Core manifest (%d).\n",
187*54fd6939SJiyong Park 			unmap_ret);
188*54fd6939SJiyong Park 		if (rc == 0) {
189*54fd6939SJiyong Park 			rc = unmap_ret;
190*54fd6939SJiyong Park 		}
191*54fd6939SJiyong Park 	}
192*54fd6939SJiyong Park 
193*54fd6939SJiyong Park 	return rc;
194*54fd6939SJiyong Park }
195