1 /*
2 * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
3 * Copyright (c) 2022-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 /*
11 * Definitions of Remote Procedure Call (RPC) functionalities in TF-M, which
12 * sits between upper TF-M SPM and underlying mailbox implementation.
13 */
14
15 #ifndef __TFM_RPC_H__
16 #define __TFM_RPC_H__
17
18 #ifdef TFM_PARTITION_NS_AGENT_MAILBOX
19
20 #include <stdbool.h>
21 #include <stdint.h>
22 #include "cmsis_compiler.h"
23 #include "psa/client.h"
24 #include "psa/service.h"
25 #include "thread.h"
26 #include "spm.h"
27 #include "ffm/agent_api.h"
28
29 #define TFM_RPC_SUCCESS (0)
30 #define TFM_RPC_INVAL_PARAM (INT32_MIN + 1)
31 #define TFM_RPC_CONFLICT_CALLBACK (INT32_MIN + 2)
32
33 /*
34 * The underlying mailbox communication implementation should provide
35 * the specific operations to complete the RPC functionalities.
36 *
37 * It includes the following operations:
38 * handle_req() - Handle PSA client call request from NSPE
39 * reply() - Reply PSA client call return result to NSPE. The parameter
40 * owner identifies the owner of the PSA client call.
41 * get_caller_data() - Get the private data of NSPE client from mailbox to
42 * identify the PSA client call.
43 */
44 struct tfm_rpc_ops_t {
45 void (*handle_req)(void);
46 void (*reply)(const void *owner, int32_t ret);
47 const void * (*get_caller_data)(int32_t client_id);
48 };
49
50 /**
51 * \brief RPC handler for \ref psa_framework_version.
52 *
53 * \return version The version of the PSA Framework implementation
54 * that is providing the runtime services.
55 */
56 uint32_t tfm_rpc_psa_framework_version(void);
57
58 /**
59 * \brief RPC handler for \ref psa_version.
60 *
61 * \param[in] sid RoT Service identity.
62 *
63 * \retval PSA_VERSION_NONE The RoT Service is not implemented, or the
64 * caller is not permitted to access the service.
65 * \retval > 0 The version of the implemented RoT Service.
66 */
67 uint32_t tfm_rpc_psa_version(uint32_t sid);
68
69 /**
70 * \brief RPC handler for \ref psa_connect.
71 *
72 * \param[in] sid RoT Service identity.
73 * \param[in] version The version of the RoT Service.
74 * \param[in] ns_client_id Agent representing NS client's identifier.
75 * \param[in] client_data Client data, treated as opaque by SPM.
76 *
77 * \retval PSA_SUCCESS Success.
78 * \retval PSA_CONNECTION_BUSY The SPM cannot make the connection
79 * at the moment.
80 * \retval "Does not return" The RoT Service ID and version are not
81 * supported, or the caller is not permitted to
82 * access the service.
83 */
84 psa_status_t tfm_rpc_psa_connect(uint32_t sid,
85 uint32_t version,
86 int32_t ns_client_id,
87 const void *client_data);
88
89 /**
90 * \brief RPC handler for \ref psa_call.
91 *
92 * \param[in] handle Handle to the service being accessed.
93 * \param[in] control A composited uint32_t value for controlling purpose,
94 * containing call types, numbers of in/out vectors and
95 * attributes of vectors.
96 * \param[in] params Combines the psa_invec and psa_outvec params
97 * for the psa_call() to be made, as well as
98 * NS agent's client identifier, which is ignored
99 * for connection-based services.
100 * \param[in] client_data_stateless Client data, treated as opaque by SPM.
101 *
102 * \retval PSA_SUCCESS Success.
103 * \retval "Does not return" The call is invalid, one or more of the
104 * following are true:
105 * \arg An invalid handle was passed.
106 * \arg The connection is already handling a request.
107 * \arg An invalid memory reference was provided.
108 * \arg in_num + out_num > PSA_MAX_IOVEC.
109 * \arg The message is unrecognized by the RoT
110 * Service or incorrectly formatted.
111 */
112 psa_status_t tfm_rpc_psa_call(psa_handle_t handle, uint32_t control,
113 const struct client_params_t *params,
114 const void *client_data_stateless);
115
116 /**
117 * \brief RPC handler for \ref psa_close.
118 *
119 * \param[in] handle A handle to an established connection, or the null handle.
120 *
121 * \retval void Success.
122 * \retval "Does not return" The call is invalid, one or more of the
123 * following are true:
124 * \arg An invalid handle was provided that is not
125 * the null handle..
126 */
127 void tfm_rpc_psa_close(psa_handle_t handle);
128
129 /**
130 * \brief Register underlying mailbox communication operations.
131 *
132 * \param[in] ops_ptr Pointer to the specific operation structure.
133 *
134 * \retval TFM_RPC_SUCCESS Mailbox operations are successfully registered.
135 * \retval Other error code Fail to register mailbox operations.
136 */
137 int32_t tfm_rpc_register_ops(const struct tfm_rpc_ops_t *ops_ptr);
138
139 /**
140 * \brief Unregister underlying mailbox communication operations.
141 *
142 * Currently one and only one underlying mailbox communication implementation is
143 * allowed in runtime. Thus it is unnecessary to specify the mailbox
144 * communication operation callbacks to be unregistered.
145 *
146 * \param[in] void
147 */
148 void tfm_rpc_unregister_ops(void);
149
150 /**
151 * \brief Handling PSA client call request
152 *
153 * \param void
154 */
155 void tfm_rpc_client_call_handler(void);
156
157 #if CONFIG_TFM_SPM_BACKEND_IPC == 1
158 /**
159 * \brief Reply PSA client call return result
160 *
161 * \param[in] void
162 */
163 void tfm_rpc_client_call_reply(void);
164 #endif /* CONFIG_TFM_SPM_BACKEND_IPC == 1 */
165
166 /*
167 * Check if the message was allocated for a non-secure request via RPC
168 *
169 * \param[in] handle The connection handle context pointer
170 * \ref connection_t structures
171 *
172 * \retval true The message was allocated for a NS request via RPC.
173 * \retval false Otherwise.
174 */
is_tfm_rpc_msg(const struct connection_t * handle)175 __STATIC_INLINE bool is_tfm_rpc_msg(const struct connection_t *handle)
176 {
177 /*
178 * FIXME
179 * The ID should be smaller than 0 if the message is allocated by a
180 * non-secure caller.
181 * However, current TF-M implementation use 0 as the default non-secure
182 * caller ID. Therefore, treat the caller as non-secure when client_id == 0.
183 *
184 * This condition check should be improved after TF-M non-secure client ID
185 * management is implemented.
186 */
187 if (handle && (handle->caller_data) && (handle->msg.client_id <= 0)) {
188 return true;
189 }
190
191 return false;
192 }
193
194 /*
195 * \brief Set the private data of the NS caller in \ref connection_t, to
196 * identify the caller after PSA client call is compeleted.
197 *
198 * \param[in] handle The address of \ref connection_t structure
199 * \param[in] client_id The client ID of the NS caller.
200 */
201 void tfm_rpc_set_caller_data(struct connection_t *handle, int32_t client_id);
202
203 #else /* TFM_PARTITION_NS_AGENT_MAILBOX */
204
205 /* RPC is only available in multi-core scenario */
206 #define is_tfm_rpc_msg(x) (false)
207
208 #define tfm_rpc_client_call_reply(owner, ret) do {} while (0)
209
210 #endif /* TFM_PARTITION_NS_AGENT_MAILBOX */
211 #endif /* __TFM_RPC_H__ */
212