1 /*
2  * Copyright (c) 2019-2022, 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 #include "psa/client.h"
15 #include "psa/service.h"
16 
17 /**
18  * \brief This function handles the specific programmer error cases.
19  *
20  * \param[in] status            Standard error codes for the SPM.
21  *
22  * \retval void                 Status will not cause SPM panic
23  * \retval "SPM panic"          Following programmer errors are triggered by SP:
24  * \arg                           PSA_ERROR_PROGRAMMER_ERROR
25  * \arg                           PSA_ERROR_CONNECTION_REFUSED
26  * \arg                           PSA_ERROR_CONNECTION_BUSY
27  */
28 void spm_handle_programmer_errors(psa_status_t status);
29 
30 /**
31  * \brief This function get the current PSA RoT lifecycle state.
32  *
33  * \return state                The current security lifecycle state of the PSA
34  *                              RoT. The PSA state and implementation state are
35  *                              encoded as follows:
36  * \arg                           state[15:8] – PSA lifecycle state
37  * \arg                           state[7:0] – IMPLEMENTATION DEFINED state
38  */
39 uint32_t tfm_spm_get_lifecycle_state(void);
40 
41 /* PSA Client API function body, for privileged use only. */
42 
43 /**
44  * \brief handler for \ref psa_framework_version.
45  *
46  * \return version              The version of the PSA Framework implementation
47  *                              that is providing the runtime services.
48  */
49 uint32_t tfm_spm_client_psa_framework_version(void);
50 
51 /**
52  * \brief handler for \ref psa_version.
53  *
54  * \param[in] sid               RoT Service identity.
55  *
56  * \retval PSA_VERSION_NONE     The RoT Service is not implemented, or the
57  *                              caller is not permitted to access the service.
58  * \retval > 0                  The version of the implemented RoT Service.
59  */
60 uint32_t tfm_spm_client_psa_version(uint32_t sid);
61 
62 /**
63  * \brief handler for \ref psa_call.
64  *
65  * \param[in] handle            Service handle to the established connection,
66  *                              \ref psa_handle_t
67  * \param[in] ctrl_param        Parameters combined in uint32_t,
68  *                              includes request type, in_num and out_num.
69  * \param[in] inptr             Array of input psa_invec structures.
70  *                              \ref psa_invec
71  * \param[in] outptr            Array of output psa_outvec structures.
72  *                              \ref psa_outvec
73  *
74  * \retval PSA_SUCCESS          Success.
75  * \retval "Does not return"    The call is invalid, one or more of the
76  *                              following are true:
77  * \arg                           An invalid handle was passed.
78  * \arg                           The connection is already handling a request.
79  * \arg                           An invalid memory reference was provided.
80  * \arg                           in_num + out_num > PSA_MAX_IOVEC.
81  * \arg                           The message is unrecognized by the RoT
82  *                                Service or incorrectly formatted.
83  */
84 psa_status_t tfm_spm_client_psa_call(psa_handle_t handle,
85                                      uint32_t ctrl_param,
86                                      const psa_invec *inptr,
87                                      psa_outvec *outptr);
88 
89 /* Following PSA APIs are only needed by connection-based services */
90 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
91 
92 /**
93  * \brief handler for \ref psa_connect.
94  *
95  * \param[in] sid               RoT Service identity.
96  * \param[in] version           The version of the RoT Service.
97  *
98  * \retval PSA_SUCCESS          Success.
99  * \retval PSA_ERROR_CONNECTION_REFUSED The SPM or RoT Service has refused the
100  *                              connection.
101  * \retval PSA_ERROR_CONNECTION_BUSY The SPM or RoT Service cannot make the
102  *                              connection at the moment.
103  * \retval "Does not return"    The RoT Service ID and version are not
104  *                              supported, or the caller is not permitted to
105  *                              access the service.
106  */
107 psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version);
108 
109 /**
110  * \brief handler for \ref psa_close.
111  *
112  * \param[in] handle            Service handle to the connection to be closed,
113  *                              \ref psa_handle_t
114  *
115  * \retval PSA_SUCCESS          Success.
116  * \retval PSA_ERROR_PROGRAMMER_ERROR The call is invalid, one or more of the
117  *                              following are true:
118  * \arg                           Called with a stateless handle.
119  * \arg                           An invalid handle was provided that is not
120  *                                the null handle.
121  * \arg                           The connection is handling a request.
122  */
123 psa_status_t tfm_spm_client_psa_close(psa_handle_t handle);
124 
125 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
126 
127 /* PSA Partition API function body, for privileged use only. */
128 
129 #if CONFIG_TFM_SPM_BACKEND_IPC == 1 \
130     || CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
131 /**
132  * \brief Function body of \ref psa_wait.
133  *
134  * \param[in] signal_mask       A set of signals to query. Signals that are not
135  *                              in this set will be ignored.
136  * \param[in] timeout           Specify either blocking \ref PSA_BLOCK or
137  *                              polling \ref PSA_POLL operation.
138  *
139  * \retval >0                   At least one signal is asserted.
140  * \retval 0                    No signals are asserted. This is only seen when
141  *                              a polling timeout is used.
142  */
143 psa_signal_t tfm_spm_partition_psa_wait(psa_signal_t signal_mask,
144                                         uint32_t timeout);
145 #endif
146 
147 /* This API is only used in IPC backend. */
148 #if CONFIG_TFM_SPM_BACKEND_IPC == 1
149 /**
150  * \brief Function body of \ref psa_get.
151  *
152  * \param[in] signal            The signal value for an asserted RoT Service.
153  * \param[out] msg              Pointer to \ref psa_msg_t object for receiving
154  *                              the message.
155  *
156  * \retval PSA_SUCCESS          Success, *msg will contain the delivered
157  *                              message.
158  * \retval PSA_ERROR_DOES_NOT_EXIST Message could not be delivered.
159  * \retval "PROGRAMMER ERROR"   The call is invalid because one or more of the
160  *                              following are true:
161  * \arg                           signal has more than a single bit set.
162  * \arg                           signal does not correspond to an RoT Service.
163  * \arg                           The RoT Service signal is not currently
164  *                                asserted.
165  * \arg                           The msg pointer provided is not a valid memory
166  *                                reference.
167  */
168 psa_status_t tfm_spm_partition_psa_get(psa_signal_t signal, psa_msg_t *msg);
169 #endif /* CONFIG_TFM_SPM_BACKEND_IPC == 1 */
170 
171 /**
172  * \brief Function body of \ref psa_read.
173  *
174  * \param[in] msg_handle        Handle for the client's message.
175  * \param[in] invec_idx         Index of the input vector to read from. Must be
176  *                              less than \ref PSA_MAX_IOVEC.
177  * \param[out] buffer           Buffer in the Secure Partition to copy the
178  *                              requested data to.
179  * \param[in] num_bytes         Maximum number of bytes to be read from the
180  *                              client input vector.
181  *
182  * \retval >0                   Number of bytes copied.
183  * \retval 0                    There was no remaining data in this input
184  *                              vector.
185  * \retval "PROGRAMMER ERROR"   The call is invalid, one or more of the
186  *                              following are true:
187  * \arg                           msg_handle is invalid.
188  * \arg                           msg_handle does not refer to a
189  *                                \ref PSA_IPC_CALL message.
190  * \arg                           invec_idx is equal to or greater than
191  *                                \ref PSA_MAX_IOVEC.
192  * \arg                           the memory reference for buffer is invalid or
193  *                                not writable.
194  */
195 size_t tfm_spm_partition_psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
196                                   void *buffer, size_t num_bytes);
197 
198 /**
199  * \brief Function body of psa_skip.
200  *
201  * \param[in] msg_handle        Handle for the client's message.
202  * \param[in] invec_idx         Index of input vector to skip from. Must be
203  *                              less than \ref PSA_MAX_IOVEC.
204  * \param[in] num_bytes         Maximum number of bytes to skip in the client
205  *                              input vector.
206  *
207  * \retval >0                   Number of bytes skipped.
208  * \retval 0                    There was no remaining data in this input
209  *                              vector.
210  * \retval "PROGRAMMER ERROR"   The call is invalid, one or more of the
211  *                              following are true:
212  * \arg                           msg_handle is invalid.
213  * \arg                           msg_handle does not refer to a request
214  *                                message.
215  * \arg                           invec_idx is equal to or greater than
216  *                                \ref PSA_MAX_IOVEC.
217  */
218 size_t tfm_spm_partition_psa_skip(psa_handle_t msg_handle, uint32_t invec_idx,
219                                   size_t num_bytes);
220 
221 /**
222  * \brief Function body of \ref psa_write.
223  *
224  * \param[in] msg_handle        Handle for the client's message.
225  * \param[out] outvec_idx       Index of output vector in message to write to.
226  *                              Must be less than \ref PSA_MAX_IOVEC.
227  * \param[in] buffer            Buffer with the data to write.
228  * \param[in] num_bytes         Number of bytes to write to the client output
229  *                              vector.
230  *
231  * \retval void                 Success
232  * \retval "PROGRAMMER ERROR"   The call is invalid, one or more of the
233  *                              following are true:
234  * \arg                           msg_handle is invalid.
235  * \arg                           msg_handle does not refer to a request
236  *                                message.
237  * \arg                           outvec_idx is equal to or greater than
238  *                                \ref PSA_MAX_IOVEC.
239  * \arg                           The memory reference for buffer is invalid.
240  * \arg                           The call attempts to write data past the end
241  *                                of the client output vector.
242  */
243 void tfm_spm_partition_psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
244                                  const void *buffer, size_t num_bytes);
245 
246 /**
247  * \brief Function body of \ref psa_reply.
248  *
249  * \param[in] msg_handle        Handle for the client's message.
250  * \param[in] status            Message result value to be reported to the
251  *                              client.
252  *
253  * \retval Positive integer     Success, the connection handle.
254  * \retval PSA_SUCCESS          Success
255  * \retval "PROGRAMMER ERROR"   The call is invalid, one or more of the
256  *                              following are true:
257  * \arg                         msg_handle is invalid.
258  * \arg                         An invalid status code is specified for the
259  *                              type of message.
260  */
261 int32_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
262                                     psa_status_t status);
263 
264 #if CONFIG_TFM_DOORBELL_API == 1
265 /**
266  * \brief Function body of \ref psa_norify.
267  *
268  * \param[in] partition_id      Secure Partition ID of the target partition.
269  *
270  * \retval void                 Success.
271  * \retval "PROGRAMMER ERROR"   partition_id does not correspond to a Secure
272  *                              Partition.
273  */
274 void tfm_spm_partition_psa_notify(int32_t partition_id);
275 
276 /**
277  * \brief Function body of \ref psa_clear.
278  *
279  * \retval void                 Success.
280  * \retval "PROGRAMMER ERROR"   The Secure Partition's doorbell signal is not
281  *                              currently asserted.
282  */
283 void tfm_spm_partition_psa_clear(void);
284 #endif /* CONFIG_TFM_DOORBELL_API == 1 */
285 
286 /**
287  * \brief Function body of \ref psa_panic.
288  *
289  * \retval "Does not return"
290  */
291 void tfm_spm_partition_psa_panic(void);
292 
293 /* psa_set_rhandle is only needed by connection-based services */
294 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
295 
296 /**
297  * \brief Function body of \ref psa_set_rhandle.
298  *
299  * \param[in] msg_handle        Handle for the client's message.
300  * \param[in] rhandle           Reverse handle allocated by the RoT Service.
301  *
302  * \retval void                 Success, rhandle will be provided with all
303  *                              subsequent messages delivered on this
304  *                              connection.
305  * \retval "PROGRAMMER ERROR"   msg_handle is invalid.
306  */
307 void tfm_spm_partition_psa_set_rhandle(psa_handle_t msg_handle, void *rhandle);
308 
309 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
310 
311 #if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
312 /**
313  * \brief Function body of \ref psa_irq_enable.
314  *
315  * \param[in] irq_signal The signal for the interrupt to be enabled.
316  *                       This must have a single bit set, which must be the
317  *                       signal value for an interrupt in the calling Secure
318  *                       Partition.
319  *
320  * \retval void
321  * \retval "PROGRAMMER ERROR" If one or more of the following are true:
322  * \arg                       \a irq_signal is not an interrupt signal.
323  * \arg                       \a irq_signal indicates more than one signal.
324  */
325 void tfm_spm_partition_psa_irq_enable(psa_signal_t irq_signal);
326 
327 /**
328  * \brief Function body of psa_irq_disable.
329  *
330  * \param[in] irq_signal The signal for the interrupt to be disabled.
331  *                       This must have a single bit set, which must be the
332  *                       signal value for an interrupt in the calling Secure
333  *                       Partition.
334  *
335  * \retval 0                  The interrupt was disabled prior to this call.
336  *         1                  The interrupt was enabled prior to this call.
337  * \retval "PROGRAMMER ERROR" If one or more of the following are true:
338  * \arg                       \a irq_signal is not an interrupt signal.
339  * \arg                       \a irq_signal indicates more than one signal.
340  *
341  * \note The current implementation always return 1. Do not use the return.
342  */
343 psa_irq_status_t tfm_spm_partition_psa_irq_disable(psa_signal_t irq_signal);
344 
345 /* This API is only used for FLIH. */
346 #if CONFIG_TFM_FLIH_API == 1
347 /**
348  * \brief Function body of \ref psa_reset_signal.
349  *
350  * \param[in] irq_signal    The interrupt signal to be reset.
351  *                          This must have a single bit set, corresponding to a
352  *                          currently asserted signal for an interrupt that is
353  *                          defined to use FLIH handling.
354  *
355  * \retval void
356  * \retval "Programmer Error" if one or more of the following are true:
357  * \arg                       \a irq_signal is not a signal for an interrupt
358  *                            that is specified with FLIH handling in the Secure
359  *                            Partition manifest.
360  * \arg                       \a irq_signal indicates more than one signal.
361  * \arg                       \a irq_signal is not currently asserted.
362  */
363 void tfm_spm_partition_psa_reset_signal(psa_signal_t irq_signal);
364 #endif
365 
366 /* This API is only used for SLIH. */
367 #if CONFIG_TFM_SLIH_API == 1
368 /**
369  * \brief Function body of \ref psa_eoi.
370  *
371  * \param[in] irq_signal        The interrupt signal that has been processed.
372  *
373  * \retval void                 Success.
374  * \retval "PROGRAMMER ERROR"   The call is invalid, one or more of the
375  *                              following are true:
376  * \arg                           irq_signal is not an interrupt signal.
377  * \arg                           irq_signal indicates more than one signal.
378  * \arg                           irq_signal is not currently asserted.
379  * \arg                           The interrupt is not using SLIH.
380  */
381 void tfm_spm_partition_psa_eoi(psa_signal_t irq_signal);
382 #endif
383 #endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
384 
385 #if PSA_FRAMEWORK_HAS_MM_IOVEC
386 
387 /**
388  * \brief Function body of psa_map_invec.
389  */
390 const void *tfm_spm_partition_psa_map_invec(psa_handle_t msg_handle,
391                                             uint32_t invec_idx);
392 
393 /**
394  * \brief Function body of psa_unmap_invec.
395  */
396 void tfm_spm_partition_psa_unmap_invec(psa_handle_t msg_handle,
397                                        uint32_t invec_idx);
398 
399 /**
400  * \brief Function body of psa_map_outvet.
401  */
402 void *tfm_spm_partition_psa_map_outvec(psa_handle_t msg_handle,
403                                        uint32_t outvec_idx);
404 
405 /**
406  * \brief Function body of psa_unmap_outvec.
407  */
408 void tfm_spm_partition_psa_unmap_outvec(psa_handle_t msg_handle,
409                                         uint32_t outvec_idx, size_t len);
410 
411 #endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
412 
413 #endif /* __PSA_API_H__ */
414