1 /*
2 * Copyright (c) 2020, Google Inc. All rights reserved
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23 #pragma once
24
25 #include <kernel/event.h>
26 #include <kernel/thread.h>
27 #include <lib/trusty/handle_set.h>
28 #include <lib/trusty/ipc_msg.h>
29 #include <lib/trusty/uio.h>
30
31 __BEGIN_CDECLS
32
33 struct ktipc_server {
34 const char* name;
35 struct handle* hset;
36 struct thread* thread;
37 struct event have_handles_evt;
38 };
39
40 /**
41 * KTIPC_SERVER_INITIAL_VALUE() - ktipc server static initializer
42 * @ksrv: pointer to @struct ktipc_server to initialize
43 * @name: server name
44 *
45 * @name should not be deallocated while server is running
46 */
47 #define KTIPC_SERVER_INITIAL_VALUE(ksrv, nm) \
48 { \
49 .name = (nm), .hset = NULL, .thread = NULL, \
50 .have_handles_evt = \
51 EVENT_INITIAL_VALUE(ksrv.have_handles_evt, false, 0), \
52 }
53
54 /**
55 * ktipc_server_init() - initialize ktipc server structure
56 * @ksrv: pointer to @struct ktipc_server to initialize
57 * @name: server name
58 *
59 * @name should not be deallocated while server is running
60 *
61 * Return: none
62 */
ktipc_server_init(struct ktipc_server * ksrv,const char * name)63 static inline void ktipc_server_init(struct ktipc_server* ksrv,
64 const char* name) {
65 ksrv->name = name;
66 ksrv->hset = NULL;
67 ksrv->thread = NULL;
68 event_init(&ksrv->have_handles_evt, false, 0);
69 }
70
71 /**
72 * ktipc_server_start() - start specified ktipc server
73 * @server: server to start
74 * @name: server name
75 *
76 * The &struct ktipc_server must be initialized by calling ktipc_server_init()
77 * or static initializer KTIPC_SERVER_INITIAL_VALUE.
78 *
79 *
80 * Return: 0 on success, negative error code otherwise
81 */
82 int ktipc_server_start(struct ktipc_server* server);
83
84 /**
85 * struct tipc_port_acl - tipc port ACL descriptor
86 * @flags: a combination of IPC_PORT_ALLOW_XXX_CONNECT flags that will be
87 * directly passed to underlying port_create call.
88 * @uuid_num: number of entries in an array pointed by @uuids field
89 * @uuids: pointer to array of pointers to uuids of apps allowed to connect
90 * @extra_data: pointer to extra data associated with this ACL structure, which
91 * can be used in application specific way.
92 *
93 * Note: @uuid_num parameter can be 0 to indicate that there is no filtering by
94 * UUID and connection from any client will be accepted. In this case @uuids
95 * parameter is ignored and can be set to NULL.
96 */
97 struct ktipc_port_acl {
98 uint32_t flags;
99 uint32_t uuid_num;
100 const struct uuid** uuids;
101 const void* extra_data;
102 };
103
104 /**
105 * struct tipc_port - TIPC port descriptor
106 * @name: port name
107 * @uuid: UUID of the service
108 * @msg_max_size: max message size supported
109 * @msg_queue_len: max number of messages in queue
110 * @acl: pointer to &struct tipc_port_acl specifying ACL rules
111 * @priv: port specific private data
112 *
113 * Note: @acl is a required parameter for specifying any port even if
114 * service does not require access control.
115 *
116 * Most services should use ``&kernel_uuid`` as the value of @uuid,
117 * unless there is a legitimate reason to use a different UUID.
118 */
119 struct ktipc_port {
120 const char* name;
121 const struct uuid* uuid;
122 uint32_t msg_max_size;
123 uint32_t msg_queue_len;
124 const struct ktipc_port_acl* acl;
125 const void* priv;
126 };
127
128 /**
129 * struct ktipc_srv_ops - service specific ops (callbacks)
130 * @on_connect: is invoked when a new connection is established.
131 * @on_message: is invoked when a new message is available
132 * @on_disconnect: is invoked when the peer terminates connection
133 * @on_channel_cleanup: is invoked to cleanup user allocated state
134 * @on_send_unblocked: is invoked when the channel is unblocked for sending
135 *
136 * The overall call flow is as follow:
137 *
138 * Upon receiving a connection request from client framework accepts it and
139 * validates against configured ACL rules. If connection is allowed, the
140 * framework allocates a channel tracking structure and invokes an optional
141 * @on_connect callback if specified. The user who choose to implement this
142 * callback can allocate its own tracking structure and return pointer to that
143 * through @ctx_p parameter. After that this pointer will be associated with
144 * particular channel and it will be passed to all other callbacks.
145 *
146 * Upon receiving a message directed to particular channel, a corresponding
147 * @on_message callback is invoked so this message can be handled according
148 * with application specific protocol. The @on_message call back is a
149 * mandatory in this implementation.
150 *
151 * Upon receiving a disconnect request an optional @on_disconnect callback is
152 * invoked to indicate that peer closed connection. At this point the channel
153 * is still alive but in disconnected state, it will be closed by framework
154 * after control returns from executing this callback.
155 *
156 * The @on_channel_cleanup callback is invoked by framework to give the user
157 * a chance to release channel specific resources if allocated by
158 * @on_connect callback, after the channel have been closed. This
159 * callback is mandatory if the user implements @on_connect callback and
160 * allocates per channel state.
161 *
162 * The @on_send_unblocked callback is invoked when a channel becomes unblocked
163 * for sending after an earlier %ERR_NOT_ENOUGH_BUFFER error code returned
164 * by tipc_send1() or ipc_send_msg().
165 *
166 * Note: an application implementing these callbacks MUST not close channel
167 * received as @chan parameter directly, instead it should return an error
168 * and the channel will be closed by the framework.
169 *
170 */
171 struct ktipc_srv_ops {
172 int (*on_connect)(const struct ktipc_port* port,
173 struct handle* chan,
174 const struct uuid* peer,
175 void** ctx_p);
176
177 int (*on_message)(const struct ktipc_port* port,
178 struct handle* chan,
179 void* ctx);
180
181 void (*on_disconnect)(const struct ktipc_port* port,
182 struct handle* chan,
183 void* ctx);
184
185 void (*on_channel_cleanup)(void* ctx);
186
187 int (*on_send_unblocked)(const struct ktipc_port* port,
188 struct handle* chan,
189 void* ctx);
190 };
191
192 /**
193 * ktipc_server_add_port() - Add new port to kernel tipc server
194 * @ksrv: pointer to kernel tipc server to add port to
195 * @port: pointer to &struct ktipc_port
196 * @ops: pointer to &struct ktipc_srv_ops with service specific
197 * callbacks
198 *
199 * Note: the caller retains ownership of structures pointed by @port
200 * parameters and should not modify these structures in any way after the
201 * service has been instantiated. Also, the caller is responsible for keeping
202 * them alive while service is running.
203 *
204 * Return: 0 on success, negative error code otherwise
205 */
206 int ktipc_server_add_port(struct ktipc_server* ksrv,
207 const struct ktipc_port* port,
208 const struct ktipc_srv_ops* ops);
209
210 #define KTIPC_INTERNAL_IOV_INIT(buf, len) \
211 { .iov_base = (void*)(buf), .iov_len = (len) }
212
213 #define ktipc_internal_send(chan, arg_handles, arg_num_handles, buf0, sz0, \
214 buf1, sz1, buf2, sz2, buf3, sz3, buf4, sz4, buf5, \
215 sz5, buf6, sz6, buf7, sz7, db0, ds0, db1, ds1, \
216 db2, ds2, db3, ds3, db4, ds4, db5, ds5, db6, ds6, \
217 db7, ds7, count, rest...) \
218 ({ \
219 /* \
220 * Put the rest of the arguments in a fixed array so we get a \
221 * static error if the caller passed in too many buffers \
222 */ \
223 __UNUSED int rest_array[2 * 8] = {rest}; \
224 struct iovec_kern iov[] = { \
225 KTIPC_INTERNAL_IOV_INIT(buf0, sz0), \
226 KTIPC_INTERNAL_IOV_INIT(buf1, sz1), \
227 KTIPC_INTERNAL_IOV_INIT(buf2, sz2), \
228 KTIPC_INTERNAL_IOV_INIT(buf3, sz3), \
229 KTIPC_INTERNAL_IOV_INIT(buf4, sz4), \
230 KTIPC_INTERNAL_IOV_INIT(buf5, sz5), \
231 KTIPC_INTERNAL_IOV_INIT(buf6, sz6), \
232 KTIPC_INTERNAL_IOV_INIT(buf7, sz7), \
233 }; \
234 struct ipc_msg_kern msg = { \
235 .iov = iov, \
236 .num_iov = count, \
237 .handles = (struct handle**)(arg_handles), \
238 .num_handles = (arg_num_handles), \
239 }; \
240 ipc_send_msg((chan), &msg); \
241 })
242
243 /**
244 * ktipc_send_handles() - send a message from zero or more buffers
245 * @chan: handle of the channel to send message over
246 * @handles: pointer to an array of handles or %NULL
247 * @num_handles: size of @handles array
248 * @buffers: zero or more pairs of two arguments: a pointer to a buffer
249 * and the size of that buffer; up to 8 buffer pairs are currently
250 * supported by the implementation
251 *
252 * If there are no handles to send, @handles should be %NULL
253 * and @num_handles should be zero.
254 *
255 * Return: the total number of bytes sent on success, a negative
256 * error code otherwise.
257 */
258 #define ktipc_send_handles(chan, handles, num_handles, buffers...) \
259 ktipc_internal_send(chan, handles, num_handles, buffers, NULL, 0, NULL, 0, \
260 NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, \
261 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0)
262
263 /**
264 * ktipc_send() - send a message from zero or more buffers
265 * @chan: handle of the channel to send message over
266 * @buffers: zero or more pairs of two arguments: a pointer to a buffer
267 * and the size of that buffer; up to 8 buffer pairs are currently
268 * supported by the implementation
269 *
270 * Return: the total number of bytes sent on success, a negative
271 * error code otherwise.
272 */
273 #define ktipc_send(chan, buffers...) ktipc_send_handles(chan, NULL, 0, buffers)
274
275 /**
276 * ktipc_recv_iov() - receive message into a set of iovecs
277 * @chan: handle of the channel to receive message from
278 * @min_sz: minimum size of the message expected
279 * @iov: pointer to an array of &struct iovec_kern elements
280 * @num_iov: number of iovecs to receive
281 * @handles: pointer to an array of handles or %NULL
282 * @num_handles: size of @handles array
283 *
284 * The received message has to contain at least @min_sz bytes and
285 * fully fit into provided buffers.
286 *
287 * If there are no handles to receive, @handles should be %NULL
288 * and @num_handles should be zero.
289 *
290 * Return: the number of bytes stored into the iovecs
291 * parameter on success, a negative error code otherwise
292 */
293 int ktipc_recv_iov(struct handle* chan,
294 size_t min_sz,
295 struct iovec_kern* iov,
296 uint32_t num_iov,
297 struct handle** handles,
298 uint32_t num_handles);
299
300 #define ktipc_internal_recv(chan, min_sz, handles, num_handles, buf0, sz0, \
301 buf1, sz1, buf2, sz2, buf3, sz3, buf4, sz4, buf5, \
302 sz5, buf6, sz6, buf7, sz7, db0, ds0, db1, ds1, \
303 db2, ds2, db3, ds3, db4, ds4, db5, ds5, db6, ds6, \
304 db7, ds7, count, rest...) \
305 ({ \
306 /* \
307 * Put the rest of the arguments in a fixed array so we get a \
308 * static error if the caller passed in too many buffers \
309 */ \
310 __UNUSED int rest_array[2 * 8] = {rest}; \
311 struct iovec_kern iov[] = { \
312 KTIPC_INTERNAL_IOV_INIT(buf0, sz0), \
313 KTIPC_INTERNAL_IOV_INIT(buf1, sz1), \
314 KTIPC_INTERNAL_IOV_INIT(buf2, sz2), \
315 KTIPC_INTERNAL_IOV_INIT(buf3, sz3), \
316 KTIPC_INTERNAL_IOV_INIT(buf4, sz4), \
317 KTIPC_INTERNAL_IOV_INIT(buf5, sz5), \
318 KTIPC_INTERNAL_IOV_INIT(buf6, sz6), \
319 KTIPC_INTERNAL_IOV_INIT(buf7, sz7), \
320 }; \
321 ktipc_recv_iov((chan), (min_sz), iov, count, (handles), \
322 (num_handles)); \
323 })
324
325 /**
326 * ktipc_recv_handles() - receive a message into zero or more buffers
327 * @chan: handle of the channel to send message over
328 * @min_sz: minimum size of the message expected
329 * @handles: pointer to an array of handles or %NULL
330 * @num_handles: size of @handles array
331 * @buffers: zero or more pairs of two arguments: a pointer to a buffer
332 * and the size of that buffer; up to 8 buffer pairs are currently
333 * supported by the implementation
334 *
335 * The received message has to contain at least @min_sz bytes and
336 * fully fit into provided buffer.
337 *
338 * If there are no handles to send, @handles should be %NULL
339 * and @num_handles should be zero.
340 *
341 * Return: the number of bytes stored into the buffers pointed by @buffers
342 * on success, a negative error code otherwise
343 */
344 #define ktipc_recv_handles(chan, min_sz, handles, num_handles, buffers...) \
345 ktipc_internal_recv(chan, min_sz, handles, num_handles, buffers, NULL, 0, \
346 NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, \
347 NULL, 0, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, \
348 1, 0)
349
350 /**
351 * ktipc_recv() - receive a message into zero or more buffers
352 * @chan: handle of the channel to send message over
353 * @min_sz: minimum size of the message expected
354 * @buffers: zero or more pairs of two arguments: a pointer to a buffer
355 * and the size of that buffer; up to 8 buffer pairs are currently
356 * supported by the implementation
357 *
358 * The received message has to contain at least @min_sz bytes and
359 * fully fit into provided buffer.
360 *
361 * Return: the number of bytes stored into the buffers pointed by @buffers
362 * on success, a negative error code otherwise
363 */
364 #define ktipc_recv(chan, min_sz, buffers...) \
365 ktipc_recv_handles(chan, min_sz, NULL, 0, buffers)
366
367 __END_CDECLS
368