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