1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4  */
5 
6 #include <arch_helpers.h>
7 #include <assert.h>
8 #include <debug.h>
9 #include <rmm_el3_ifc.h>
10 #include <rmm_el3_ifc_priv.h>
11 #include <smc.h>
12 #include <stdint.h>
13 #include <xlat_defs.h>
14 
15 /* Boot Interface arguments */
16 static uintptr_t rmm_shared_buffer_start_pa;
17 static unsigned long rmm_el3_ifc_abi_version;
18 
19 /* Platform parameters */
20 uintptr_t rmm_shared_buffer_start_va;
21 
22 /* Internal status */
23 static bool initialized;
24 
25 /*
26  * Abort the boot process and return to EL3 FW reporting
27  * the ec error code.
28  */
rmm_el3_ifc_report_fail_to_el3(int ec)29 __dead2 void rmm_el3_ifc_report_fail_to_el3(int ec)
30 {
31 	(void)monitor_call(SMC_RMM_BOOT_COMPLETE, (unsigned long)ec,
32 			   0UL, 0UL, 0UL, 0UL, 0UL);
33 	/* EL3 should never return back here */
34 	panic();
35 }
36 
37 /*
38  * Validate the boot arguments and initialize the rmm_el3_ifc library.
39  * This function must be called only once during cold boot.
40  *
41  * This function must be called prior to enable the MMU and data cache.
42  */
rmm_el3_ifc_init(unsigned long x0,unsigned long x1,unsigned long x2,unsigned long x3,uintptr_t shared_buf_va)43 int rmm_el3_ifc_init(unsigned long x0, unsigned long x1, unsigned long x2,
44 		     unsigned long x3, uintptr_t shared_buf_va)
45 {
46 	assert(is_mmu_enabled() == false);
47 	assert((shared_buf_va & PAGE_SIZE_MASK) == 0UL);
48 	assert(shared_buf_va != 0UL);
49 
50 	if (initialized == true) {
51 		return 0;
52 	}
53 
54 	/*
55 	 * Validate that the version number is correct.
56 	 *
57 	 * x1: RMM-EL3 Interface version.
58 	 */
59 	if (!IS_RMM_EL3_IFC_COMPATIBLE(x1)) {
60 		rmm_el3_ifc_report_fail_to_el3(E_RMM_BOOT_VERSION_NOT_VALID);
61 	}
62 
63 	/*
64 	 * Validate the number of CPUs received from EL3.
65 	 *
66 	 * x2: Number of CPUs in the system as reported by EL3.
67 	 */
68 	if (x2 > MAX_CPUS) {
69 		rmm_el3_ifc_report_fail_to_el3(E_RMM_BOOT_CPUS_OUT_OF_RANGE);
70 	}
71 
72 	/*
73 	 * Validate that the CPU Id is in the range of the maximum
74 	 * number of CPUs.
75 	 *
76 	 * x0: CPU Id.
77 	 * x2: Number of CPUs in the system as reported by EL3.
78 	 */
79 	if (x0 >= x2) {
80 		rmm_el3_ifc_report_fail_to_el3(E_RMM_BOOT_CPU_ID_OUT_OF_RANGE);
81 	}
82 
83 	/*
84 	 * Validate that the shared buffer pointer is not NULL.
85 	 *
86 	 * x3: Pointer to the start of the EL3-RMM shared buffer.
87 	 */
88 	if ((x3 == 0UL) || ((x3 & PAGE_SIZE_MASK) != 0UL)) {
89 		rmm_el3_ifc_report_fail_to_el3(E_RMM_BOOT_INVALID_SHARED_BUFFER);
90 	}
91 
92 	rmm_el3_ifc_abi_version = x1;
93 	rmm_shared_buffer_start_pa = (uintptr_t)x3;
94 	rmm_shared_buffer_start_va = shared_buf_va;
95 
96 	initialized = true;
97 
98 	inv_dcache_range((uintptr_t)&rmm_shared_buffer_start_pa,
99 				sizeof(rmm_shared_buffer_start_pa));
100 	inv_dcache_range((uintptr_t)&rmm_el3_ifc_abi_version,
101 				sizeof(rmm_el3_ifc_abi_version));
102 	inv_dcache_range((uintptr_t)&rmm_shared_buffer_start_va,
103 				sizeof(rmm_shared_buffer_start_va));
104 	inv_dcache_range((uintptr_t)&initialized, sizeof(bool));
105 
106 	/* Process the Boot Manifest */
107 	rmm_el3_ifc_process_boot_manifest();
108 
109 	return 0;
110 }
111 
112 /*
113  * Get a pointer to the Physical Address of the
114  * start of the RMM<->EL3 shared area.
115  */
rmm_el3_ifc_get_shared_buf_pa(void)116 uintptr_t rmm_el3_ifc_get_shared_buf_pa(void)
117 {
118 	assert(initialized == true);
119 
120 	return rmm_shared_buffer_start_pa;
121 }
122 
123 /* Get the raw value of the boot interface version */
rmm_el3_ifc_get_version(void)124 unsigned int rmm_el3_ifc_get_version(void)
125 {
126 	assert(initialized == true);
127 
128 	return (unsigned int)rmm_el3_ifc_abi_version;
129 }
130