1 /*
2  *  SPDX-License-Identifier: BSD-3-Clause
3  *  SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
4  *
5  */
6 
7 
8 #include <stdint.h>
9 #include <stdbool.h>
10 
11 #include "psa/client.h"
12 #include "tfm_ns_interface.h"
13 #include "tfm_psa_call_pack.h"
14 #include "tfm_mailbox.h"
15 #include "tfm_ns_mailbox.h"
16 
17 #include "hardware/structs/sio.h"
18 
19 /*
20  * TODO
21  * Currently, force all the non-secure client to share the same ID.
22  *
23  * It requires a more clear mechanism to synchronize the non-secure client
24  * ID with SPE in dual core scenario.
25  * In current design, the value is transferred to SPE via mailbox message.
26  * A dedicated routine to receive the non-secure client information in
27  * TF-M core/SPM in dual core scenario should be added besides current
28  * implementation for single Armv8-M.
29  * The non-secure client identification is shared with SPE in
30  * single Armv8-M scenario via CMSIS TrustZone context management API,
31  * which may not work in dual core scenario.
32  */
33 #define NON_SECURE_CLIENT_ID            (-1)
34 
35 /*
36  * TODO
37  * Require a formal definition of errors related to mailbox in PSA client call.
38  */
39 #define PSA_INTER_CORE_COMM_ERR         (INT32_MIN + 0xFF)
40 
41 /**** TZ API functions ****/
42 
tz_psa_framework_version(void)43 uint32_t tz_psa_framework_version(void)
44 {
45     return tfm_ns_interface_dispatch(
46                                 (veneer_fn)tfm_psa_framework_version_veneer,
47                                 0,
48                                 0,
49                                 0,
50                                 0);
51 }
52 
tz_psa_version(uint32_t sid)53 uint32_t tz_psa_version(uint32_t sid)
54 {
55     return tfm_ns_interface_dispatch(
56                                 (veneer_fn)tfm_psa_version_veneer,
57                                 sid,
58                                 0,
59                                 0,
60                                 0);
61 }
62 
tz_psa_call(psa_handle_t handle,int32_t type,const psa_invec * in_vec,size_t in_len,psa_outvec * out_vec,size_t out_len)63 psa_status_t tz_psa_call(psa_handle_t handle, int32_t type,
64                       const psa_invec *in_vec,
65                       size_t in_len,
66                       psa_outvec *out_vec,
67                       size_t out_len)
68 {
69     if ((type    > PSA_CALL_TYPE_MAX) ||
70         (type    < PSA_CALL_TYPE_MIN) ||
71         (in_len  > PSA_MAX_IOVEC)     ||
72         (out_len > PSA_MAX_IOVEC)) {
73         return PSA_ERROR_PROGRAMMER_ERROR;
74     }
75 
76     return tfm_ns_interface_dispatch(
77                                 (veneer_fn)tfm_psa_call_veneer,
78                                 (uint32_t)handle,
79                                 PARAM_PACK(type, in_len, out_len),
80                                 (uint32_t)in_vec,
81                                 (uint32_t)out_vec);
82 }
83 
tz_psa_connect(uint32_t sid,uint32_t version)84 psa_handle_t tz_psa_connect(uint32_t sid, uint32_t version)
85 {
86     return tfm_ns_interface_dispatch((veneer_fn)tfm_psa_connect_veneer, sid, version, 0, 0);
87 }
88 
tz_psa_close(psa_handle_t handle)89 void tz_psa_close(psa_handle_t handle)
90 {
91     (void)tfm_ns_interface_dispatch((veneer_fn)tfm_psa_close_veneer, (uint32_t)handle, 0, 0, 0);
92 }
93 
94 /**** Mailbox API functions ****/
95 
mb_psa_framework_version(void)96 uint32_t mb_psa_framework_version(void)
97 {
98     struct psa_client_params_t params;
99     uint32_t version;
100     int32_t ret;
101 
102     ret = tfm_ns_mailbox_client_call(MAILBOX_PSA_FRAMEWORK_VERSION,
103                                      &params, NON_SECURE_CLIENT_ID,
104                                      (int32_t *)&version);
105     if (ret != MAILBOX_SUCCESS) {
106         version = PSA_VERSION_NONE;
107     }
108 
109     return version;
110 }
111 
mb_psa_version(uint32_t sid)112 uint32_t mb_psa_version(uint32_t sid)
113 {
114     struct psa_client_params_t params;
115     uint32_t version;
116     int32_t ret;
117 
118     params.psa_version_params.sid = sid;
119 
120     ret = tfm_ns_mailbox_client_call(MAILBOX_PSA_VERSION, &params,
121                                      NON_SECURE_CLIENT_ID,
122                                      (int32_t *)&version);
123     if (ret != MAILBOX_SUCCESS) {
124         version = PSA_VERSION_NONE;
125     }
126 
127     return version;
128 }
129 
mb_psa_connect(uint32_t sid,uint32_t version)130 psa_handle_t mb_psa_connect(uint32_t sid, uint32_t version)
131 {
132     struct psa_client_params_t params;
133     psa_handle_t psa_handle;
134     int32_t ret;
135 
136     params.psa_connect_params.sid = sid;
137     params.psa_connect_params.version = version;
138 
139     ret = tfm_ns_mailbox_client_call(MAILBOX_PSA_CONNECT, &params,
140                                      NON_SECURE_CLIENT_ID,
141                                      (int32_t *)&psa_handle);
142     if (ret != MAILBOX_SUCCESS) {
143         psa_handle = PSA_NULL_HANDLE;
144     }
145 
146     return psa_handle;
147 }
148 
mb_psa_call(psa_handle_t handle,int32_t type,const psa_invec * in_vec,size_t in_len,psa_outvec * out_vec,size_t out_len)149 psa_status_t mb_psa_call(psa_handle_t handle, int32_t type,
150                       const psa_invec *in_vec, size_t in_len,
151                       psa_outvec *out_vec, size_t out_len)
152 {
153     struct psa_client_params_t params;
154     int32_t ret;
155     psa_status_t status;
156 
157     params.psa_call_params.handle = handle;
158     params.psa_call_params.type = type;
159     params.psa_call_params.in_vec = in_vec;
160     params.psa_call_params.in_len = in_len;
161     params.psa_call_params.out_vec = out_vec;
162     params.psa_call_params.out_len = out_len;
163 
164     ret = tfm_ns_mailbox_client_call(MAILBOX_PSA_CALL, &params,
165                                      NON_SECURE_CLIENT_ID,
166                                      (int32_t *)&status);
167     if (ret != MAILBOX_SUCCESS) {
168         status = PSA_INTER_CORE_COMM_ERR;
169     }
170 
171     return status;
172 }
173 
mb_psa_close(psa_handle_t handle)174 void mb_psa_close(psa_handle_t handle)
175 {
176     struct psa_client_params_t params;
177     int32_t reply;
178 
179     params.psa_close_params.handle = handle;
180 
181     (void)tfm_ns_mailbox_client_call(MAILBOX_PSA_CLOSE, &params,
182                                      NON_SECURE_CLIENT_ID, &reply);
183 }
184 
185 /**** API functions ****/
186 
psa_framework_version(void)187 uint32_t psa_framework_version(void)
188 {
189     if(sio_hw->cpuid == 0) {
190         return tz_psa_framework_version();
191     } else {
192         return mb_psa_framework_version();
193     }
194 }
195 
psa_version(uint32_t sid)196 uint32_t psa_version(uint32_t sid)
197 {
198     if(sio_hw->cpuid == 0) {
199         return tz_psa_version(sid);
200     } else {
201         return mb_psa_version(sid);
202     }
203 }
204 
psa_call(psa_handle_t handle,int32_t type,const psa_invec * in_vec,size_t in_len,psa_outvec * out_vec,size_t out_len)205 psa_status_t psa_call(psa_handle_t handle, int32_t type,
206                       const psa_invec *in_vec,
207                       size_t in_len,
208                       psa_outvec *out_vec,
209                       size_t out_len)
210 {
211     if(sio_hw->cpuid == 0) {
212         return tz_psa_call(handle, type, in_vec, in_len, out_vec, out_len);
213     } else {
214         return mb_psa_call(handle, type, in_vec, in_len, out_vec, out_len);
215     }
216 }
217 
psa_connect(uint32_t sid,uint32_t version)218 psa_handle_t psa_connect(uint32_t sid, uint32_t version)
219 {
220     if(sio_hw->cpuid == 0) {
221         return tz_psa_connect(sid, version);
222     } else {
223         return mb_psa_connect(sid, version);
224     }
225 }
226 
psa_close(psa_handle_t handle)227 void psa_close(psa_handle_t handle)
228 {
229     if(sio_hw->cpuid == 0) {
230         return tz_psa_close(handle);
231     } else {
232         return mb_psa_close(handle);
233     }
234 }
235