1 /*
2  * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
3  * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company)
4  * or an affiliate of Cypress Semiconductor Corporation. All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  */
9 
10 #ifndef __PSA_SERVICE_H__
11 #define __PSA_SERVICE_H__
12 
13 #include <stddef.h>
14 #include <stdint.h>
15 
16 #include "config_impl.h"
17 
18 #include "psa/client.h"
19 #include "psa/error.h"
20 #include "psa/framework_feature.h"
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 /********************** PSA Secure Partition Macros and Types ****************/
27 
28 /**
29  * A timeout value that requests a polling wait operation.
30  */
31 #define PSA_POLL                (0x00000000u)
32 
33 /**
34  * A timeout value that requests a blocking wait operation.
35  */
36 #define PSA_BLOCK               (0x80000000u)
37 
38 /**
39  * A mask value that includes all Secure Partition signals.
40  */
41 #define PSA_WAIT_ANY            (0xFFFFFFFFu)
42 
43 /**
44  * The signal number for the Secure Partition doorbell.
45  */
46 #define PSA_DOORBELL            (0x00000008u)
47 
48 /* PSA message types */
49 /* An IPC message type that indicates a new connection. */
50 #define PSA_IPC_CONNECT         (-1)
51 /* An IPC message type that indicates the end of a connection. */
52 #define PSA_IPC_DISCONNECT      (-2)
53 
54 /* FLIH return types */
55 #define PSA_FLIH_NO_SIGNAL      ((psa_flih_result_t) 0)
56 #define PSA_FLIH_SIGNAL         ((psa_flih_result_t) 1)
57 
58 /* Store a set of one or more Secure Partition signals */
59 typedef uint32_t psa_signal_t;
60 
61 /* A type used to temporarily store a previous interrupt state. */
62 typedef uint32_t psa_irq_status_t;
63 
64 /* The type of the return value from an FLIH function */
65 typedef uint32_t psa_flih_result_t;
66 
67 /**
68  * Describe a message received by an RoT Service after calling \ref psa_get().
69  */
70 typedef struct psa_msg_t {
71     int32_t type;              /* One of the following values:
72                                  * \ref PSA_IPC_CONNECT
73                                  * >= 0
74                                  * \ref PSA_IPC_DISCONNECT
75                                  */
76     psa_handle_t handle;        /* A reference generated by the SPM to the
77                                  * message returned by psa_get().
78                                  */
79     int32_t client_id;          /*
80                                  * Partition ID of the sender of the
81                                  * message:
82                                  *  - secure partition id;
83                                  *  - non secure client endpoint id.
84                                  */
85     void *rhandle;              /* Be useful for binding a connection to some
86                                  * application-specific data or function
87                                  * pointer within the RoT Service
88                                  * implementation.
89                                  */
90     size_t in_size[PSA_MAX_IOVEC]; /* Provide the size of each client input
91                                     * vector in bytes.
92                                     */
93     size_t out_size[PSA_MAX_IOVEC];/* Provide the size of each client output
94                                     * vector in bytes.
95                                     */
96 } psa_msg_t;
97 
98 /************************* PSA Secure Partition API **************************/
99 
100 /**
101  * \brief Return the Secure Partition interrupt signals that have been asserted
102  *        from a subset of signals provided by the caller.
103  *
104  * \param[in] signal_mask       A set of signals to query. Signals that are not
105  *                              in this set will be ignored.
106  * \param[in] timeout           Specify either blocking \ref PSA_BLOCK or
107  *                              polling \ref PSA_POLL operation.
108  *
109  * \retval >0                   At least one signal is asserted.
110  * \retval 0                    No signals are asserted. This is only seen when
111  *                              a polling timeout is used.
112  */
113 psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout);
114 
115 /**
116  * \brief Retrieve the message which corresponds to a given RoT Service signal
117  *        and remove the message from the RoT Service queue.
118  *
119  * \param[in] signal            The signal value for an asserted RoT Service.
120  * \param[out] msg              Pointer to \ref psa_msg_t object for receiving
121  *                              the message.
122  *
123  * \retval PSA_SUCCESS          Success, *msg will contain the delivered
124  *                              message.
125  * \retval PSA_ERROR_DOES_NOT_EXIST Message could not be delivered.
126  * \retval "PROGRAMMER ERROR"   The call is invalid because one or more of the
127  *                              following are true:
128  * \arg                           signal has more than a single bit set.
129  * \arg                           signal does not correspond to an RoT Service.
130  * \arg                           The RoT Service signal is not currently
131  *                                asserted.
132  * \arg                           The msg pointer provided is not a valid memory
133  *                                reference.
134  */
135 psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg);
136 
137 /**
138  * \brief Associate some RoT Service private data with a client connection.
139  *
140  * \param[in] msg_handle        Handle for the client's message.
141  * \param[in] rhandle           Reverse handle allocated by the RoT Service.
142  *
143  * \note When successful,rhandle will be provided with all subsequent messages
144  *       delivered on this connection.
145  * \note The call is a "PROGRAMMER ERROR" if msg_handle is invalid.
146  */
147 void psa_set_rhandle(psa_handle_t msg_handle, void *rhandle);
148 
149 /**
150  * \brief Read a message parameter or part of a message parameter from a client
151  *        input vector.
152  *
153  * \param[in] msg_handle        Handle for the client's message.
154  * \param[in] invec_idx         Index of the input vector to read from. Must be
155  *                              less than \ref PSA_MAX_IOVEC.
156  * \param[out] buffer           Buffer in the Secure Partition to copy the
157  *                              requested data to.
158  * \param[in] num_bytes         Maximum number of bytes to be read from the
159  *                              client input vector.
160  *
161  * \retval >0                   Number of bytes copied.
162  * \retval 0                    There was no remaining data in this input
163  *                              vector.
164  * \retval "PROGRAMMER ERROR"   The call is invalid, one or more of the
165  *                              following are true:
166  * \arg                           msg_handle is invalid.
167  * \arg                           msg_handle does not refer to a
168  *                                \ref PSA_IPC_CALL message.
169  * \arg                           invec_idx is equal to or greater than
170  *                                \ref PSA_MAX_IOVEC.
171  * \arg                           the memory reference for buffer is invalid or
172  *                                not writable.
173  */
174 size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
175                 void *buffer, size_t num_bytes);
176 
177 /**
178  * \brief Skip over part of a client input vector.
179  *
180  * \param[in] msg_handle        Handle for the client's message.
181  * \param[in] invec_idx         Index of input vector to skip from. Must be
182  *                              less than \ref PSA_MAX_IOVEC.
183  * \param[in] num_bytes         Maximum number of bytes to skip in the client
184  *                              input vector.
185  *
186  * \retval >0                   Number of bytes skipped.
187  * \retval 0                    There was no remaining data in this input
188  *                              vector.
189  * \retval "PROGRAMMER ERROR"   The call is invalid, one or more of the
190  *                              following are true:
191  * \arg                           msg_handle is invalid.
192  * \arg                           msg_handle does not refer to a request
193  *                                message.
194  * \arg                           invec_idx is equal to or greater than
195  *                                \ref PSA_MAX_IOVEC.
196  */
197 size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes);
198 
199 /**
200  * \brief Write a message response to a client output vector.
201  *
202  * \param[in] msg_handle        Handle for the client's message.
203  * \param[out] outvec_idx       Index of output vector in message to write to.
204  *                              Must be less than \ref PSA_MAX_IOVEC.
205  * \param[in] buffer            Buffer with the data to write.
206  * \param[in] num_bytes         Number of bytes to write to the client output
207  *                              vector.
208  *
209  * \note The call is a "PROGRAMMER ERROR" if one or more of the following occur:
210  *        - msg_handle is invalid.
211  *        - msg_handle does not refer to a request message.
212  *        - outvec_idx is equal to or greater than \ref PSA_MAX_IOVEC.
213  *        - the memory reference for buffer is invalid.
214  *        - the call attempts to write data past the end of the client output
215  *          vector.
216  */
217 void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
218                const void *buffer, size_t num_bytes);
219 
220 /**
221  * \brief Complete handling of a specific message and unblock the client.
222  *
223  * \param[in] msg_handle        Handle for the client's message.
224  * \param[in] status            Message result value to be reported to the
225  *                              client.
226  *
227  * \note The call is a "PROGRAMMER ERROR" if one or more of the following occur:
228  *        - msg_handle is invalid.
229  *        - An invalid status code is specified for the type of message.
230  */
231 void psa_reply(psa_handle_t msg_handle, psa_status_t status);
232 
233 /**
234  * \brief Send a PSA_DOORBELL signal to a specific Secure Partition.
235  *
236  * \param[in] partition_id      Secure Partition ID of the target partition.
237  *
238  * \note The call is a "PROGRAMMER ERROR" if partition_id does not correspond to
239  *       a Secure Partition.
240  */
241 void psa_notify(int32_t partition_id);
242 
243 /**
244  * \brief Clear the PSA_DOORBELL signal.
245  *
246  * \note The call is a "PROGRAMMER ERROR" if the Secure Partition's doorbell
247  *       signal is not currently asserted.
248  */
249 void psa_clear(void);
250 
251 /**
252  * \brief Inform the SPM that an interrupt has been handled (end of interrupt).
253  *
254  * \param[in] irq_signal        The interrupt signal that has been processed.
255  *
256  * \note The call is a "PROGRAMMER ERROR" if one or more of the following occur:
257  *        - irq_signal is not an interrupt signal.
258  *        - irq_signal indicates more than one signal.
259  *        - irq_signal is not currently asserted.
260  *        - The interrupt is not using SLIH.
261  */
262 void psa_eoi(psa_signal_t irq_signal);
263 
264 /**
265  * \brief Terminate execution within the calling Secure Partition and will not
266  *        return.
267  */
268 void psa_panic(void);
269 
270 /**
271  * \brief Enable an interrupt.
272  *
273  * \param[in] irq_signal The signal for the interrupt to be enabled.
274  *                       This must have a single bit set, which must be the
275  *                       signal value for an interrupt in the calling Secure
276  *                       Partition.
277  *
278  * \note The call is a "PROGRAMMER ERROR" if one or more of the following occur:
279  *        - \a irq_signal is not an interrupt signal.
280  *        - \a irq_signal indicates more than one signal.
281  */
282 void psa_irq_enable(psa_signal_t irq_signal);
283 
284 /**
285  * \brief Disable an interrupt and return the status of the interrupt prior to
286  *        being disabled by this call.
287  *
288  * \param[in] irq_signal The signal for the interrupt to be disabled.
289  *                       This must have a single bit set, which must be the
290  *                       signal value for an interrupt in the calling Secure
291  *                       Partition.
292  *
293  * \retval 0                  The interrupt was disabled prior to this call.
294  *         1                  The interrupt was enabled prior to this call.
295  * \retval "PROGRAMMER ERROR" If one or more of the following are true:
296  * \arg                       \a irq_signal is not an interrupt signal.
297  * \arg                       \a irq_signal indicates more than one signal.
298  *
299  * \note The current implementation always return 1. Do not use the return.
300  */
301 psa_irq_status_t psa_irq_disable(psa_signal_t irq_signal);
302 
303 /**
304  * \brief Reset the signal for an interrupt that is using FLIH handling.
305  *
306  * \param[in] irq_signal    The interrupt signal to be reset.
307  *                          This must have a single bit set, corresponding to a
308  *                          currently asserted signal for an interrupt that is
309  *                          defined to use FLIH handling.
310  *
311  * \note The call is a "PROGRAMMER ERROR" if one or more of the following occur:
312  *        - \a irq_signal is not a signal for an interrupt that is specified
313  *          with FLIH handling in the Secure Partition manifest.
314  *        - \a irq_signal indicates more than one signal.
315  *        - \a irq_signal is not currently asserted.
316  */
317 void psa_reset_signal(psa_signal_t irq_signal);
318 
319 #if PSA_FRAMEWORK_HAS_MM_IOVEC
320 
321 /**
322  * \brief Map a client input vector for direct access by a Secure Partition RoT
323  *        Service.
324  *
325  * \param[in] msg_handle        Handle for the client's message.
326  * \param[in] invec_idx         Index of input vector to map. Must be
327  *                              less than \ref PSA_MAX_IOVEC.
328  *
329  * \retval                      A pointer to the input vector data.
330  * \retval "PROGRAMMER ERROR"   The call is invalid, one or more of the
331  *                              following are true:
332  * \arg                           MM-IOVEC has not been enabled for the RoT
333  *                                Service that received the message.
334  * \arg                           msg_handle is invalid.
335  * \arg                           msg_handle does not refer to a request
336  *                                message.
337  * \arg                           invec_idx is equal to or greater than
338  *                                \ref PSA_MAX_IOVEC.
339  * \arg                           The input vector has length zero.
340  * \arg                           The input vector has already been mapped using
341  *                                psa_map_invec().
342  * \arg                           The input vector has already been accessed
343  *                                using psa_read() or psa_skip().
344  */
345 const void *psa_map_invec(psa_handle_t msg_handle, uint32_t invec_idx);
346 
347 /**
348  * \brief Unmap a previously mapped client input vector from a Secure Partition
349  *        RoT Service.
350  *
351  * \param[in] msg_handle        Handle for the client's message.
352  * \param[in] invec_idx         Index of input vector to map. Must be
353  *                              less than \ref PSA_MAX_IOVEC.
354  *
355  * \note The call is a "PROGRAMMER ERROR" if one or more of the following occur:
356  *        - msg_handle is invalid.
357  *        - msg_handle does not refer to a request message.
358  *        - invec_idx is equal to or greater than \ref PSA_MAX_IOVEC.
359  *        - The input vector has not been mapped by a call to psa_map_invec().
360  *        - The input vector has already been unmapped by a call to
361  *          psa_unmap_invec().
362  */
363 void psa_unmap_invec(psa_handle_t msg_handle, uint32_t invec_idx);
364 
365 /**
366  * \brief Map a client output vector for direct access by a Secure Partition RoT
367  *        Service.
368  *
369  * \param[in] msg_handle        Handle for the client's message.
370  * \param[in] outvec_idx        Index of output vector to map. Must be
371  *                              less than \ref PSA_MAX_IOVEC.
372  *
373  * \retval                      A pointer to the output vector data.
374  * \retval "PROGRAMMER ERROR"   The call is invalid, one or more of the
375  *                              following are true:
376  * \arg                           MM-IOVEC has not been enabled for the RoT
377  *                                Service that received the message.
378  * \arg                           msg_handle is invalid.
379  * \arg                           msg_handle does not refer to a request
380  *                                message.
381  * \arg                           outvec_idx is equal to or greater than
382  *                                \ref PSA_MAX_IOVEC.
383  * \arg                           The output vector has length zero.
384  * \arg                           The output vector has already been mapped
385  *                                using psa_map_outvec().
386  * \arg                           The output vector has already been accessed
387  *                                using psa_write().
388  */
389 void *psa_map_outvec(psa_handle_t msg_handle, uint32_t outvec_idx);
390 
391 /**
392  * \brief Unmap a previously mapped client output vector from a Secure Partition
393  *        RoT Service.
394  *
395  * \param[in] msg_handle        Handle for the client's message.
396  * \param[in] outvec_idx        Index of output vector to map. Must be
397  *                              less than \ref PSA_MAX_IOVEC.
398  * \param[in] len               The number of bytes written to the output
399  *                              vector. This must be less than or equal to the
400  *                              size of the output vector.
401  *
402  * \note The call is a "PROGRAMMER ERROR" if one or more of the following occur:
403  *        - msg_handle is invalid.
404  *        - msg_handle does not refer to a request message.
405  *        - outvec_idx is equal to or greater than \ref PSA_MAX_IOVEC.
406  *        - The output vector has not been mapped by a call to psa_map_outvec().
407  *        - The output vector has already been unmapped by a call to
408  *          psa_unmap_outvec().
409  */
410 void psa_unmap_outvec(psa_handle_t msg_handle, uint32_t outvec_idx, size_t len);
411 
412 #endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
413 
414 #ifdef __cplusplus
415 }
416 #endif
417 
418 #endif /* __PSA_SERVICE_H__ */
419