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