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