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 "utilities.h"
13 #include "tfm_hal_isolation.h"
14
tfm_spm_partition_psa_read(psa_handle_t msg_handle,uint32_t invec_idx,void * buffer,size_t num_bytes)15 size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
16 void *buffer, size_t num_bytes)
17 {
18 size_t bytes, remaining;
19 struct connection_t *handle = NULL;
20 const struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
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 /*
30 * It is a fatal error if message handle does not refer to a request
31 * message
32 */
33 if (handle->msg.type < PSA_IPC_CALL) {
34 tfm_core_panic();
35 }
36
37 /*
38 * It is a fatal error if invec_idx is equal to or greater than
39 * PSA_MAX_IOVEC
40 */
41 if (invec_idx >= PSA_MAX_IOVEC) {
42 tfm_core_panic();
43 }
44
45 #if PSA_FRAMEWORK_HAS_MM_IOVEC
46 /*
47 * It is a fatal error if the input vector has already been mapped using
48 * psa_map_invec().
49 */
50 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE)) ||
51 IOVEC_IS_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
52 tfm_core_panic();
53 }
54
55 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
56 #endif
57
58 remaining = handle->msg.in_size[invec_idx] - handle->invec_accessed[invec_idx];
59 /* There was no remaining data in this input vector */
60 if (remaining == 0) {
61 return 0;
62 }
63
64 /*
65 * Copy the client data to the service buffer. It is a fatal error
66 * if the memory reference for buffer is invalid or not read-write.
67 */
68 FIH_CALL(tfm_hal_memory_check, fih_rc,
69 curr_partition->boundary, (uintptr_t)buffer,
70 num_bytes, TFM_HAL_ACCESS_READWRITE);
71 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
72 tfm_core_panic();
73 }
74
75 bytes = (num_bytes < remaining) ? num_bytes : remaining;
76
77 spm_memcpy(buffer, (char *)handle->invec_base[invec_idx] +
78 handle->invec_accessed[invec_idx], bytes);
79
80 /* Update the data size read */
81 handle->invec_accessed[invec_idx] += bytes;
82
83 return bytes;
84 }
85
tfm_spm_partition_psa_skip(psa_handle_t msg_handle,uint32_t invec_idx,size_t num_bytes)86 size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
87 size_t num_bytes)
88 {
89 struct connection_t *handle = NULL;
90 size_t remaining;
91
92 /* It is a fatal error if message handle is invalid */
93 handle = spm_msg_handle_to_connection(msg_handle);
94 if (!handle) {
95 tfm_core_panic();
96 }
97
98 /*
99 * It is a fatal error if message handle does not refer to a request
100 * message
101 */
102 if (handle->msg.type < PSA_IPC_CALL) {
103 tfm_core_panic();
104 }
105
106 /*
107 * It is a fatal error if invec_idx is equal to or greater than
108 * PSA_MAX_IOVEC
109 */
110 if (invec_idx >= PSA_MAX_IOVEC) {
111 tfm_core_panic();
112 }
113
114 #if PSA_FRAMEWORK_HAS_MM_IOVEC
115 /*
116 * It is a fatal error if the input vector has already been mapped using
117 * psa_map_invec().
118 */
119 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE)) ||
120 IOVEC_IS_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
121 tfm_core_panic();
122 }
123
124 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
125 #endif
126
127 remaining = handle->msg.in_size[invec_idx] - handle->invec_accessed[invec_idx];
128 /* There was no remaining data in this input vector */
129 if (remaining == 0) {
130 return 0;
131 }
132
133 /*
134 * If num_bytes is greater than the remaining size of the input vector then
135 * the remaining size of the input vector is used.
136 */
137 if (num_bytes > remaining) {
138 num_bytes = remaining;
139 }
140
141 /* Update the data size accessed */
142 handle->invec_accessed[invec_idx] += num_bytes;
143
144 return num_bytes;
145 }
146
tfm_spm_partition_psa_write(psa_handle_t msg_handle,uint32_t outvec_idx,const void * buffer,size_t num_bytes)147 psa_status_t tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
148 const void *buffer, size_t num_bytes)
149 {
150 struct connection_t *handle = NULL;
151 const struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
152 fih_int fih_rc = FIH_FAILURE;
153
154 /* It is a fatal error if message handle is invalid */
155 handle = spm_msg_handle_to_connection(msg_handle);
156 if (!handle) {
157 tfm_core_panic();
158 }
159
160 /*
161 * It is a fatal error if message handle does not refer to a request
162 * message
163 */
164 if (handle->msg.type < PSA_IPC_CALL) {
165 tfm_core_panic();
166 }
167
168 /*
169 * It is a fatal error if outvec_idx is equal to or greater than
170 * PSA_MAX_IOVEC
171 */
172 if (outvec_idx >= PSA_MAX_IOVEC) {
173 tfm_core_panic();
174 }
175
176 /*
177 * It is a fatal error if the call attempts to write data past the end of
178 * the client output vector
179 */
180 if (num_bytes > (handle->msg.out_size[outvec_idx] - handle->outvec_written[outvec_idx])) {
181 tfm_core_panic();
182 }
183
184 #if PSA_FRAMEWORK_HAS_MM_IOVEC
185 /*
186 * It is a fatal error if the output vector has already been mapped using
187 * psa_map_outvec().
188 */
189 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE)) ||
190 IOVEC_IS_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
191 tfm_core_panic();
192 }
193
194 SET_IOVEC_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE));
195 #endif
196
197 /*
198 * Copy the service buffer to client outvecs. It is a fatal error
199 * if the memory reference for buffer is invalid or not readable.
200 */
201 FIH_CALL(tfm_hal_memory_check, fih_rc,
202 curr_partition->boundary, (uintptr_t)buffer,
203 num_bytes, TFM_HAL_ACCESS_READABLE);
204 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
205 tfm_core_panic();
206 }
207
208 spm_memcpy((char *)handle->outvec_base[outvec_idx] +
209 handle->outvec_written[outvec_idx], buffer, num_bytes);
210
211 /* Update the data size written */
212 handle->outvec_written[outvec_idx] += num_bytes;
213
214 return PSA_SUCCESS;
215 }
216