1 /*
2  * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
3  * Copyright (c) 2022-2023 Cypress Semiconductor Corporation (an Infineon
4  * company) or an affiliate of Cypress Semiconductor Corporation. All rights
5  * reserved.
6  *
7  * SPDX-License-Identifier: BSD-3-Clause
8  *
9  */
10 #include "ffm/psa_api.h"
11 #include "spm.h"
12 #include "load/service_defs.h"
13 #include "utilities.h"
14 #include "tfm_hal_isolation.h"
15 
tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,uint32_t invec_idx)16 const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
17                                             uint32_t invec_idx)
18 {
19     struct connection_t *handle;
20     struct partition_t *partition = NULL;
21     fih_int fih_rc = FIH_FAILURE;
22 
23     /* It is a fatal error if message handle is invalid */
24     handle = spm_msg_handle_to_connection(msg_handle);
25     if (!handle) {
26         tfm_core_panic();
27     }
28 
29     partition = handle->service->partition;
30 
31     /*
32      * It is a fatal error if MM-IOVEC has not been enabled for the RoT
33      * Service that received the message.
34      */
35     if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
36         tfm_core_panic();
37     }
38 
39     /*
40      * It is a fatal error if message handle does not refer to a request
41      * message.
42      */
43     if (handle->msg.type < PSA_IPC_CALL) {
44         tfm_core_panic();
45     }
46 
47     /*
48      * It is a fatal error if invec_idx is equal to or greater than
49      * PSA_MAX_IOVEC.
50      */
51     if (invec_idx >= PSA_MAX_IOVEC) {
52         tfm_core_panic();
53     }
54 
55     /* It is a fatal error if the input vector has length zero. */
56     if (handle->msg.in_size[invec_idx] == 0) {
57         tfm_core_panic();
58     }
59 
60     /*
61      * It is a fatal error if the input vector has already been mapped using
62      * psa_map_invec().
63      */
64     if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
65         tfm_core_panic();
66     }
67 
68     /*
69      * It is a fatal error if the input vector has already been accessed
70      * using psa_read() or psa_skip().
71      */
72     if (IOVEC_IS_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE))) {
73         tfm_core_panic();
74     }
75 
76     /*
77      * It is a fatal error if the memory reference for the wrap input vector is
78      * invalid or not readable.
79      */
80     FIH_CALL(tfm_hal_memory_check, fih_rc,
81              partition->boundary, (uintptr_t)handle->invec_base[invec_idx],
82              handle->msg.in_size[invec_idx], TFM_HAL_ACCESS_READABLE);
83     if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
84         tfm_core_panic();
85     }
86 
87     SET_IOVEC_MAPPED(handle, (invec_idx + INVEC_IDX_BASE));
88 
89     return handle->invec_base[invec_idx];
90 }
91 
tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,uint32_t invec_idx)92 void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
93                                        uint32_t invec_idx)
94 {
95     struct connection_t *handle;
96 
97     /* It is a fatal error if message handle is invalid */
98     handle = spm_msg_handle_to_connection(msg_handle);
99     if (!handle) {
100         tfm_core_panic();
101     }
102 
103     /*
104      * It is a fatal error if MM-IOVEC has not been enabled for the RoT
105      * Service that received the message.
106      */
107     if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
108         tfm_core_panic();
109     }
110 
111     /*
112      * It is a fatal error if message handle does not refer to a request
113      * message.
114      */
115     if (handle->msg.type < PSA_IPC_CALL) {
116         tfm_core_panic();
117     }
118 
119     /*
120      * It is a fatal error if invec_idx is equal to or greater than
121      * PSA_MAX_IOVEC.
122      */
123     if (invec_idx >= PSA_MAX_IOVEC) {
124         tfm_core_panic();
125     }
126 
127     /*
128      * It is a fatal error if The input vector has not been mapped by a call to
129      * psa_map_invec().
130      */
131     if (!IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
132         tfm_core_panic();
133     }
134 
135     /*
136      * It is a fatal error if the input vector has already been unmapped by a
137      * call to psa_unmap_invec().
138      */
139     if (IOVEC_IS_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
140         tfm_core_panic();
141     }
142 
143     SET_IOVEC_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE));
144 }
145 
tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,uint32_t outvec_idx)146 void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
147                                        uint32_t outvec_idx)
148 {
149     struct connection_t *handle;
150     struct partition_t *partition = NULL;
151     fih_int fih_rc = FIH_FAILURE;
152 
153     /* It is a fatal error if message handle is invalid */
154     handle = spm_msg_handle_to_connection(msg_handle);
155     if (!handle) {
156         tfm_core_panic();
157     }
158 
159     partition = handle->service->partition;
160 
161     /*
162      * It is a fatal error if MM-IOVEC has not been enabled for the RoT
163      * Service that received the message.
164      */
165     if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
166         tfm_core_panic();
167     }
168 
169     /*
170      * It is a fatal error if message handle does not refer to a request
171      * message.
172      */
173     if (handle->msg.type < PSA_IPC_CALL) {
174         tfm_core_panic();
175     }
176 
177     /*
178      * It is a fatal error if outvec_idx is equal to or greater than
179      * PSA_MAX_IOVEC.
180      */
181     if (outvec_idx >= PSA_MAX_IOVEC) {
182         tfm_core_panic();
183     }
184 
185     /* It is a fatal error if the output vector has length zero. */
186     if (handle->msg.out_size[outvec_idx] == 0) {
187         tfm_core_panic();
188     }
189 
190     /*
191      * It is a fatal error if the output vector has already been mapped using
192      * psa_map_outvec().
193      */
194     if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
195         tfm_core_panic();
196     }
197 
198     /*
199      * It is a fatal error if the output vector has already been accessed
200      * using psa_write().
201      */
202     if (IOVEC_IS_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
203         tfm_core_panic();
204     }
205 
206     /*
207      * It is a fatal error if the output vector is invalid or not read-write.
208      */
209     FIH_CALL(tfm_hal_memory_check, fih_rc,
210              partition->boundary, (uintptr_t)handle->outvec_base[outvec_idx],
211              handle->msg.out_size[outvec_idx], TFM_HAL_ACCESS_READWRITE);
212     if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
213         tfm_core_panic();
214     }
215     SET_IOVEC_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
216 
217     return handle->outvec_base[outvec_idx];
218 }
219 
tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,uint32_t outvec_idx,size_t len)220 void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
221                                         uint32_t outvec_idx, size_t len)
222 {
223     struct connection_t *handle;
224 
225     /* It is a fatal error if message handle is invalid */
226     handle = spm_msg_handle_to_connection(msg_handle);
227     if (!handle) {
228         tfm_core_panic();
229     }
230 
231     /*
232      * It is a fatal error if MM-IOVEC has not been enabled for the RoT
233      * Service that received the message.
234      */
235     if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
236         tfm_core_panic();
237     }
238 
239     /*
240      * It is a fatal error if message handle does not refer to a request
241      * message.
242      */
243     if (handle->msg.type < PSA_IPC_CALL) {
244         tfm_core_panic();
245     }
246 
247     /*
248      * It is a fatal error if outvec_idx is equal to or greater than
249      * PSA_MAX_IOVEC.
250      */
251     if (outvec_idx >= PSA_MAX_IOVEC) {
252         tfm_core_panic();
253     }
254 
255     /*
256      * It is a fatal error if len is greater than the output vector size.
257      */
258     if (len > handle->msg.out_size[outvec_idx]) {
259         tfm_core_panic();
260     }
261 
262     /*
263      * It is a fatal error if The output vector has not been mapped by a call to
264      * psa_map_outvec().
265      */
266     if (!IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
267         tfm_core_panic();
268     }
269 
270     /*
271      * It is a fatal error if the output vector has already been unmapped by a
272      * call to psa_unmap_outvec().
273      */
274     if (IOVEC_IS_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
275         tfm_core_panic();
276     }
277 
278     SET_IOVEC_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
279 
280     /* Update the write number */
281     handle->outvec_written[outvec_idx] = len;
282 }
283