blob: f72609b2c17109d6eacd9ce12f52cb94353eebbf [file] [log] [blame]
David Hu733d8f92019-09-23 15:32:40 +08001/*
Xinyu Zhang669744c2023-02-06 15:24:26 +08002 * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
BohdanHunko628109f2023-01-31 17:23:35 +02003 * Copyright (c) 2022-2023 Cypress Semiconductor Corporation (an Infineon
Chris Brand10a2acb2022-10-18 17:12:27 -07004 * company) or an affiliate of Cypress Semiconductor Corporation. All rights
5 * reserved.
David Hu733d8f92019-09-23 15:32:40 +08006 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 */
10
Mingyang Suneeca4652021-07-15 15:19:16 +080011#include <stdint.h>
Mingyang Sunb26b2802021-07-07 11:25:00 +080012#include "bitops.h"
Mingyang Sun4609ac72022-02-08 18:56:35 +080013#include "config_impl.h"
Xinyu Zhangcdbe3622022-10-31 14:34:25 +080014#include "config_spm.h"
Ken Liu92ede9f2021-10-20 09:35:00 +080015#include "critical_section.h"
Mingyang Suneeca4652021-07-15 15:19:16 +080016#include "psa/lifecycle.h"
David Hu733d8f92019-09-23 15:32:40 +080017#include "psa/service.h"
Kevin Peng3f67b2e2021-10-18 17:47:27 +080018#include "interrupt.h"
Sherry Zhangc7147022023-02-03 11:21:10 +080019#include "spm.h"
Mingyang Sun22a3faf2021-07-09 15:32:47 +080020#include "tfm_arch.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080021#include "load/partition_defs.h"
Mingyang Sun2b352662021-04-21 11:35:43 +080022#include "load/service_defs.h"
Ken Liu3dd92562021-08-17 16:22:54 +080023#include "load/interrupt_defs.h"
Summer Qin5fdcf632020-06-22 16:49:24 +080024#include "utilities.h"
Mingyang Sundeae45d2021-09-06 15:31:07 +080025#include "ffm/backend.h"
Ken Liue07c3b72021-10-14 16:19:13 +080026#include "ffm/psa_api.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080027#include "tfm_rpc.h"
Kevin Pengb42ed862022-08-08 14:44:02 +080028#include "tfm_api.h"
Kevin Pengd399a1f2021-09-08 15:33:14 +080029#include "tfm_hal_interrupt.h"
Mingyang Sunb26b2802021-07-07 11:25:00 +080030#include "tfm_hal_platform.h"
Ken Liu82e3eac2021-10-14 16:19:13 +080031#include "tfm_psa_call_pack.h"
Summer Qin56725eb2022-05-06 15:23:40 +080032#include "tfm_hal_isolation.h"
David Hu733d8f92019-09-23 15:32:40 +080033
Shawn Shan038348e2021-09-08 17:11:04 +080034#if PSA_FRAMEWORK_HAS_MM_IOVEC
35
36/*
37 * The MM-IOVEC status
38 * The max total number of invec and outvec is 8.
39 * Each invec/outvec takes 4 bit, 32 bits in total.
40 *
41 * The encoding format of the MM-IOVEC status:
42 *--------------------------------------------------------------
43 *| Bit | 31 - 28 | 27 - 24 | ... | 7 - 4 | 3 - 0 |
44 *--------------------------------------------------------------
45 *| Vector | outvec[3] | outvec[2] | ... | invec[1] | invec[0] |
46 *--------------------------------------------------------------
47 *
48 * Take invec[0] as an example:
49 *
50 * bit 0: whether invec[0] has been mapped.
51 * bit 1: whether invec[0] has been unmapped.
52 * bit 2: whether invec[0] has been accessed using psa_read(), psa_skip() or
53 * psa_write().
54 * bit 3: reserved for invec[0].
55 */
56
57#define IOVEC_STATUS_BITS 4 /* Each vector occupies 4 bits. */
58#define OUTVEC_IDX_BASE 4 /*
59 * Base index of outvec.
60 * There are four invecs in front of
61 * outvec.
62 */
63#define INVEC_IDX_BASE 0 /* Base index of invec. */
64
65#define IOVEC_MAPPED_BIT (1U << 0)
66#define IOVEC_UNMAPPED_BIT (1U << 1)
67#define IOVEC_ACCESSED_BIT (1U << 2)
68
Mingyang Suna09adda2022-02-16 18:11:33 +080069#define IOVEC_IS_MAPPED(handle, iovec_idx) \
70 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080071 IOVEC_MAPPED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080072#define IOVEC_IS_UNMAPPED(handle, iovec_idx) \
73 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080074 IOVEC_UNMAPPED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080075#define IOVEC_IS_ACCESSED(handle, iovec_idx) \
76 ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) & \
Shawn Shan038348e2021-09-08 17:11:04 +080077 IOVEC_ACCESSED_BIT)
Mingyang Suna09adda2022-02-16 18:11:33 +080078#define SET_IOVEC_MAPPED(handle, iovec_idx) \
79 (((handle)->iovec_status) |= (IOVEC_MAPPED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080080 ((iovec_idx) * IOVEC_STATUS_BITS)))
Mingyang Suna09adda2022-02-16 18:11:33 +080081#define SET_IOVEC_UNMAPPED(handle, iovec_idx) \
82 (((handle)->iovec_status) |= (IOVEC_UNMAPPED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080083 ((iovec_idx) * IOVEC_STATUS_BITS)))
Mingyang Suna09adda2022-02-16 18:11:33 +080084#define SET_IOVEC_ACCESSED(handle, iovec_idx) \
85 (((handle)->iovec_status) |= (IOVEC_ACCESSED_BIT << \
Shawn Shan038348e2021-09-08 17:11:04 +080086 ((iovec_idx) * IOVEC_STATUS_BITS)))
87
88#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
89
Xinyu Zhangb287ef82021-11-03 18:38:50 +080090void spm_handle_programmer_errors(psa_status_t status)
91{
Summer Qind9d497b2022-04-14 14:39:26 +080092 if (status == PSA_ERROR_PROGRAMMER_ERROR ||
93 status == PSA_ERROR_CONNECTION_REFUSED) {
94 if (!tfm_spm_is_ns_caller()) {
Xinyu Zhangb287ef82021-11-03 18:38:50 +080095 tfm_core_panic();
Summer Qind9d497b2022-04-14 14:39:26 +080096 }
Xinyu Zhangb287ef82021-11-03 18:38:50 +080097 }
98}
99
Mingyang Suneeca4652021-07-15 15:19:16 +0800100uint32_t tfm_spm_get_lifecycle_state(void)
101{
102 /*
103 * FixMe: return PSA_LIFECYCLE_UNKNOWN to the caller directly. It will be
104 * implemented in the future.
105 */
106 return PSA_LIFECYCLE_UNKNOWN;
107}
108
Mingyang Suneeca4652021-07-15 15:19:16 +0800109/* PSA Partition API function body */
110
Kevin Pengdef92de2021-11-10 16:14:48 +0800111#if CONFIG_TFM_SPM_BACKEND_IPC == 1 \
112 || CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800113psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
114 uint32_t timeout)
115{
116 struct partition_t *partition = NULL;
117
118 /*
119 * Timeout[30:0] are reserved for future use.
120 * SPM must ignore the value of RES.
121 */
122 timeout &= PSA_TIMEOUT_MASK;
123
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800124 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800125
126 /*
Ruchika Guptad1834172022-06-15 12:03:08 +0530127 * signals_allowed can be 0 for TF-M internal partitions for special usages.
128 * Regular Secure Partitions should have at least one signal.
129 * This is gauranteed by the manifest tool.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800130 * It is a PROGRAMMER ERROR if the signal_mask does not include any assigned
131 * signals.
132 */
Ruchika Guptad1834172022-06-15 12:03:08 +0530133 if ((partition->signals_allowed) &&
134 (partition->signals_allowed & signal_mask) == 0) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800135 tfm_core_panic();
136 }
137
138 /*
Ken Liu995a9742022-05-18 19:28:30 +0800139 * backend_wake_up() blocks the caller thread if no signals are
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800140 * available. In this case, the return value of this function is temporary
141 * set into runtime context. After new signal(s) are available, the return
142 * value is updated with the available signal(s) and blocked thread gets
143 * to run.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800144 */
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800145 if (timeout == PSA_BLOCK) {
Ken Liu995a9742022-05-18 19:28:30 +0800146 return backend_wait(partition, signal_mask);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800147 }
148
149 return partition->signals_asserted & signal_mask;
150}
Kevin Pengdef92de2021-11-10 16:14:48 +0800151#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800152
Kevin Pengdef92de2021-11-10 16:14:48 +0800153#if CONFIG_TFM_SPM_BACKEND_IPC == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800154psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
155{
Mingyang Suna09adda2022-02-16 18:11:33 +0800156 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800157 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800158 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800159
160 /*
161 * Only one message could be retrieved every time for psa_get(). It is a
162 * fatal error if the input signal has more than a signal bit set.
163 */
164 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
165 tfm_core_panic();
166 }
167
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800168 partition = GET_CURRENT_COMPONENT();
169
Mingyang Sunb26b2802021-07-07 11:25:00 +0800170 /*
171 * Write the message to the service buffer. It is a fatal error if the
172 * input msg pointer is not a valid memory reference or not read-write.
173 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800174 FIH_CALL(tfm_hal_memory_check, fih_rc,
175 partition->boundary, (uintptr_t)msg,
176 sizeof(psa_msg_t), TFM_HAL_ACCESS_READWRITE);
177 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800178 tfm_core_panic();
179 }
180
181 /*
182 * It is a fatal error if the caller call psa_get() when no message has
183 * been set. The caller must call this function after an RoT Service signal
184 * is returned by psa_wait().
185 */
186 if (partition->signals_asserted == 0) {
187 tfm_core_panic();
188 }
189
190 /*
191 * It is a fatal error if the RoT Service signal is not currently asserted.
192 */
193 if ((partition->signals_asserted & signal) == 0) {
194 tfm_core_panic();
195 }
196
197 /*
198 * Get message by signal from partition. It is a fatal error if getting
199 * failed, which means the input signal is not correspond to an RoT service.
200 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800201 handle = spm_get_handle_by_signal(partition, signal);
202 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800203 return PSA_ERROR_DOES_NOT_EXIST;
204 }
205
Mingyang Suna09adda2022-02-16 18:11:33 +0800206 spm_memcpy(msg, &handle->msg, sizeof(psa_msg_t));
Mingyang Sunb26b2802021-07-07 11:25:00 +0800207
208 return PSA_SUCCESS;
209}
Mingyang Sun4609ac72022-02-08 18:56:35 +0800210#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800211
Mingyang Sunb26b2802021-07-07 11:25:00 +0800212size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
213 void *buffer, size_t num_bytes)
214{
215 size_t bytes;
Mingyang Suna09adda2022-02-16 18:11:33 +0800216 struct conn_handle_t *handle = NULL;
Summer Qin56725eb2022-05-06 15:23:40 +0800217 struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800218 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800219
220 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800221 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800222 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800223 tfm_core_panic();
224 }
225
Mingyang Sunb26b2802021-07-07 11:25:00 +0800226 /*
227 * It is a fatal error if message handle does not refer to a request
228 * message
229 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800230 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800231 tfm_core_panic();
232 }
233
234 /*
235 * It is a fatal error if invec_idx is equal to or greater than
236 * PSA_MAX_IOVEC
237 */
238 if (invec_idx >= PSA_MAX_IOVEC) {
239 tfm_core_panic();
240 }
241
Shawn Shan038348e2021-09-08 17:11:04 +0800242#if PSA_FRAMEWORK_HAS_MM_IOVEC
243 /*
244 * It is a fatal error if the input vector has already been mapped using
245 * psa_map_invec().
246 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800247 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800248 tfm_core_panic();
249 }
250
Mingyang Suna09adda2022-02-16 18:11:33 +0800251 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800252#endif
253
Kevin Peng016b0e42022-04-15 11:28:48 +0800254 /* There was no remaining data in this input vector */
255 if (handle->msg.in_size[invec_idx] == 0) {
256 return 0;
257 }
258
Mingyang Sunb26b2802021-07-07 11:25:00 +0800259 /*
260 * Copy the client data to the service buffer. It is a fatal error
261 * if the memory reference for buffer is invalid or not read-write.
262 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800263 FIH_CALL(tfm_hal_memory_check, fih_rc,
264 curr_partition->boundary, (uintptr_t)buffer,
265 num_bytes, TFM_HAL_ACCESS_READWRITE);
266 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800267 tfm_core_panic();
268 }
269
Mingyang Suna09adda2022-02-16 18:11:33 +0800270 bytes = num_bytes > handle->msg.in_size[invec_idx] ?
271 handle->msg.in_size[invec_idx] : num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800272
Mingyang Suna09adda2022-02-16 18:11:33 +0800273 spm_memcpy(buffer, handle->invec[invec_idx].base, bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800274
275 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800276 handle->invec[invec_idx].base =
277 (char *)handle->invec[invec_idx].base + bytes;
278 handle->msg.in_size[invec_idx] -= bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800279
280 return bytes;
281}
282
283size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
284 size_t num_bytes)
285{
Mingyang Suna09adda2022-02-16 18:11:33 +0800286 struct conn_handle_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800287
288 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800289 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800290 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800291 tfm_core_panic();
292 }
293
294 /*
295 * It is a fatal error if message handle does not refer to a request
296 * message
297 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800298 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800299 tfm_core_panic();
300 }
301
302 /*
303 * It is a fatal error if invec_idx is equal to or greater than
304 * PSA_MAX_IOVEC
305 */
306 if (invec_idx >= PSA_MAX_IOVEC) {
307 tfm_core_panic();
308 }
309
Shawn Shan038348e2021-09-08 17:11:04 +0800310#if PSA_FRAMEWORK_HAS_MM_IOVEC
311 /*
312 * It is a fatal error if the input vector has already been mapped using
313 * psa_map_invec().
314 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800315 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800316 tfm_core_panic();
317 }
318
Mingyang Suna09adda2022-02-16 18:11:33 +0800319 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800320#endif
321
Kevin Peng016b0e42022-04-15 11:28:48 +0800322 /* There was no remaining data in this input vector */
323 if (handle->msg.in_size[invec_idx] == 0) {
324 return 0;
325 }
326
Mingyang Sunb26b2802021-07-07 11:25:00 +0800327 /*
328 * If num_bytes is greater than the remaining size of the input vector then
329 * the remaining size of the input vector is used.
330 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800331 if (num_bytes > handle->msg.in_size[invec_idx]) {
332 num_bytes = handle->msg.in_size[invec_idx];
Mingyang Sunb26b2802021-07-07 11:25:00 +0800333 }
334
335 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800336 handle->invec[invec_idx].base =
337 (char *)handle->invec[invec_idx].base + num_bytes;
338 handle->msg.in_size[invec_idx] -= num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800339
340 return num_bytes;
341}
342
343void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
344 const void *buffer, size_t num_bytes)
345{
Mingyang Suna09adda2022-02-16 18:11:33 +0800346 struct conn_handle_t *handle = NULL;
Summer Qin56725eb2022-05-06 15:23:40 +0800347 struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800348 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800349
350 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800351 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800352 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800353 tfm_core_panic();
354 }
355
Mingyang Sunb26b2802021-07-07 11:25:00 +0800356 /*
357 * It is a fatal error if message handle does not refer to a request
358 * message
359 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800360 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800361 tfm_core_panic();
362 }
363
364 /*
365 * It is a fatal error if outvec_idx is equal to or greater than
366 * PSA_MAX_IOVEC
367 */
368 if (outvec_idx >= PSA_MAX_IOVEC) {
369 tfm_core_panic();
370 }
371
372 /*
373 * It is a fatal error if the call attempts to write data past the end of
374 * the client output vector
375 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800376 if (num_bytes > handle->msg.out_size[outvec_idx] -
377 handle->outvec[outvec_idx].len) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800378 tfm_core_panic();
379 }
380
Shawn Shan038348e2021-09-08 17:11:04 +0800381#if PSA_FRAMEWORK_HAS_MM_IOVEC
382 /*
383 * It is a fatal error if the output vector has already been mapped using
384 * psa_map_outvec().
385 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800386 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800387 tfm_core_panic();
388 }
389
Mingyang Suna09adda2022-02-16 18:11:33 +0800390 SET_IOVEC_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800391#endif
392
Mingyang Sunb26b2802021-07-07 11:25:00 +0800393 /*
394 * Copy the service buffer to client outvecs. It is a fatal error
395 * if the memory reference for buffer is invalid or not readable.
396 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800397 FIH_CALL(tfm_hal_memory_check, fih_rc,
398 curr_partition->boundary, (uintptr_t)buffer,
399 num_bytes, TFM_HAL_ACCESS_READABLE);
400 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800401 tfm_core_panic();
402 }
403
Mingyang Suna09adda2022-02-16 18:11:33 +0800404 spm_memcpy((char *)handle->outvec[outvec_idx].base +
405 handle->outvec[outvec_idx].len, buffer, num_bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800406
407 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +0800408 handle->outvec[outvec_idx].len += num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800409}
410
Ken Liuf8c7e532022-02-10 15:03:04 +0800411psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
412 psa_status_t status)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800413{
Ken Liu0bed7e02022-02-10 12:38:07 +0800414 struct service_t *service;
Mingyang Suna09adda2022-02-16 18:11:33 +0800415 struct conn_handle_t *handle;
Ken Liuf8c7e532022-02-10 15:03:04 +0800416 psa_status_t ret = PSA_SUCCESS;
Mingyang Sun620c8562021-11-10 11:44:58 +0800417 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800418
419 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800420 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800421 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800422 tfm_core_panic();
423 }
424
425 /*
426 * RoT Service information is needed in this function, stored it in message
427 * body structure. Only two parameters are passed in this function: handle
428 * and status, so it is useful and simply to do like this.
429 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800430 service = handle->service;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800431 if (!service) {
432 tfm_core_panic();
433 }
434
Mingyang Suna09adda2022-02-16 18:11:33 +0800435 switch (handle->msg.type) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800436 case PSA_IPC_CONNECT:
437 /*
438 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
439 * input status is PSA_SUCCESS. Others return values are based on the
440 * input status.
441 */
442 if (status == PSA_SUCCESS) {
443 ret = msg_handle;
444 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
445 /* Refuse the client connection, indicating a permanent error. */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800446 ret = PSA_ERROR_CONNECTION_REFUSED;
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800447 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800448 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
449 /* Fail the client connection, indicating a transient error. */
450 ret = PSA_ERROR_CONNECTION_BUSY;
451 } else {
452 tfm_core_panic();
453 }
454 break;
455 case PSA_IPC_DISCONNECT:
456 /* Service handle is not used anymore */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800457 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800458
459 /*
460 * If the message type is PSA_IPC_DISCONNECT, then the status code is
461 * ignored
462 */
463 break;
464 default:
Mingyang Suna09adda2022-02-16 18:11:33 +0800465 if (handle->msg.type >= PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800466
467#if PSA_FRAMEWORK_HAS_MM_IOVEC
468
469 /*
470 * If the unmapped function is not called for an input/output vector
471 * that has been mapped, the framework will remove the mapping.
472 */
473 int i;
474
475 for (i = 0; i < PSA_MAX_IOVEC * 2; i++) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800476 if (IOVEC_IS_MAPPED(handle, i) &&
477 (!IOVEC_IS_UNMAPPED(handle, i))) {
478 SET_IOVEC_UNMAPPED(handle, i);
Shawn Shan038348e2021-09-08 17:11:04 +0800479 /*
480 * Any output vectors that are still mapped will report that
481 * zero bytes have been written.
482 */
483 if (i >= OUTVEC_IDX_BASE) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800484 handle->outvec[i - OUTVEC_IDX_BASE].len = 0;
Shawn Shan038348e2021-09-08 17:11:04 +0800485 }
486 }
487 }
488
489#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800490 /* Reply to a request message. Return values are based on status */
491 ret = status;
492 /*
493 * The total number of bytes written to a single parameter must be
494 * reported to the client by updating the len member of the
495 * psa_outvec structure for the parameter before returning from
496 * psa_call().
497 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800498 update_caller_outvec_len(handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800499 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800500 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800501 }
502 } else {
503 tfm_core_panic();
504 }
505 }
506
507 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
508 /*
509 * If the source of the programmer error is a Secure Partition, the SPM
510 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
511 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800512 if (!TFM_CLIENT_ID_IS_NS(handle->msg.client_id)) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800513 tfm_core_panic();
514 }
Mingyang Sunb26b2802021-07-07 11:25:00 +0800515 }
516
Mingyang Sun620c8562021-11-10 11:44:58 +0800517 /*
518 * TODO: It can be optimized further by moving critical section protection
519 * to mailbox. Also need to check implementation when secure context is
520 * involved.
521 */
522 CRITICAL_SECTION_ENTER(cs_assert);
Ken Liu995a9742022-05-18 19:28:30 +0800523 ret = backend_replying(handle, ret);
Mingyang Sun620c8562021-11-10 11:44:58 +0800524 CRITICAL_SECTION_LEAVE(cs_assert);
525
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800526 if (handle->status == TFM_HANDLE_STATUS_TO_FREE) {
527 tfm_spm_free_conn_handle(handle);
528 } else {
529 handle->status = TFM_HANDLE_STATUS_IDLE;
530 }
531
Mingyang Sun620c8562021-11-10 11:44:58 +0800532 return ret;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800533}
534
Kevin Peng613b4172022-02-15 14:41:44 +0800535#if CONFIG_TFM_DOORBELL_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800536void tfm_spm_partition_psa_notify(int32_t partition_id)
537{
Ken Liu5d73c872021-08-19 19:23:17 +0800538 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
539
540 spm_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800541}
542
543void tfm_spm_partition_psa_clear(void)
544{
Ken Liu92ede9f2021-10-20 09:35:00 +0800545 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800546 struct partition_t *partition = NULL;
547
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800548 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800549
550 /*
551 * It is a fatal error if the Secure Partition's doorbell signal is not
552 * currently asserted.
553 */
554 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
555 tfm_core_panic();
556 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800557
558 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800559 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800560 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800561}
Kevin Peng613b4172022-02-15 14:41:44 +0800562#endif /* CONFIG_TFM_DOORBELL_API == 1 */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800563
Mingyang Sunb26b2802021-07-07 11:25:00 +0800564void tfm_spm_partition_psa_panic(void)
565{
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100566#ifdef CONFIG_TFM_HALT_ON_CORE_PANIC
567 tfm_hal_system_halt();
568#else
Mingyang Sunb26b2802021-07-07 11:25:00 +0800569 /*
570 * PSA FF recommends that the SPM causes the system to restart when a secure
571 * partition panics.
572 */
573 tfm_hal_system_reset();
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100574#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800575}
576
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800577#if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Kevin Peng67a89fd2021-11-25 11:22:02 +0800578void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800579{
580 struct partition_t *partition;
Chris Brand10a2acb2022-10-18 17:12:27 -0700581 const struct irq_load_info_t *irq_info;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800582
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800583 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800584
585 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
586 if (!irq_info) {
587 tfm_core_panic();
588 }
589
Kevin Pengd399a1f2021-09-08 15:33:14 +0800590 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800591}
592
Kevin Peng67a89fd2021-11-25 11:22:02 +0800593psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800594{
595 struct partition_t *partition;
Chris Brand10a2acb2022-10-18 17:12:27 -0700596 const struct irq_load_info_t *irq_info;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800597
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800598 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800599
600 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
601 if (!irq_info) {
602 tfm_core_panic();
603 }
604
Kevin Pengd399a1f2021-09-08 15:33:14 +0800605 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800606
607 return 1;
608}
609
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800610/* This API is only used for FLIH. */
611#if CONFIG_TFM_FLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800612void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
613{
Ken Liu92ede9f2021-10-20 09:35:00 +0800614 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Chris Brand10a2acb2022-10-18 17:12:27 -0700615 const struct irq_load_info_t *irq_info;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800616 struct partition_t *partition;
617
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800618 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800619
620 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
621 if (!irq_info) {
622 tfm_core_panic();
623 }
624
625 if (!irq_info->flih_func) {
626 /* This API is for FLIH IRQs only */
627 tfm_core_panic();
628 }
629
630 if ((partition->signals_asserted & irq_signal) == 0) {
631 /* The signal is not asserted */
632 tfm_core_panic();
633 }
634
Ken Liu92ede9f2021-10-20 09:35:00 +0800635 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800636 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800637 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800638}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800639#endif
Shawn Shan038348e2021-09-08 17:11:04 +0800640
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800641/* This API is only used for SLIH. */
642#if CONFIG_TFM_SLIH_API == 1
643void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800644{
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800645 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Chris Brand10a2acb2022-10-18 17:12:27 -0700646 const struct irq_load_info_t *irq_info = NULL;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800647 struct partition_t *partition = NULL;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800648
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800649 partition = GET_CURRENT_COMPONENT();
650
651 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
652 /* It is a fatal error if passed signal is not an interrupt signal. */
653 if (!irq_info) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800654 tfm_core_panic();
655 }
656
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800657 if (irq_info->flih_func) {
658 /* This API is for SLIH IRQs only */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800659 tfm_core_panic();
660 }
661
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800662 /* It is a fatal error if passed signal is not currently asserted */
663 if ((partition->signals_asserted & irq_signal) == 0) {
664 tfm_core_panic();
665 }
666
667 CRITICAL_SECTION_ENTER(cs_assert);
668 partition->signals_asserted &= ~irq_signal;
669 CRITICAL_SECTION_LEAVE(cs_assert);
670
671 tfm_hal_irq_clear_pending(irq_info->source);
672 tfm_hal_irq_enable(irq_info->source);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800673}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800674#endif
675#endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800676
Shawn Shan038348e2021-09-08 17:11:04 +0800677#if PSA_FRAMEWORK_HAS_MM_IOVEC
678
679const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
680 uint32_t invec_idx)
681{
Mingyang Suna09adda2022-02-16 18:11:33 +0800682 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +0800683 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800684 fih_int fih_rc = FIH_FAILURE;
Shawn Shan038348e2021-09-08 17:11:04 +0800685
686 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800687 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800688 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +0800689 tfm_core_panic();
690 }
691
Mingyang Suna09adda2022-02-16 18:11:33 +0800692 partition = handle->service->partition;
Shawn Shan038348e2021-09-08 17:11:04 +0800693
694 /*
695 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
696 * Service that received the message.
697 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800698 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +0800699 tfm_core_panic();
700 }
701
702 /*
703 * It is a fatal error if message handle does not refer to a request
704 * message.
705 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800706 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800707 tfm_core_panic();
708 }
709
710 /*
711 * It is a fatal error if invec_idx is equal to or greater than
712 * PSA_MAX_IOVEC.
713 */
714 if (invec_idx >= PSA_MAX_IOVEC) {
715 tfm_core_panic();
716 }
717
718 /* It is a fatal error if the input vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800719 if (handle->msg.in_size[invec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +0800720 tfm_core_panic();
721 }
722
723 /*
724 * It is a fatal error if the input vector has already been mapped using
725 * psa_map_invec().
726 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800727 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800728 tfm_core_panic();
729 }
730
731 /*
732 * It is a fatal error if the input vector has already been accessed
733 * using psa_read() or psa_skip().
734 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800735 if (IOVEC_IS_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800736 tfm_core_panic();
737 }
738
739 /*
740 * It is a fatal error if the memory reference for the wrap input vector is
741 * invalid or not readable.
742 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800743 FIH_CALL(tfm_hal_memory_check, fih_rc,
744 partition->boundary, (uintptr_t)handle->invec[invec_idx].base,
745 handle->invec[invec_idx].len, TFM_HAL_ACCESS_READABLE);
746 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800747 tfm_core_panic();
748 }
749
Mingyang Suna09adda2022-02-16 18:11:33 +0800750 SET_IOVEC_MAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800751
Mingyang Suna09adda2022-02-16 18:11:33 +0800752 return handle->invec[invec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +0800753}
754
755void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
756 uint32_t invec_idx)
757{
Mingyang Suna09adda2022-02-16 18:11:33 +0800758 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +0800759
760 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800761 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800762 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +0800763 tfm_core_panic();
764 }
765
766 /*
767 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
768 * Service that received the message.
769 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800770 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +0800771 tfm_core_panic();
772 }
773
774 /*
775 * It is a fatal error if message handle does not refer to a request
776 * message.
777 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800778 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800779 tfm_core_panic();
780 }
781
782 /*
783 * It is a fatal error if invec_idx is equal to or greater than
784 * PSA_MAX_IOVEC.
785 */
786 if (invec_idx >= PSA_MAX_IOVEC) {
787 tfm_core_panic();
788 }
789
790 /*
791 * It is a fatal error if The input vector has not been mapped by a call to
792 * psa_map_invec().
793 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800794 if (!IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800795 tfm_core_panic();
796 }
797
798 /*
799 * It is a fatal error if the input vector has already been unmapped by a
800 * call to psa_unmap_invec().
801 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800802 if (IOVEC_IS_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800803 tfm_core_panic();
804 }
805
Mingyang Suna09adda2022-02-16 18:11:33 +0800806 SET_IOVEC_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800807}
808
809void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
810 uint32_t outvec_idx)
811{
Mingyang Suna09adda2022-02-16 18:11:33 +0800812 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +0800813 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800814 fih_int fih_rc = FIH_FAILURE;
Shawn Shan038348e2021-09-08 17:11:04 +0800815
816 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800817 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800818 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +0800819 tfm_core_panic();
820 }
821
Mingyang Suna09adda2022-02-16 18:11:33 +0800822 partition = handle->service->partition;
Shawn Shan038348e2021-09-08 17:11:04 +0800823
824 /*
825 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
826 * Service that received the message.
827 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800828 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +0800829 tfm_core_panic();
830 }
831
832 /*
833 * It is a fatal error if message handle does not refer to a request
834 * message.
835 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800836 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800837 tfm_core_panic();
838 }
839
840 /*
841 * It is a fatal error if outvec_idx is equal to or greater than
842 * PSA_MAX_IOVEC.
843 */
844 if (outvec_idx >= PSA_MAX_IOVEC) {
845 tfm_core_panic();
846 }
847
848 /* It is a fatal error if the output vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800849 if (handle->msg.out_size[outvec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +0800850 tfm_core_panic();
851 }
852
853 /*
854 * It is a fatal error if the output vector has already been mapped using
855 * psa_map_outvec().
856 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800857 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800858 tfm_core_panic();
859 }
860
861 /*
862 * It is a fatal error if the output vector has already been accessed
863 * using psa_write().
864 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800865 if (IOVEC_IS_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800866 tfm_core_panic();
867 }
868
869 /*
870 * It is a fatal error if the output vector is invalid or not read-write.
871 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800872 FIH_CALL(tfm_hal_memory_check, fih_rc,
873 partition->boundary, (uintptr_t)handle->outvec[outvec_idx].base,
874 handle->outvec[outvec_idx].len, TFM_HAL_ACCESS_READWRITE);
875 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800876 tfm_core_panic();
877 }
Mingyang Suna09adda2022-02-16 18:11:33 +0800878 SET_IOVEC_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800879
Mingyang Suna09adda2022-02-16 18:11:33 +0800880 return handle->outvec[outvec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +0800881}
882
883void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
884 uint32_t outvec_idx, size_t len)
885{
Mingyang Suna09adda2022-02-16 18:11:33 +0800886 struct conn_handle_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +0800887
888 /* It is a fatal error if message handle is invalid */
Kevin Penge61e7052022-01-27 14:57:06 +0800889 handle = spm_get_handle_by_msg_handle(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800890 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +0800891 tfm_core_panic();
892 }
893
894 /*
895 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
896 * Service that received the message.
897 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800898 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +0800899 tfm_core_panic();
900 }
901
902 /*
903 * It is a fatal error if message handle does not refer to a request
904 * message.
905 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800906 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800907 tfm_core_panic();
908 }
909
910 /*
911 * It is a fatal error if outvec_idx is equal to or greater than
912 * PSA_MAX_IOVEC.
913 */
914 if (outvec_idx >= PSA_MAX_IOVEC) {
915 tfm_core_panic();
916 }
917
918 /*
919 * It is a fatal error if len is greater than the output vector size.
920 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800921 if (len > handle->msg.out_size[outvec_idx]) {
Shawn Shan038348e2021-09-08 17:11:04 +0800922 tfm_core_panic();
923 }
924
925 /*
926 * It is a fatal error if The output vector has not been mapped by a call to
927 * psa_map_outvec().
928 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800929 if (!IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800930 tfm_core_panic();
931 }
932
933 /*
934 * It is a fatal error if the output vector has already been unmapped by a
935 * call to psa_unmap_outvec().
936 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800937 if (IOVEC_IS_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800938 tfm_core_panic();
939 }
940
Mingyang Suna09adda2022-02-16 18:11:33 +0800941 SET_IOVEC_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800942
943 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +0800944 handle->outvec[outvec_idx].len = len;
Shawn Shan038348e2021-09-08 17:11:04 +0800945}
946
947#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */