1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4  */
5 
6 #include <assert.h>
7 #include <debug.h>
8 #include <rmm_el3_ifc.h>
9 #include <sizes.h>
10 #include <smc.h>
11 #include <spinlock.h>
12 #include <stdbool.h>
13 #include <stddef.h>
14 #include <stdint.h>
15 #include <xlat_defs.h>
16 
17 /* Platform parameter */
18 extern uintptr_t rmm_shared_buffer_start_va;
19 
20 /* Spinlock used to protect the EL3<->RMM shared area */
21 static spinlock_t shared_area_lock = {0U};
22 
23 /*
24  * Get and lock a pointer to the start of the RMM<->EL3 shared buffer.
25  */
rmm_el3_ifc_get_shared_buf_locked(void)26 uintptr_t rmm_el3_ifc_get_shared_buf_locked(void)
27 {
28 	spinlock_acquire(&shared_area_lock);
29 
30 	return rmm_shared_buffer_start_va;
31 }
32 
33 /*
34  * Release the RMM <-> EL3 buffer.
35  */
rmm_el3_ifc_release_shared_buf(void)36 void rmm_el3_ifc_release_shared_buf(void)
37 {
38 	spinlock_release(&shared_area_lock);
39 }
40 
41 /*
42  * Get the realm attestation key to sign the realm attestation token. It is
43  * expected that only the private key is retrieved in raw format.
44  */
rmm_el3_ifc_get_realm_attest_key(uintptr_t buf,size_t buflen,size_t * len,unsigned int crv)45 int rmm_el3_ifc_get_realm_attest_key(uintptr_t buf, size_t buflen,
46 				     size_t *len, unsigned int crv)
47 {
48 	struct smc_result smc_res;
49 	unsigned long buffer_pa;
50 	unsigned long offset =
51 		(unsigned long)(buf - rmm_shared_buffer_start_va);
52 
53 	assert((offset + buflen) <= rmm_el3_ifc_get_shared_buf_size());
54 	assert((buf & ~PAGE_SIZE_MASK) == rmm_shared_buffer_start_va);
55 
56 	buffer_pa = (unsigned long)rmm_el3_ifc_get_shared_buf_pa() + offset;
57 
58 	monitor_call_with_res(SMC_RMM_GET_REALM_ATTEST_KEY,
59 			      buffer_pa,
60 			      buflen,
61 			      crv, 0UL, 0UL, 0UL, &smc_res);
62 
63 	if (smc_res.x[0] != 0UL) {
64 		ERROR("Failed to get realm attestation key x0 = 0x%lx\n",
65 				smc_res.x[0]);
66 	}
67 
68 	*len = smc_res.x[1];
69 
70 	return smc_res.x[0];
71 }
72 
73 /*
74  * Get the platform token from the EL3 firmware.
75  * The caller must have already populated the public hash in `buf` which is an
76  * input for platform token computation.
77  */
rmm_el3_ifc_get_platform_token(uintptr_t buf,size_t buflen,size_t * len,size_t hash_size)78 int rmm_el3_ifc_get_platform_token(uintptr_t buf, size_t buflen,
79 				   size_t *len, size_t hash_size)
80 {
81 	struct smc_result smc_res;
82 	unsigned long buffer_pa;
83 	unsigned long offset =
84 		(unsigned long)(buf - rmm_shared_buffer_start_va);
85 
86 	assert((offset + buflen) <= rmm_el3_ifc_get_shared_buf_size());
87 	assert((buf & ~PAGE_SIZE_MASK) == rmm_shared_buffer_start_va);
88 
89 	buffer_pa = (unsigned long)rmm_el3_ifc_get_shared_buf_pa() + offset;
90 	/* Get the available space on the buffer after the offset */
91 
92 	monitor_call_with_res(SMC_RMM_GET_PLAT_TOKEN,
93 			      buffer_pa,
94 			      buflen,
95 			      hash_size,
96 			      0UL, 0UL, 0UL, &smc_res);
97 
98 	if (smc_res.x[0] != 0UL) {
99 		ERROR("Failed to get platform token x0 = 0x%lx\n",
100 				smc_res.x[0]);
101 		return smc_res.x[0];
102 	}
103 
104 	*len = smc_res.x[1];
105 
106 	return smc_res.x[0];
107 }
108