1 /*
2 * Copyright (c) 2018-2023, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #ifndef SERVICE_PSA_IPC_H
8 #define SERVICE_PSA_IPC_H
9
10 #include <stddef.h>
11 #include <stdint.h>
12
13 #include <rpc_caller.h>
14 #include <psa/error.h>
15
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19
20 #ifndef IOVEC_LEN
21 #define IOVEC_LEN(arr) ((uint32_t)(sizeof(arr)/sizeof(arr[0])))
22 #endif
23
24 /*********************** PSA Client Macros and Types *************************/
25
26 typedef int32_t psa_handle_t;
27
28 /**
29 * The version of the PSA Framework API that is being used to build the calling
30 * firmware. Only part of features of FF-M v1.1 have been implemented. FF-M v1.1
31 * is compatible with v1.0.
32 */
33 #define PSA_FRAMEWORK_VERSION (0x0101u)
34
35 /**
36 * Return value from psa_version() if the requested RoT Service is not present
37 * in the system.
38 */
39 #define PSA_VERSION_NONE (0u)
40
41 /**
42 * The zero-value null handle can be assigned to variables used in clients and
43 * RoT Services, indicating that there is no current connection or message.
44 */
45 #define PSA_NULL_HANDLE ((psa_handle_t)0)
46
47 /**
48 * Tests whether a handle value returned by psa_connect() is valid.
49 */
50 #define PSA_HANDLE_IS_VALID(handle) ((psa_handle_t)(handle) > 0)
51
52 /**
53 * Converts the handle value returned from a failed call psa_connect() into
54 * an error code.
55 */
56 #define PSA_HANDLE_TO_ERROR(handle) ((psa_status_t)(handle))
57
58 /**
59 * Maximum number of input and output vectors for a request to psa_call().
60 */
61 #define PSA_MAX_IOVEC (4u)
62
63 /**
64 * An IPC message type that indicates a generic client request.
65 */
66 #define PSA_IPC_CALL (0)
67
68 /**
69 * A read-only input memory region provided to an RoT Service.
70 */
71 struct __attribute__ ((__packed__)) psa_invec {
72 uint32_t base; /*!< the start address of the memory buffer */
73 uint32_t len; /*!< the size in bytes */
74 };
75
76 /**
77 * A writable output memory region provided to an RoT Service.
78 */
79 struct __attribute__ ((__packed__)) psa_outvec {
80 uint32_t base; /*!< the start address of the memory buffer */
81 uint32_t len; /*!< the size in bytes */
82 };
83
psa_u32_to_ptr(uint32_t addr)84 inline static void *psa_u32_to_ptr(uint32_t addr)
85 {
86 return (void *)(uintptr_t)addr;
87 }
88
psa_ptr_to_u32(void * ptr)89 inline static uint32_t psa_ptr_to_u32(void *ptr)
90 {
91 return (uintptr_t)ptr;
92 }
93
psa_ptr_const_to_u32(const void * ptr)94 inline static uint32_t psa_ptr_const_to_u32(const void *ptr)
95 {
96 return (uintptr_t)ptr;
97 }
98
99 /*************************** PSA Client API **********************************/
100
101 /**
102 * \brief Retrieve the version of the PSA Framework API that is implemented.
103 *
104 * \param[in] rpc_caller RPC caller to use
105 * \return version The version of the PSA Framework implementation
106 * that is providing the runtime services to the
107 * caller. The major and minor version are encoded
108 * as follows:
109 * \arg version[15:8] -- major version number.
110 * \arg version[7:0] -- minor version number.
111 */
112 uint32_t psa_framework_version(struct rpc_caller_interface *caller);
113
114 /**
115 * \brief Retrieve the version of an RoT Service or indicate that it is not
116 * present on this system.
117 *
118 * \param[in] rpc_caller RPC caller to use
119 * \param[in] sid ID of the RoT Service to query.
120 *
121 * \retval PSA_VERSION_NONE The RoT Service is not implemented, or the
122 * caller is not permitted to access the service.
123 * \retval > 0 The version of the implemented RoT Service.
124 */
125 uint32_t psa_version(struct rpc_caller_interface *caller, uint32_t sid);
126
127 /**
128 * \brief Connect to an RoT Service by its SID.
129 *
130 * \param[in] rpc_caller RPC caller to use
131 * \param[in] sid ID of the RoT Service to connect to.
132 * \param[in] version Requested version of the RoT Service.
133 *
134 * \retval > 0 A handle for the connection.
135 * \retval PSA_ERROR_CONNECTION_REFUSED The SPM or RoT Service has refused the
136 * connection.
137 * \retval PSA_ERROR_CONNECTION_BUSY The SPM or RoT Service cannot make the
138 * connection at the moment.
139 * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more
140 * of the following are true:
141 * \arg The RoT Service ID is not present.
142 * \arg The RoT Service version is not supported.
143 * \arg The caller is not allowed to access the RoT
144 * service.
145 */
146 psa_handle_t psa_connect(struct rpc_caller_interface *caller, uint32_t sid,
147 uint32_t version);
148
149 /**
150 * \brief Call an RoT Service on an established connection.
151 *
152 * \note FF-M 1.0 proposes 6 parameters for psa_call but the secure gateway ABI
153 * support at most 4 parameters. TF-M chooses to encode 'in_len',
154 * 'out_len', and 'type' into a 32-bit integer to improve efficiency.
155 * Compared with struct-based encoding, this method saves extra memory
156 * check and memory copy operation. The disadvantage is that the 'type'
157 * range has to be reduced into a 16-bit integer. So with this encoding,
158 * the valid range for 'type' is 0-32767.
159 *
160 * \param[in] rpc_caller RPC caller to use
161 * \param[in] handle A handle to an established connection.
162 * \param[in] type The request type.
163 * Must be zero( \ref PSA_IPC_CALL) or positive.
164 * \param[in] in_vec Array of input \ref psa_invec structures.
165 * \param[in] in_len Number of input \ref psa_invec structures.
166 * \param[in,out] out_vec Array of output \ref psa_outvec structures.
167 * \param[in] out_len Number of output \ref psa_outvec structures.
168 *
169 * \retval >=0 RoT Service-specific status value.
170 * \retval <0 RoT Service-specific error code.
171 * \retval PSA_ERROR_PROGRAMMER_ERROR The connection has been terminated by the
172 * RoT Service. The call is a PROGRAMMER ERROR if
173 * one or more of the following are true:
174 * \arg An invalid handle was passed.
175 * \arg The connection is already handling a request.
176 * \arg type < 0.
177 * \arg An invalid memory reference was provided.
178 * \arg in_len + out_len > PSA_MAX_IOVEC.
179 * \arg The message is unrecognized by the RoT
180 * Service or incorrectly formatted.
181 */
182 psa_status_t psa_call(struct rpc_caller_interface *caller, psa_handle_t handle,
183 int32_t type, const struct psa_invec *in_vec,
184 size_t in_len, struct psa_outvec *out_vec, size_t out_len);
185
186 /**
187 * \brief Call an RoT Service on an established connection.
188 *
189 * \note FF-M 1.0 proposes 6 parameters for psa_call but the secure gateway ABI
190 * support at most 4 parameters. TF-M chooses to encode 'in_len',
191 * 'out_len', and 'type' into a 32-bit integer to improve efficiency.
192 * Compared with struct-based encoding, this method saves extra memory
193 * check and memory copy operation. The disadvantage is that the 'type'
194 * range has to be reduced into a 16-bit integer. So with this encoding,
195 * the valid range for 'type' is 0-32767.
196 *
197 * \param[in] rpc_caller RPC caller to use
198 * \param[in] handle A handle to an established connection.
199 * \param[in] client_id A client_id to be passed over the request
200 * \param[in] type The request type.
201 * Must be zero( \ref PSA_IPC_CALL) or positive.
202 * \param[in] in_vec Array of input \ref psa_invec structures.
203 * \param[in] in_len Number of input \ref psa_invec structures.
204 * \param[in,out] out_vec Array of output \ref psa_outvec structures.
205 * \param[in] out_len Number of output \ref psa_outvec structures.
206 *
207 * \retval >=0 RoT Service-specific status value.
208 * \retval <0 RoT Service-specific error code.
209 * \retval PSA_ERROR_PROGRAMMER_ERROR The connection has been terminated by the
210 * RoT Service. The call is a PROGRAMMER ERROR if
211 * one or more of the following are true:
212 * \arg An invalid handle was passed.
213 * \arg The connection is already handling a request.
214 * \arg type < 0.
215 * \arg An invalid memory reference was provided.
216 * \arg in_len + out_len > PSA_MAX_IOVEC.
217 * \arg The message is unrecognized by the RoT
218 * Service or incorrectly formatted.
219 */
220 psa_status_t psa_call_client_id(struct rpc_caller_interface *caller, psa_handle_t handle,
221 int32_t client_id, int32_t type,
222 const struct psa_invec *in_vec, size_t in_len,
223 struct psa_outvec *out_vec, size_t out_len);
224
225 /**
226 * \brief Close a connection to an RoT Service.
227 *
228 * \param[in] rpc_caller RPC caller to use
229 * \param[in] handle A handle to an established connection, or the
230 * null handle.
231 *
232 * \retval void Success.
233 * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more
234 * of the following are true:
235 * \arg An invalid handle was provided that is not
236 * the null handle.
237 * \arg The connection is currently handling a
238 * request.
239 */
240 void psa_close(struct rpc_caller_interface *caller, psa_handle_t handle);
241
242 #ifdef __cplusplus
243 }
244 #endif
245
246 #endif /* SERVICE_PSA_IPC_H */
247
248
249