1 /*
2  * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 
8 #include <common/debug.h>
9 #include <plat/common/platform.h>
10 #include <services/rmm_core_manifest.h>
11 #include <services/rmmd_svc.h>
12 #include <services/trp/platform_trp.h>
13 #include <trp_helpers.h>
14 #include "trp_private.h"
15 
16 #include <platform_def.h>
17 
18 /* Parameters received from the previous image */
19 static unsigned int trp_boot_abi_version;
20 static uintptr_t trp_shared_region_start;
21 
22 /* Parameters received from boot manifest */
23 uint32_t trp_boot_manifest_version;
24 
25 /*******************************************************************************
26  * Setup function for TRP.
27  ******************************************************************************/
trp_setup(uint64_t x0,uint64_t x1,uint64_t x2,uint64_t x3)28 void trp_setup(uint64_t x0,
29 	       uint64_t x1,
30 	       uint64_t x2,
31 	       uint64_t x3)
32 {
33 	/*
34 	 * Validate boot parameters.
35 	 *
36 	 * According to the Boot Interface ABI v.0.1, the
37 	 * parameters recived from EL3 are:
38 	 * x0: CPUID (verified earlier so not used)
39 	 * x1: Boot Interface version
40 	 * x2: PLATFORM_CORE_COUNT
41 	 * x3: Pointer to the shared memory area.
42 	 */
43 
44 	(void)x0;
45 
46 	if (TRP_RMM_EL3_VERSION_GET_MAJOR(x1) != TRP_RMM_EL3_ABI_VERS_MAJOR) {
47 		trp_boot_abort(E_RMM_BOOT_VERSION_MISMATCH);
48 	}
49 
50 	if ((void *)x3 == NULL) {
51 		trp_boot_abort(E_RMM_BOOT_INVALID_SHARED_BUFFER);
52 	}
53 
54 	if (x2 > TRP_PLATFORM_CORE_COUNT) {
55 		trp_boot_abort(E_RMM_BOOT_CPUS_OUT_OF_RANGE);
56 	}
57 
58 	trp_boot_abi_version = x1;
59 	trp_shared_region_start = x3;
60 	flush_dcache_range((uintptr_t)&trp_boot_abi_version,
61 			   sizeof(trp_boot_abi_version));
62 	flush_dcache_range((uintptr_t)&trp_shared_region_start,
63 			   sizeof(trp_shared_region_start));
64 
65 	/* Perform early platform-specific setup */
66 	trp_early_platform_setup((rmm_manifest_t *)trp_shared_region_start);
67 }
68 
69 /* Main function for TRP */
trp_main(void)70 void trp_main(void)
71 {
72 	NOTICE("TRP: %s\n", version_string);
73 	NOTICE("TRP: %s\n", build_message);
74 	NOTICE("TRP: Supported RMM-EL3 Interface ABI: v.%u.%u\n",
75 		TRP_RMM_EL3_ABI_VERS_MAJOR, TRP_RMM_EL3_ABI_VERS_MINOR);
76 	NOTICE("TRP: Boot Manifest Version : v.%u.%u\n",
77 		RMMD_GET_MANIFEST_VERSION_MAJOR(trp_boot_manifest_version),
78 		RMMD_GET_MANIFEST_VERSION_MINOR(trp_boot_manifest_version));
79 	INFO("TRP: Memory base : 0x%lx\n", (unsigned long)RMM_BASE);
80 	INFO("TRP: Base address for the shared region : 0x%lx\n",
81 			(unsigned long)trp_shared_region_start);
82 	INFO("TRP: Total size : 0x%lx bytes\n", (unsigned long)(RMM_END
83 								- RMM_BASE));
84 	INFO("TRP: RMM-EL3 Interface ABI reported by EL3: v.%u.%u\n",
85 		TRP_RMM_EL3_VERSION_GET_MAJOR(trp_boot_abi_version),
86 		TRP_RMM_EL3_VERSION_GET_MINOR(trp_boot_abi_version));
87 }
88 
89 /*******************************************************************************
90  * Returning RMI version back to Normal World
91  ******************************************************************************/
trp_ret_rmi_version(void)92 static trp_args_t *trp_ret_rmi_version(void)
93 {
94 	VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR,
95 					  RMI_ABI_VERSION_MINOR);
96 	return set_smc_args(RMM_RMI_REQ_COMPLETE, RMI_ABI_VERSION,
97 			    0, 0, 0, 0, 0, 0);
98 }
99 
100 /*******************************************************************************
101  * Transitioning granule of NON-SECURE type to REALM type
102  ******************************************************************************/
trp_asc_mark_realm(unsigned long long x1)103 static trp_args_t *trp_asc_mark_realm(unsigned long long x1)
104 {
105 	unsigned long long ret;
106 
107 	VERBOSE("Delegating granule 0x%llx\n", x1);
108 	ret = trp_smc(set_smc_args(RMM_GTSI_DELEGATE, x1, 0, 0, 0, 0, 0, 0));
109 
110 	if (ret != 0ULL) {
111 		ERROR("Granule transition from NON-SECURE type to REALM type "
112 			"failed 0x%llx\n", ret);
113 	}
114 	return set_smc_args(RMM_RMI_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0);
115 }
116 
117 /*******************************************************************************
118  * Transitioning granule of REALM type to NON-SECURE type
119  ******************************************************************************/
trp_asc_mark_nonsecure(unsigned long long x1)120 static trp_args_t *trp_asc_mark_nonsecure(unsigned long long x1)
121 {
122 	unsigned long long ret;
123 
124 	VERBOSE("Undelegating granule 0x%llx\n", x1);
125 	ret = trp_smc(set_smc_args(RMM_GTSI_UNDELEGATE, x1, 0, 0, 0, 0, 0, 0));
126 
127 	if (ret != 0ULL) {
128 		ERROR("Granule transition from REALM type to NON-SECURE type "
129 			"failed 0x%llx\n", ret);
130 	}
131 	return set_smc_args(RMM_RMI_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0);
132 }
133 
134 /*******************************************************************************
135  * Main RMI SMC handler function
136  ******************************************************************************/
trp_rmi_handler(unsigned long fid,unsigned long long x1)137 trp_args_t *trp_rmi_handler(unsigned long fid, unsigned long long x1)
138 {
139 	switch (fid) {
140 	case RMI_RMM_REQ_VERSION:
141 		return trp_ret_rmi_version();
142 	case RMI_RMM_GRANULE_DELEGATE:
143 		return trp_asc_mark_realm(x1);
144 	case RMI_RMM_GRANULE_UNDELEGATE:
145 		return trp_asc_mark_nonsecure(x1);
146 	default:
147 		ERROR("Invalid SMC code to %s, FID %lu\n", __func__, fid);
148 	}
149 	return set_smc_args(SMC_UNK, 0, 0, 0, 0, 0, 0, 0);
150 }
151