blob: 1f1c715d9a71a5750a1e1ddd11170c3ed84ffc38 [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 /*
shejia0195a88bc2023-01-16 15:44:46 +0800139 * After new signal(s) are available, the return value will be updated in
140 * PendSV and blocked thread gets to run.
Mingyang Sunb26b2802021-07-07 11:25:00 +0800141 */
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800142 if (timeout == PSA_BLOCK) {
shejia0195a88bc2023-01-16 15:44:46 +0800143 return backend_wait_signals(partition, signal_mask);
144 } else {
145 return partition->signals_asserted & signal_mask;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800146 }
Mingyang Sunb26b2802021-07-07 11:25:00 +0800147}
Kevin Pengdef92de2021-11-10 16:14:48 +0800148#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800149
Kevin Pengdef92de2021-11-10 16:14:48 +0800150#if CONFIG_TFM_SPM_BACKEND_IPC == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800151psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg)
152{
Ken Liuc9313eb2023-02-22 15:45:54 +0800153 struct connection_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800154 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800155 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800156
157 /*
158 * Only one message could be retrieved every time for psa_get(). It is a
159 * fatal error if the input signal has more than a signal bit set.
160 */
161 if (!IS_ONLY_ONE_BIT_IN_UINT32(signal)) {
162 tfm_core_panic();
163 }
164
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800165 partition = GET_CURRENT_COMPONENT();
166
Mingyang Sunb26b2802021-07-07 11:25:00 +0800167 /*
168 * Write the message to the service buffer. It is a fatal error if the
169 * input msg pointer is not a valid memory reference or not read-write.
170 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800171 FIH_CALL(tfm_hal_memory_check, fih_rc,
172 partition->boundary, (uintptr_t)msg,
173 sizeof(psa_msg_t), TFM_HAL_ACCESS_READWRITE);
174 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800175 tfm_core_panic();
176 }
177
178 /*
179 * It is a fatal error if the caller call psa_get() when no message has
180 * been set. The caller must call this function after an RoT Service signal
181 * is returned by psa_wait().
182 */
183 if (partition->signals_asserted == 0) {
184 tfm_core_panic();
185 }
186
187 /*
188 * It is a fatal error if the RoT Service signal is not currently asserted.
189 */
190 if ((partition->signals_asserted & signal) == 0) {
191 tfm_core_panic();
192 }
193
194 /*
195 * Get message by signal from partition. It is a fatal error if getting
196 * failed, which means the input signal is not correspond to an RoT service.
197 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800198 handle = spm_get_handle_by_signal(partition, signal);
199 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800200 return PSA_ERROR_DOES_NOT_EXIST;
201 }
202
Mingyang Suna09adda2022-02-16 18:11:33 +0800203 spm_memcpy(msg, &handle->msg, sizeof(psa_msg_t));
Mingyang Sunb26b2802021-07-07 11:25:00 +0800204
205 return PSA_SUCCESS;
206}
Mingyang Sun4609ac72022-02-08 18:56:35 +0800207#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800208
Mingyang Sunb26b2802021-07-07 11:25:00 +0800209size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
210 void *buffer, size_t num_bytes)
211{
212 size_t bytes;
Ken Liuc9313eb2023-02-22 15:45:54 +0800213 struct connection_t *handle = NULL;
Summer Qin56725eb2022-05-06 15:23:40 +0800214 struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800215 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800216
217 /* It is a fatal error if message handle is invalid */
Ken Liuc9313eb2023-02-22 15:45:54 +0800218 handle = spm_msg_handle_to_connection(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800219 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800220 tfm_core_panic();
221 }
222
Mingyang Sunb26b2802021-07-07 11:25:00 +0800223 /*
224 * It is a fatal error if message handle does not refer to a request
225 * message
226 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800227 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800228 tfm_core_panic();
229 }
230
231 /*
232 * It is a fatal error if invec_idx is equal to or greater than
233 * PSA_MAX_IOVEC
234 */
235 if (invec_idx >= PSA_MAX_IOVEC) {
236 tfm_core_panic();
237 }
238
Shawn Shan038348e2021-09-08 17:11:04 +0800239#if PSA_FRAMEWORK_HAS_MM_IOVEC
240 /*
241 * It is a fatal error if the input vector has already been mapped using
242 * psa_map_invec().
243 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800244 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800245 tfm_core_panic();
246 }
247
Mingyang Suna09adda2022-02-16 18:11:33 +0800248 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800249#endif
250
Kevin Peng016b0e42022-04-15 11:28:48 +0800251 /* There was no remaining data in this input vector */
252 if (handle->msg.in_size[invec_idx] == 0) {
253 return 0;
254 }
255
Mingyang Sunb26b2802021-07-07 11:25:00 +0800256 /*
257 * Copy the client data to the service buffer. It is a fatal error
258 * if the memory reference for buffer is invalid or not read-write.
259 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800260 FIH_CALL(tfm_hal_memory_check, fih_rc,
261 curr_partition->boundary, (uintptr_t)buffer,
262 num_bytes, TFM_HAL_ACCESS_READWRITE);
263 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800264 tfm_core_panic();
265 }
266
Mingyang Suna09adda2022-02-16 18:11:33 +0800267 bytes = num_bytes > handle->msg.in_size[invec_idx] ?
268 handle->msg.in_size[invec_idx] : num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800269
Mingyang Suna09adda2022-02-16 18:11:33 +0800270 spm_memcpy(buffer, handle->invec[invec_idx].base, bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800271
272 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800273 handle->invec[invec_idx].base =
274 (char *)handle->invec[invec_idx].base + bytes;
275 handle->msg.in_size[invec_idx] -= bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800276
277 return bytes;
278}
279
280size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
281 size_t num_bytes)
282{
Ken Liuc9313eb2023-02-22 15:45:54 +0800283 struct connection_t *handle = NULL;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800284
285 /* It is a fatal error if message handle is invalid */
Ken Liuc9313eb2023-02-22 15:45:54 +0800286 handle = spm_msg_handle_to_connection(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800287 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800288 tfm_core_panic();
289 }
290
291 /*
292 * It is a fatal error if message handle does not refer to a request
293 * message
294 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800295 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800296 tfm_core_panic();
297 }
298
299 /*
300 * It is a fatal error if invec_idx is equal to or greater than
301 * PSA_MAX_IOVEC
302 */
303 if (invec_idx >= PSA_MAX_IOVEC) {
304 tfm_core_panic();
305 }
306
Shawn Shan038348e2021-09-08 17:11:04 +0800307#if PSA_FRAMEWORK_HAS_MM_IOVEC
308 /*
309 * It is a fatal error if the input vector has already been mapped using
310 * psa_map_invec().
311 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800312 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800313 tfm_core_panic();
314 }
315
Mingyang Suna09adda2022-02-16 18:11:33 +0800316 SET_IOVEC_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800317#endif
318
Kevin Peng016b0e42022-04-15 11:28:48 +0800319 /* There was no remaining data in this input vector */
320 if (handle->msg.in_size[invec_idx] == 0) {
321 return 0;
322 }
323
Mingyang Sunb26b2802021-07-07 11:25:00 +0800324 /*
325 * If num_bytes is greater than the remaining size of the input vector then
326 * the remaining size of the input vector is used.
327 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800328 if (num_bytes > handle->msg.in_size[invec_idx]) {
329 num_bytes = handle->msg.in_size[invec_idx];
Mingyang Sunb26b2802021-07-07 11:25:00 +0800330 }
331
332 /* There maybe some remaining data */
Mingyang Suna09adda2022-02-16 18:11:33 +0800333 handle->invec[invec_idx].base =
334 (char *)handle->invec[invec_idx].base + num_bytes;
335 handle->msg.in_size[invec_idx] -= num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800336
337 return num_bytes;
338}
339
340void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
341 const void *buffer, size_t num_bytes)
342{
Ken Liuc9313eb2023-02-22 15:45:54 +0800343 struct connection_t *handle = NULL;
Summer Qin56725eb2022-05-06 15:23:40 +0800344 struct partition_t *curr_partition = GET_CURRENT_COMPONENT();
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800345 fih_int fih_rc = FIH_FAILURE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800346
347 /* It is a fatal error if message handle is invalid */
Ken Liuc9313eb2023-02-22 15:45:54 +0800348 handle = spm_msg_handle_to_connection(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800349 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800350 tfm_core_panic();
351 }
352
Mingyang Sunb26b2802021-07-07 11:25:00 +0800353 /*
354 * It is a fatal error if message handle does not refer to a request
355 * message
356 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800357 if (handle->msg.type < PSA_IPC_CALL) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800358 tfm_core_panic();
359 }
360
361 /*
362 * It is a fatal error if outvec_idx is equal to or greater than
363 * PSA_MAX_IOVEC
364 */
365 if (outvec_idx >= PSA_MAX_IOVEC) {
366 tfm_core_panic();
367 }
368
369 /*
370 * It is a fatal error if the call attempts to write data past the end of
371 * the client output vector
372 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800373 if (num_bytes > handle->msg.out_size[outvec_idx] -
374 handle->outvec[outvec_idx].len) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800375 tfm_core_panic();
376 }
377
Shawn Shan038348e2021-09-08 17:11:04 +0800378#if PSA_FRAMEWORK_HAS_MM_IOVEC
379 /*
380 * It is a fatal error if the output vector has already been mapped using
381 * psa_map_outvec().
382 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800383 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800384 tfm_core_panic();
385 }
386
Mingyang Suna09adda2022-02-16 18:11:33 +0800387 SET_IOVEC_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800388#endif
389
Mingyang Sunb26b2802021-07-07 11:25:00 +0800390 /*
391 * Copy the service buffer to client outvecs. It is a fatal error
392 * if the memory reference for buffer is invalid or not readable.
393 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800394 FIH_CALL(tfm_hal_memory_check, fih_rc,
395 curr_partition->boundary, (uintptr_t)buffer,
396 num_bytes, TFM_HAL_ACCESS_READABLE);
397 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800398 tfm_core_panic();
399 }
400
Mingyang Suna09adda2022-02-16 18:11:33 +0800401 spm_memcpy((char *)handle->outvec[outvec_idx].base +
402 handle->outvec[outvec_idx].len, buffer, num_bytes);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800403
404 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +0800405 handle->outvec[outvec_idx].len += num_bytes;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800406}
407
Ken Liuf8c7e532022-02-10 15:03:04 +0800408psa_status_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
409 psa_status_t status)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800410{
Ken Liu0bed7e02022-02-10 12:38:07 +0800411 struct service_t *service;
Ken Liuc9313eb2023-02-22 15:45:54 +0800412 struct connection_t *handle;
Ken Liuf8c7e532022-02-10 15:03:04 +0800413 psa_status_t ret = PSA_SUCCESS;
Mingyang Sun620c8562021-11-10 11:44:58 +0800414 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800415
416 /* It is a fatal error if message handle is invalid */
Ken Liuc9313eb2023-02-22 15:45:54 +0800417 handle = spm_msg_handle_to_connection(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800418 if (!handle) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800419 tfm_core_panic();
420 }
421
422 /*
423 * RoT Service information is needed in this function, stored it in message
424 * body structure. Only two parameters are passed in this function: handle
425 * and status, so it is useful and simply to do like this.
426 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800427 service = handle->service;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800428 if (!service) {
429 tfm_core_panic();
430 }
431
Mingyang Suna09adda2022-02-16 18:11:33 +0800432 switch (handle->msg.type) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800433 case PSA_IPC_CONNECT:
434 /*
435 * Reply to PSA_IPC_CONNECT message. Connect handle is returned if the
436 * input status is PSA_SUCCESS. Others return values are based on the
437 * input status.
438 */
439 if (status == PSA_SUCCESS) {
440 ret = msg_handle;
441 } else if (status == PSA_ERROR_CONNECTION_REFUSED) {
442 /* Refuse the client connection, indicating a permanent error. */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800443 ret = PSA_ERROR_CONNECTION_REFUSED;
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800444 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800445 } else if (status == PSA_ERROR_CONNECTION_BUSY) {
446 /* Fail the client connection, indicating a transient error. */
447 ret = PSA_ERROR_CONNECTION_BUSY;
448 } else {
449 tfm_core_panic();
450 }
451 break;
452 case PSA_IPC_DISCONNECT:
453 /* Service handle is not used anymore */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800454 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800455
456 /*
457 * If the message type is PSA_IPC_DISCONNECT, then the status code is
458 * ignored
459 */
460 break;
461 default:
Mingyang Suna09adda2022-02-16 18:11:33 +0800462 if (handle->msg.type >= PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800463
464#if PSA_FRAMEWORK_HAS_MM_IOVEC
465
466 /*
467 * If the unmapped function is not called for an input/output vector
468 * that has been mapped, the framework will remove the mapping.
469 */
470 int i;
471
472 for (i = 0; i < PSA_MAX_IOVEC * 2; i++) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800473 if (IOVEC_IS_MAPPED(handle, i) &&
474 (!IOVEC_IS_UNMAPPED(handle, i))) {
475 SET_IOVEC_UNMAPPED(handle, i);
Shawn Shan038348e2021-09-08 17:11:04 +0800476 /*
477 * Any output vectors that are still mapped will report that
478 * zero bytes have been written.
479 */
480 if (i >= OUTVEC_IDX_BASE) {
Mingyang Suna09adda2022-02-16 18:11:33 +0800481 handle->outvec[i - OUTVEC_IDX_BASE].len = 0;
Shawn Shan038348e2021-09-08 17:11:04 +0800482 }
483 }
484 }
485
486#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800487 /* Reply to a request message. Return values are based on status */
488 ret = status;
489 /*
490 * The total number of bytes written to a single parameter must be
491 * reported to the client by updating the len member of the
492 * psa_outvec structure for the parameter before returning from
493 * psa_call().
494 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800495 update_caller_outvec_len(handle);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800496 if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800497 handle->status = TFM_HANDLE_STATUS_TO_FREE;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800498 }
499 } else {
500 tfm_core_panic();
501 }
502 }
503
504 if (ret == PSA_ERROR_PROGRAMMER_ERROR) {
505 /*
506 * If the source of the programmer error is a Secure Partition, the SPM
507 * must panic the Secure Partition in response to a PROGRAMMER ERROR.
508 */
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800509 if (!TFM_CLIENT_ID_IS_NS(handle->msg.client_id)) {
Mingyang Sunb26b2802021-07-07 11:25:00 +0800510 tfm_core_panic();
511 }
Mingyang Sunb26b2802021-07-07 11:25:00 +0800512 }
513
Mingyang Sun620c8562021-11-10 11:44:58 +0800514 /*
515 * TODO: It can be optimized further by moving critical section protection
516 * to mailbox. Also need to check implementation when secure context is
517 * involved.
518 */
519 CRITICAL_SECTION_ENTER(cs_assert);
Ken Liu995a9742022-05-18 19:28:30 +0800520 ret = backend_replying(handle, ret);
Mingyang Sun620c8562021-11-10 11:44:58 +0800521 CRITICAL_SECTION_LEAVE(cs_assert);
522
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800523 if (handle->status == TFM_HANDLE_STATUS_TO_FREE) {
Ken Liuc9313eb2023-02-22 15:45:54 +0800524 spm_free_connection(handle);
Mingyang Sunaeca8e02022-02-24 14:47:56 +0800525 } else {
526 handle->status = TFM_HANDLE_STATUS_IDLE;
527 }
528
Mingyang Sun620c8562021-11-10 11:44:58 +0800529 return ret;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800530}
531
Kevin Peng613b4172022-02-15 14:41:44 +0800532#if CONFIG_TFM_DOORBELL_API == 1
Jianliang Shenbd8c7c92023-03-03 16:07:42 +0100533void tfm_spm_partition_psa_notify(int32_t partition_id)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800534{
Ken Liu5d73c872021-08-19 19:23:17 +0800535 struct partition_t *p_pt = tfm_spm_get_partition_by_id(partition_id);
536
Jianliang Shenbd8c7c92023-03-03 16:07:42 +0100537 backend_assert_signal(p_pt, PSA_DOORBELL);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800538}
539
540void tfm_spm_partition_psa_clear(void)
541{
Ken Liu92ede9f2021-10-20 09:35:00 +0800542 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800543 struct partition_t *partition = NULL;
544
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800545 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800546
547 /*
548 * It is a fatal error if the Secure Partition's doorbell signal is not
549 * currently asserted.
550 */
551 if ((partition->signals_asserted & PSA_DOORBELL) == 0) {
552 tfm_core_panic();
553 }
Ken Liu92ede9f2021-10-20 09:35:00 +0800554
555 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800556 partition->signals_asserted &= ~PSA_DOORBELL;
Ken Liu92ede9f2021-10-20 09:35:00 +0800557 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800558}
Kevin Peng613b4172022-02-15 14:41:44 +0800559#endif /* CONFIG_TFM_DOORBELL_API == 1 */
Mingyang Sunb26b2802021-07-07 11:25:00 +0800560
Mingyang Sunb26b2802021-07-07 11:25:00 +0800561void tfm_spm_partition_psa_panic(void)
562{
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100563#ifdef CONFIG_TFM_HALT_ON_CORE_PANIC
564 tfm_hal_system_halt();
565#else
Mingyang Sunb26b2802021-07-07 11:25:00 +0800566 /*
567 * PSA FF recommends that the SPM causes the system to restart when a secure
568 * partition panics.
569 */
570 tfm_hal_system_reset();
Joakim Andersson97cef7e2022-03-18 10:22:00 +0100571#endif
Mingyang Sunb26b2802021-07-07 11:25:00 +0800572}
573
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800574#if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
Kevin Peng67a89fd2021-11-25 11:22:02 +0800575void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800576{
577 struct partition_t *partition;
Chris Brand10a2acb2022-10-18 17:12:27 -0700578 const struct irq_load_info_t *irq_info;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800579
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800580 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800581
582 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
583 if (!irq_info) {
584 tfm_core_panic();
585 }
586
Kevin Pengd399a1f2021-09-08 15:33:14 +0800587 tfm_hal_irq_enable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800588}
589
Kevin Peng67a89fd2021-11-25 11:22:02 +0800590psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal)
Mingyang Sunb26b2802021-07-07 11:25:00 +0800591{
592 struct partition_t *partition;
Chris Brand10a2acb2022-10-18 17:12:27 -0700593 const struct irq_load_info_t *irq_info;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800594
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800595 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800596
597 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
598 if (!irq_info) {
599 tfm_core_panic();
600 }
601
Kevin Pengd399a1f2021-09-08 15:33:14 +0800602 tfm_hal_irq_disable(irq_info->source);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800603
604 return 1;
605}
606
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800607/* This API is only used for FLIH. */
608#if CONFIG_TFM_FLIH_API == 1
Mingyang Sunb26b2802021-07-07 11:25:00 +0800609void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal)
610{
Ken Liu92ede9f2021-10-20 09:35:00 +0800611 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Chris Brand10a2acb2022-10-18 17:12:27 -0700612 const struct irq_load_info_t *irq_info;
Mingyang Sunb26b2802021-07-07 11:25:00 +0800613 struct partition_t *partition;
614
Kevin Pengcdf3ae22022-01-19 14:53:52 +0800615 partition = GET_CURRENT_COMPONENT();
Mingyang Sunb26b2802021-07-07 11:25:00 +0800616
617 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
618 if (!irq_info) {
619 tfm_core_panic();
620 }
621
622 if (!irq_info->flih_func) {
623 /* This API is for FLIH IRQs only */
624 tfm_core_panic();
625 }
626
627 if ((partition->signals_asserted & irq_signal) == 0) {
628 /* The signal is not asserted */
629 tfm_core_panic();
630 }
631
Ken Liu92ede9f2021-10-20 09:35:00 +0800632 CRITICAL_SECTION_ENTER(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800633 partition->signals_asserted &= ~irq_signal;
Ken Liu92ede9f2021-10-20 09:35:00 +0800634 CRITICAL_SECTION_LEAVE(cs_assert);
Mingyang Sunb26b2802021-07-07 11:25:00 +0800635}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800636#endif
Shawn Shan038348e2021-09-08 17:11:04 +0800637
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800638/* This API is only used for SLIH. */
639#if CONFIG_TFM_SLIH_API == 1
640void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal)
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800641{
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800642 struct critical_section_t cs_assert = CRITICAL_SECTION_STATIC_INIT;
Chris Brand10a2acb2022-10-18 17:12:27 -0700643 const struct irq_load_info_t *irq_info = NULL;
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800644 struct partition_t *partition = NULL;
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800645
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800646 partition = GET_CURRENT_COMPONENT();
647
648 irq_info = get_irq_info_for_signal(partition->p_ldinf, irq_signal);
649 /* It is a fatal error if passed signal is not an interrupt signal. */
650 if (!irq_info) {
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800651 tfm_core_panic();
652 }
653
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800654 if (irq_info->flih_func) {
655 /* This API is for SLIH IRQs only */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800656 tfm_core_panic();
657 }
658
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800659 /* It is a fatal error if passed signal is not currently asserted */
660 if ((partition->signals_asserted & irq_signal) == 0) {
661 tfm_core_panic();
662 }
663
664 CRITICAL_SECTION_ENTER(cs_assert);
665 partition->signals_asserted &= ~irq_signal;
666 CRITICAL_SECTION_LEAVE(cs_assert);
667
668 tfm_hal_irq_clear_pending(irq_info->source);
669 tfm_hal_irq_enable(irq_info->source);
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800670}
Mingyang Suned5fe7b2022-02-10 17:33:21 +0800671#endif
672#endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
Xinyu Zhang2bc4d572021-12-27 16:37:46 +0800673
Shawn Shan038348e2021-09-08 17:11:04 +0800674#if PSA_FRAMEWORK_HAS_MM_IOVEC
675
676const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
677 uint32_t invec_idx)
678{
Ken Liuc9313eb2023-02-22 15:45:54 +0800679 struct connection_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +0800680 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800681 fih_int fih_rc = FIH_FAILURE;
Shawn Shan038348e2021-09-08 17:11:04 +0800682
683 /* It is a fatal error if message handle is invalid */
Ken Liuc9313eb2023-02-22 15:45:54 +0800684 handle = spm_msg_handle_to_connection(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800685 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +0800686 tfm_core_panic();
687 }
688
Mingyang Suna09adda2022-02-16 18:11:33 +0800689 partition = handle->service->partition;
Shawn Shan038348e2021-09-08 17:11:04 +0800690
691 /*
692 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
693 * Service that received the message.
694 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800695 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +0800696 tfm_core_panic();
697 }
698
699 /*
700 * It is a fatal error if message handle does not refer to a request
701 * message.
702 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800703 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800704 tfm_core_panic();
705 }
706
707 /*
708 * It is a fatal error if invec_idx is equal to or greater than
709 * PSA_MAX_IOVEC.
710 */
711 if (invec_idx >= PSA_MAX_IOVEC) {
712 tfm_core_panic();
713 }
714
715 /* It is a fatal error if the input vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800716 if (handle->msg.in_size[invec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +0800717 tfm_core_panic();
718 }
719
720 /*
721 * It is a fatal error if the input vector has already been mapped using
722 * psa_map_invec().
723 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800724 if (IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800725 tfm_core_panic();
726 }
727
728 /*
729 * It is a fatal error if the input vector has already been accessed
730 * using psa_read() or psa_skip().
731 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800732 if (IOVEC_IS_ACCESSED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800733 tfm_core_panic();
734 }
735
736 /*
737 * It is a fatal error if the memory reference for the wrap input vector is
738 * invalid or not readable.
739 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800740 FIH_CALL(tfm_hal_memory_check, fih_rc,
741 partition->boundary, (uintptr_t)handle->invec[invec_idx].base,
742 handle->invec[invec_idx].len, TFM_HAL_ACCESS_READABLE);
743 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800744 tfm_core_panic();
745 }
746
Mingyang Suna09adda2022-02-16 18:11:33 +0800747 SET_IOVEC_MAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800748
Mingyang Suna09adda2022-02-16 18:11:33 +0800749 return handle->invec[invec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +0800750}
751
752void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
753 uint32_t invec_idx)
754{
Ken Liuc9313eb2023-02-22 15:45:54 +0800755 struct connection_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +0800756
757 /* It is a fatal error if message handle is invalid */
Ken Liuc9313eb2023-02-22 15:45:54 +0800758 handle = spm_msg_handle_to_connection(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800759 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +0800760 tfm_core_panic();
761 }
762
763 /*
764 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
765 * Service that received the message.
766 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800767 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +0800768 tfm_core_panic();
769 }
770
771 /*
772 * It is a fatal error if message handle does not refer to a request
773 * message.
774 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800775 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800776 tfm_core_panic();
777 }
778
779 /*
780 * It is a fatal error if invec_idx is equal to or greater than
781 * PSA_MAX_IOVEC.
782 */
783 if (invec_idx >= PSA_MAX_IOVEC) {
784 tfm_core_panic();
785 }
786
787 /*
788 * It is a fatal error if The input vector has not been mapped by a call to
789 * psa_map_invec().
790 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800791 if (!IOVEC_IS_MAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800792 tfm_core_panic();
793 }
794
795 /*
796 * It is a fatal error if the input vector has already been unmapped by a
797 * call to psa_unmap_invec().
798 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800799 if (IOVEC_IS_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800800 tfm_core_panic();
801 }
802
Mingyang Suna09adda2022-02-16 18:11:33 +0800803 SET_IOVEC_UNMAPPED(handle, (invec_idx + INVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800804}
805
806void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
807 uint32_t outvec_idx)
808{
Ken Liuc9313eb2023-02-22 15:45:54 +0800809 struct connection_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +0800810 struct partition_t *partition = NULL;
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800811 fih_int fih_rc = FIH_FAILURE;
Shawn Shan038348e2021-09-08 17:11:04 +0800812
813 /* It is a fatal error if message handle is invalid */
Ken Liuc9313eb2023-02-22 15:45:54 +0800814 handle = spm_msg_handle_to_connection(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800815 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +0800816 tfm_core_panic();
817 }
818
Mingyang Suna09adda2022-02-16 18:11:33 +0800819 partition = handle->service->partition;
Shawn Shan038348e2021-09-08 17:11:04 +0800820
821 /*
822 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
823 * Service that received the message.
824 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800825 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +0800826 tfm_core_panic();
827 }
828
829 /*
830 * It is a fatal error if message handle does not refer to a request
831 * message.
832 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800833 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800834 tfm_core_panic();
835 }
836
837 /*
838 * It is a fatal error if outvec_idx is equal to or greater than
839 * PSA_MAX_IOVEC.
840 */
841 if (outvec_idx >= PSA_MAX_IOVEC) {
842 tfm_core_panic();
843 }
844
845 /* It is a fatal error if the output vector has length zero. */
Mingyang Suna09adda2022-02-16 18:11:33 +0800846 if (handle->msg.out_size[outvec_idx] == 0) {
Shawn Shan038348e2021-09-08 17:11:04 +0800847 tfm_core_panic();
848 }
849
850 /*
851 * It is a fatal error if the output vector has already been mapped using
852 * psa_map_outvec().
853 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800854 if (IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800855 tfm_core_panic();
856 }
857
858 /*
859 * It is a fatal error if the output vector has already been accessed
860 * using psa_write().
861 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800862 if (IOVEC_IS_ACCESSED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800863 tfm_core_panic();
864 }
865
866 /*
867 * It is a fatal error if the output vector is invalid or not read-write.
868 */
Xinyu Zhang6ad07032022-08-10 14:45:56 +0800869 FIH_CALL(tfm_hal_memory_check, fih_rc,
870 partition->boundary, (uintptr_t)handle->outvec[outvec_idx].base,
871 handle->outvec[outvec_idx].len, TFM_HAL_ACCESS_READWRITE);
872 if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800873 tfm_core_panic();
874 }
Mingyang Suna09adda2022-02-16 18:11:33 +0800875 SET_IOVEC_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800876
Mingyang Suna09adda2022-02-16 18:11:33 +0800877 return handle->outvec[outvec_idx].base;
Shawn Shan038348e2021-09-08 17:11:04 +0800878}
879
880void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
881 uint32_t outvec_idx, size_t len)
882{
Ken Liuc9313eb2023-02-22 15:45:54 +0800883 struct connection_t *handle;
Shawn Shan038348e2021-09-08 17:11:04 +0800884
885 /* It is a fatal error if message handle is invalid */
Ken Liuc9313eb2023-02-22 15:45:54 +0800886 handle = spm_msg_handle_to_connection(msg_handle);
Mingyang Suna09adda2022-02-16 18:11:33 +0800887 if (!handle) {
Shawn Shan038348e2021-09-08 17:11:04 +0800888 tfm_core_panic();
889 }
890
891 /*
892 * It is a fatal error if MM-IOVEC has not been enabled for the RoT
893 * Service that received the message.
894 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800895 if (!SERVICE_ENABLED_MM_IOVEC(handle->service->p_ldinf->flags)) {
Shawn Shan038348e2021-09-08 17:11:04 +0800896 tfm_core_panic();
897 }
898
899 /*
900 * It is a fatal error if message handle does not refer to a request
901 * message.
902 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800903 if (handle->msg.type < PSA_IPC_CALL) {
Shawn Shan038348e2021-09-08 17:11:04 +0800904 tfm_core_panic();
905 }
906
907 /*
908 * It is a fatal error if outvec_idx is equal to or greater than
909 * PSA_MAX_IOVEC.
910 */
911 if (outvec_idx >= PSA_MAX_IOVEC) {
912 tfm_core_panic();
913 }
914
915 /*
916 * It is a fatal error if len is greater than the output vector size.
917 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800918 if (len > handle->msg.out_size[outvec_idx]) {
Shawn Shan038348e2021-09-08 17:11:04 +0800919 tfm_core_panic();
920 }
921
922 /*
923 * It is a fatal error if The output vector has not been mapped by a call to
924 * psa_map_outvec().
925 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800926 if (!IOVEC_IS_MAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800927 tfm_core_panic();
928 }
929
930 /*
931 * It is a fatal error if the output vector has already been unmapped by a
932 * call to psa_unmap_outvec().
933 */
Mingyang Suna09adda2022-02-16 18:11:33 +0800934 if (IOVEC_IS_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE))) {
Shawn Shan038348e2021-09-08 17:11:04 +0800935 tfm_core_panic();
936 }
937
Mingyang Suna09adda2022-02-16 18:11:33 +0800938 SET_IOVEC_UNMAPPED(handle, (outvec_idx + OUTVEC_IDX_BASE));
Shawn Shan038348e2021-09-08 17:11:04 +0800939
940 /* Update the write number */
Mingyang Suna09adda2022-02-16 18:11:33 +0800941 handle->outvec[outvec_idx].len = len;
Shawn Shan038348e2021-09-08 17:11:04 +0800942}
943
944#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */