1 /*
2  * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #ifndef __PSA_API_H__
9 #define __PSA_API_H__
10 
11 #include <stdint.h>
12 #include <stdbool.h>
13 #include "config_spm.h"
14 #ifdef TFM_PARTITION_NS_AGENT_MAILBOX
15 #include "ffm/mailbox_agent_api.h"
16 #endif
17 #include "psa/client.h"
18 #include "psa/service.h"
19 
20 #if PSA_FRAMEWORK_HAS_MM_IOVEC
21 
22 /*
23  * The MM-IOVEC status
24  * The max total number of invec and outvec is 8.
25  * Each invec/outvec takes 4 bit, 32 bits in total.
26  *
27  * The encoding format of the MM-IOVEC status:
28  *--------------------------------------------------------------
29  *|  Bit   |  31 - 28  |  27 - 24  | ... |  7 - 4   |  3 - 0   |
30  *--------------------------------------------------------------
31  *| Vector | outvec[3] | outvec[2] | ... | invec[1] | invec[0] |
32  *--------------------------------------------------------------
33  *
34  * Take invec[0] as an example:
35  *
36  * bit 0:  whether invec[0] has been mapped.
37  * bit 1:  whether invec[0] has been unmapped.
38  * bit 2:  whether invec[0] has been accessed using psa_read(), psa_skip() or
39  *         psa_write().
40  * bit 3:  reserved for invec[0].
41  */
42 
43 #define IOVEC_STATUS_BITS              4   /* Each vector occupies 4 bits. */
44 #define OUTVEC_IDX_BASE                4   /*
45                                             * Base index of outvec.
46                                             * There are four invecs in front of
47                                             * outvec.
48                                             */
49 #define INVEC_IDX_BASE                 0   /* Base index of invec. */
50 
51 #define IOVEC_MAPPED_BIT               (1UL << 0)
52 #define IOVEC_UNMAPPED_BIT             (1UL << 1)
53 #define IOVEC_ACCESSED_BIT             (1UL << 2)
54 
55 #define IOVEC_IS_MAPPED(handle, iovec_idx)      \
56     ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) &  \
57                                IOVEC_MAPPED_BIT)
58 #define IOVEC_IS_UNMAPPED(handle, iovec_idx)    \
59     ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) &  \
60                                IOVEC_UNMAPPED_BIT)
61 #define IOVEC_IS_ACCESSED(handle, iovec_idx)    \
62     ((((handle)->iovec_status) >> ((iovec_idx) * IOVEC_STATUS_BITS)) &  \
63                                IOVEC_ACCESSED_BIT)
64 #define SET_IOVEC_MAPPED(handle, iovec_idx)     \
65     (((handle)->iovec_status) |= (IOVEC_MAPPED_BIT <<   \
66                               ((iovec_idx) * IOVEC_STATUS_BITS)))
67 #define SET_IOVEC_UNMAPPED(handle, iovec_idx)   \
68     (((handle)->iovec_status) |= (IOVEC_UNMAPPED_BIT << \
69                               ((iovec_idx) * IOVEC_STATUS_BITS)))
70 #define SET_IOVEC_ACCESSED(handle, iovec_idx)   \
71     (((handle)->iovec_status) |= (IOVEC_ACCESSED_BIT << \
72                               ((iovec_idx) * IOVEC_STATUS_BITS)))
73 
74 #endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
75 
76 #ifdef TFM_PARTITION_NS_AGENT_MAILBOX
77 /**
78  * \brief handler for \ref agent_psa_call.
79  *
80  * \param[in] handle                 Handle to the service being accessed.
81  * \param[in] control                A composited uint32_t value for controlling purpose,
82  *                                   containing call types, numbers of in/out vectors and
83  *                                   attributes of vectors.
84  * \param[in] params                 Combines the psa_invec and psa_outvec params
85  *                                   for the psa_call() to be made, as well as
86  *                                   NS agent's client identifier, which is ignored
87  *                                   for connection-based services.
88  * \param[in] client_data_stateless  Client data, treated as opaque by SPM.
89  *
90  * \retval PSA_SUCCESS               Success.
91  * \retval "Does not return"         The call is invalid, one or more of the
92  *                                   following are true:
93  * \arg                                An invalid handle was passed.
94  * \arg                                The connection is already handling a request.
95  * \arg                                An invalid memory reference was provided.
96  * \arg                                in_num + out_num > PSA_MAX_IOVEC.
97  * \arg                                The message is unrecognized by the RoT
98  *                                     Service or incorrectly formatted.
99  */
100 psa_status_t tfm_spm_agent_psa_call(psa_handle_t handle,
101                                     uint32_t control,
102                                     const struct client_params_t *params,
103                                     const void *client_data_stateless);
104 
105 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
106 
107 /**
108  * \brief handler for \ref agent_psa_connect.
109  *
110  * \param[in] sid               RoT Service identity.
111  * \param[in] version           The version of the RoT Service.
112  * \param[in] ns_client_id      NS agent's client identifier.
113  * \param[in] client_data       Client data, treated as opaque by SPM.
114  *
115  * \retval PSA_SUCCESS          Success.
116  * \retval PSA_ERROR_CONNECTION_REFUSED The SPM or RoT Service has refused the
117  *                              connection.
118  * \retval PSA_ERROR_CONNECTION_BUSY The SPM or RoT Service cannot make the
119  *                              connection at the moment.
120  * \retval "Does not return"    The RoT Service ID and version are not
121  *                              supported, or the caller is not permitted to
122  *                              access the service.
123  */
124 psa_handle_t tfm_spm_agent_psa_connect(uint32_t sid, uint32_t version,
125                                        int32_t ns_client_id,
126                                        const void *client_data);
127 
128 /**
129  * \brief handler for \ref agent_psa_close.
130  *
131  * \param[in] handle            Service handle to the connection to be closed,
132  * \param[in] ns_client_id      NS agent's client identifier.
133  *
134  * \retval PSA_SUCCESS          Success.
135  * \retval PSA_ERROR_PROGRAMMER_ERROR The call is invalid, one or more of the
136  *                              following are true:
137  * \arg                           Called with a stateless handle.
138  * \arg                           An invalid handle was provided that is not
139  *                                the null handle.
140  * \arg                           The connection is handling a request.
141  */
142 psa_status_t tfm_spm_agent_psa_close(psa_handle_t handle, int32_t ns_client_id);
143 
144 #else /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1 */
145 #define tfm_spm_agent_psa_connect           NULL
146 #define tfm_spm_agent_psa_close             NULL
147 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1 */
148 #else /* TFM_PARTITION_NS_AGENT_MAILBOX */
149 #define tfm_spm_agent_psa_connect           NULL
150 #define tfm_spm_agent_psa_close             NULL
151 #define tfm_spm_agent_psa_call              NULL
152 #endif /* TFM_PARTITION_NS_AGENT_MAILBOX */
153 
154 /**
155  * \brief This function handles the specific programmer error cases.
156  *
157  * \param[in] status            Standard error codes for the SPM.
158  *
159  * \retval void                 Status will not cause SPM panic
160  * \retval "SPM panic"          Following programmer errors are triggered by SP:
161  * \arg                           PSA_ERROR_PROGRAMMER_ERROR
162  * \arg                           PSA_ERROR_CONNECTION_REFUSED
163  * \arg                           PSA_ERROR_CONNECTION_BUSY
164  */
165 void spm_handle_programmer_errors(psa_status_t status);
166 
167 /**
168  * \brief This function get the current PSA RoT lifecycle state.
169  *
170  * \return state                The current security lifecycle state of the PSA
171  *                              RoT. The PSA state and implementation state are
172  *                              encoded as follows:
173  * \arg                           state[15:8] – PSA lifecycle state
174  * \arg                           state[7:0] – IMPLEMENTATION DEFINED state
175  */
176 uint32_t tfm_spm_get_lifecycle_state(void);
177 
178 /* PSA Client API function body, for privileged use only. */
179 
180 /**
181  * \brief handler for \ref psa_framework_version.
182  *
183  * \return version              The version of the PSA Framework implementation
184  *                              that is providing the runtime services.
185  */
186 uint32_t tfm_spm_client_psa_framework_version(void);
187 
188 /**
189  * \brief handler for \ref psa_version.
190  *
191  * \param[in] sid               RoT Service identity.
192  *
193  * \retval PSA_VERSION_NONE     The RoT Service is not implemented, or the
194  *                              caller is not permitted to access the service.
195  * \retval > 0                  The version of the implemented RoT Service.
196  */
197 uint32_t tfm_spm_client_psa_version(uint32_t sid);
198 
199 /**
200  * \brief handler for \ref psa_call.
201  *
202  * \param[in] handle            Service handle to the established connection,
203  *                              \ref psa_handle_t
204  * \param[in] ctrl_param        Parameters combined in uint32_t,
205  *                              includes request type, in_num and out_num.
206  * \param[in] inptr             Array of input psa_invec structures.
207  *                              \ref psa_invec
208  * \param[in] outptr            Array of output psa_outvec structures.
209  *                              \ref psa_outvec
210  *
211  * \retval PSA_SUCCESS          Success.
212  * \retval "Does not return"    The call is invalid, one or more of the
213  *                              following are true:
214  * \arg                           An invalid handle was passed.
215  * \arg                           The connection is already handling a request.
216  * \arg                           An invalid memory reference was provided.
217  * \arg                           in_num + out_num > PSA_MAX_IOVEC.
218  * \arg                           The message is unrecognized by the RoT
219  *                                Service or incorrectly formatted.
220  */
221 psa_status_t tfm_spm_client_psa_call(psa_handle_t handle,
222                                      uint32_t ctrl_param,
223                                      const psa_invec *inptr,
224                                      psa_outvec *outptr);
225 
226 /* Following PSA APIs are only needed by connection-based services */
227 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
228 
229 /**
230  * \brief handler for \ref psa_connect.
231  *
232  * \param[in] sid               RoT Service identity.
233  * \param[in] version           The version of the RoT Service.
234  *
235  * \retval PSA_SUCCESS          Success.
236  * \retval PSA_ERROR_CONNECTION_REFUSED The SPM or RoT Service has refused the
237  *                              connection.
238  * \retval PSA_ERROR_CONNECTION_BUSY The SPM or RoT Service cannot make the
239  *                              connection at the moment.
240  * \retval "Does not return"    The RoT Service ID and version are not
241  *                              supported, or the caller is not permitted to
242  *                              access the service.
243  */
244 psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version);
245 
246 /**
247  * \brief handler for \ref psa_close.
248  *
249  * \param[in] handle            Service handle to the connection to be closed,
250  *                              \ref psa_handle_t
251  *
252  * \retval PSA_SUCCESS          Success.
253  * \retval PSA_ERROR_PROGRAMMER_ERROR The call is invalid, one or more of the
254  *                              following are true:
255  * \arg                           Called with a stateless handle.
256  * \arg                           An invalid handle was provided that is not
257  *                                the null handle.
258  * \arg                           The connection is handling a request.
259  */
260 psa_status_t tfm_spm_client_psa_close(psa_handle_t handle);
261 #else
262 #define tfm_spm_client_psa_connect      NULL
263 #define tfm_spm_client_psa_close        NULL
264 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
265 
266 /* PSA Partition API function body, for privileged use only. */
267 
268 #if CONFIG_TFM_SPM_BACKEND_IPC == 1 \
269     || CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
270 /**
271  * \brief Function body of \ref psa_wait.
272  *
273  * \param[in] signal_mask       A set of signals to query. Signals that are not
274  *                              in this set will be ignored.
275  * \param[in] timeout           Specify either blocking \ref PSA_BLOCK or
276  *                              polling \ref PSA_POLL operation.
277  *
278  * \retval >0                   At least one signal is asserted.
279  * \retval 0                    No signals are asserted. This is only seen when
280  *                              a polling timeout is used.
281  */
282 psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
283                                         uint32_t timeout);
284 #endif
285 
286 /* This API is only used in IPC backend. */
287 #if CONFIG_TFM_SPM_BACKEND_IPC == 1
288 /**
289  * \brief Function body of \ref psa_get.
290  *
291  * \param[in] signal            The signal value for an asserted RoT Service.
292  * \param[out] msg              Pointer to \ref psa_msg_t object for receiving
293  *                              the message.
294  *
295  * \retval PSA_SUCCESS          Success, *msg will contain the delivered
296  *                              message.
297  * \retval PSA_ERROR_DOES_NOT_EXIST Message could not be delivered.
298  * \retval "PROGRAMMER ERROR"   The call is invalid because one or more of the
299  *                              following are true:
300  * \arg                           signal has more than a single bit set.
301  * \arg                           signal does not correspond to an RoT Service.
302  * \arg                           The RoT Service signal is not currently
303  *                                asserted.
304  * \arg                           The msg pointer provided is not a valid memory
305  *                                reference.
306  */
307 psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg);
308 #endif /* CONFIG_TFM_SPM_BACKEND_IPC == 1 */
309 
310 /**
311  * \brief Function body of \ref psa_read.
312  *
313  * \param[in] msg_handle        Handle for the client's message.
314  * \param[in] invec_idx         Index of the input vector to read from. Must be
315  *                              less than \ref PSA_MAX_IOVEC.
316  * \param[out] buffer           Buffer in the Secure Partition to copy the
317  *                              requested data to.
318  * \param[in] num_bytes         Maximum number of bytes to be read from the
319  *                              client input vector.
320  *
321  * \retval >0                   Number of bytes copied.
322  * \retval 0                    There was no remaining data in this input
323  *                              vector.
324  * \retval "PROGRAMMER ERROR"   The call is invalid, one or more of the
325  *                              following are true:
326  * \arg                           msg_handle is invalid.
327  * \arg                           msg_handle does not refer to a
328  *                                \ref PSA_IPC_CALL message.
329  * \arg                           invec_idx is equal to or greater than
330  *                                \ref PSA_MAX_IOVEC.
331  * \arg                           the memory reference for buffer is invalid or
332  *                                not writable.
333  */
334 size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
335                                   void *buffer, size_t num_bytes);
336 
337 /**
338  * \brief Function body of psa_skip.
339  *
340  * \param[in] msg_handle        Handle for the client's message.
341  * \param[in] invec_idx         Index of input vector to skip from. Must be
342  *                              less than \ref PSA_MAX_IOVEC.
343  * \param[in] num_bytes         Maximum number of bytes to skip in the client
344  *                              input vector.
345  *
346  * \retval >0                   Number of bytes skipped.
347  * \retval 0                    There was no remaining data in this input
348  *                              vector.
349  * \retval "PROGRAMMER ERROR"   The call is invalid, one or more of the
350  *                              following are true:
351  * \arg                           msg_handle is invalid.
352  * \arg                           msg_handle does not refer to a request
353  *                                message.
354  * \arg                           invec_idx is equal to or greater than
355  *                                \ref PSA_MAX_IOVEC.
356  */
357 size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
358                                   size_t num_bytes);
359 
360 /**
361  * \brief Function body of \ref psa_write.
362  *
363  * \param[in] msg_handle        Handle for the client's message.
364  * \param[out] outvec_idx       Index of output vector in message to write to.
365  *                              Must be less than \ref PSA_MAX_IOVEC.
366  * \param[in] buffer            Buffer with the data to write.
367  * \param[in] num_bytes         Number of bytes to write to the client output
368  *                              vector.
369  *
370  * \retval PSA_SUCCESS          Success.
371  * \retval "PROGRAMMER ERROR"   The call is invalid, one or more of the
372  *                              following are true:
373  * \arg                           msg_handle is invalid.
374  * \arg                           msg_handle does not refer to a request
375  *                                message.
376  * \arg                           outvec_idx is equal to or greater than
377  *                                \ref PSA_MAX_IOVEC.
378  * \arg                           The memory reference for buffer is invalid.
379  * \arg                           The call attempts to write data past the end
380  *                                of the client output vector.
381  */
382 psa_status_t tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
383                                          const void *buffer, size_t num_bytes);
384 
385 /**
386  * \brief Function body of \ref psa_reply.
387  *
388  * \param[in] msg_handle        Handle for the client's message.
389  * \param[in] status            Message result value to be reported to the
390  *                              client.
391  *
392  * \retval Positive integer     Success, the connection handle.
393  * \retval PSA_SUCCESS          Success
394  * \retval "PROGRAMMER ERROR"   The call is invalid, one or more of the
395  *                              following are true:
396  * \arg                         msg_handle is invalid.
397  * \arg                         An invalid status code is specified for the
398  *                              type of message.
399  */
400 int32_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
401                                     psa_status_t status);
402 
403 #if CONFIG_TFM_DOORBELL_API == 1
404 /**
405  * \brief Function body of \ref psa_norify.
406  *
407  * \param[in] partition_id      Secure Partition ID of the target partition.
408  *
409  * \retval PSA_SUCCESS          Success.
410  * \retval PSA_NEED_SCHEDULE    Require schedule thread.
411  * \retval "PROGRAMMER ERROR"   partition_id does not correspond to a Secure
412  *                              Partition.
413  */
414 psa_status_t tfm_spm_partition_psa_notify(int32_t partition_id);
415 
416 /**
417  * \brief Function body of \ref psa_clear.
418  *
419  * \retval PSA_SUCCESS          Success.
420  * \retval "PROGRAMMER ERROR"   The Secure Partition's doorbell signal is not
421  *                              currently asserted.
422  */
423 psa_status_t tfm_spm_partition_psa_clear(void);
424 #else
425 #define tfm_spm_partition_psa_notify    NULL
426 #define tfm_spm_partition_psa_clear     NULL
427 #endif /* CONFIG_TFM_DOORBELL_API == 1 */
428 
429 /**
430  * \brief Function body of \ref psa_panic.
431  *
432  * \retval "Should not return"
433  */
434 psa_status_t tfm_spm_partition_psa_panic(void);
435 
436 /* psa_set_rhandle is only needed by connection-based services */
437 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
438 
439 /**
440  * \brief Function body of \ref psa_set_rhandle.
441  *
442  * \param[in] msg_handle        Handle for the client's message.
443  * \param[in] rhandle           Reverse handle allocated by the RoT Service.
444  *
445  * \retval PSA_SUCCESS          Success, rhandle will be provided with all
446  *                              subsequent messages delivered on this
447  *                              connection.
448  * \retval "PROGRAMMER ERROR"   msg_handle is invalid.
449  */
450 psa_status_t tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle);
451 #else
452 #define tfm_spm_partition_psa_set_rhandle       NULL
453 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
454 
455 #if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
456 /**
457  * \brief Function body of \ref psa_irq_enable.
458  *
459  * \param[in] irq_signal The signal for the interrupt to be enabled.
460  *                       This must have a single bit set, which must be the
461  *                       signal value for an interrupt in the calling Secure
462  *                       Partition.
463  *
464  * \retval PSA_SUCCESS        Success.
465  * \retval "PROGRAMMER ERROR" If one or more of the following are true:
466  * \arg                       \a irq_signal is not an interrupt signal.
467  * \arg                       \a irq_signal indicates more than one signal.
468  */
469 psa_status_t tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal);
470 
471 /**
472  * \brief Function body of psa_irq_disable.
473  *
474  * \param[in] irq_signal The signal for the interrupt to be disabled.
475  *                       This must have a single bit set, which must be the
476  *                       signal value for an interrupt in the calling Secure
477  *                       Partition.
478  *
479  * \retval 0                  The interrupt was disabled prior to this call.
480  *         1                  The interrupt was enabled prior to this call.
481  * \retval "PROGRAMMER ERROR" If one or more of the following are true:
482  * \arg                       \a irq_signal is not an interrupt signal.
483  * \arg                       \a irq_signal indicates more than one signal.
484  *
485  * \note The current implementation always return 1. Do not use the return.
486  */
487 psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal);
488 #else /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
489 #define tfm_spm_partition_psa_irq_enable     NULL
490 #define tfm_spm_partition_psa_irq_disable    NULL
491 #endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
492 
493 /* This API is only used for FLIH. */
494 #if CONFIG_TFM_FLIH_API == 1
495 /**
496  * \brief Function body of \ref psa_reset_signal.
497  *
498  * \param[in] irq_signal    The interrupt signal to be reset.
499  *                          This must have a single bit set, corresponding to a
500  *                          currently asserted signal for an interrupt that is
501  *                          defined to use FLIH handling.
502  *
503  * \retval PSA_SUCCESS        Success.
504  * \retval "Programmer Error" if one or more of the following are true:
505  * \arg                       \a irq_signal is not a signal for an interrupt
506  *                            that is specified with FLIH handling in the Secure
507  *                            Partition manifest.
508  * \arg                       \a irq_signal indicates more than one signal.
509  * \arg                       \a irq_signal is not currently asserted.
510  */
511 psa_status_t tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal);
512 #else /* CONFIG_TFM_FLIH_API == 1 */
513 #define tfm_spm_partition_psa_reset_signal      NULL
514 #endif /* CONFIG_TFM_FLIH_API == 1 */
515 
516 /* This API is only used for SLIH. */
517 #if CONFIG_TFM_SLIH_API == 1
518 /**
519  * \brief Function body of \ref psa_eoi.
520  *
521  * \param[in] irq_signal        The interrupt signal that has been processed.
522  *
523  * \retval PSA_SUCCESS          Success.
524  * \retval "PROGRAMMER ERROR"   The call is invalid, one or more of the
525  *                              following are true:
526  * \arg                           irq_signal is not an interrupt signal.
527  * \arg                           irq_signal indicates more than one signal.
528  * \arg                           irq_signal is not currently asserted.
529  * \arg                           The interrupt is not using SLIH.
530  */
531 psa_status_t tfm_spm_partition_psa_eoi(psa_signal_t irq_signal);
532 #else /* CONFIG_TFM_SLIH_API == 1 */
533 #define tfm_spm_partition_psa_eoi       NULL
534 #endif /* CONFIG_TFM_SLIH_API == 1 */
535 
536 #if PSA_FRAMEWORK_HAS_MM_IOVEC
537 
538 /**
539  * \brief Function body of psa_map_invec.
540  */
541 const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
542                                             uint32_t invec_idx);
543 
544 /**
545  * \brief Function body of psa_unmap_invec.
546  */
547 void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
548                                        uint32_t invec_idx);
549 
550 /**
551  * \brief Function body of psa_map_outvet.
552  */
553 void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
554                                        uint32_t outvec_idx);
555 
556 /**
557  * \brief Function body of psa_unmap_outvec.
558  */
559 void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
560                                         uint32_t outvec_idx, size_t len);
561 
562 #endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
563 
564 #endif /* __PSA_API_H__ */
565