1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, 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
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 
25 #ifndef TRUSTY_TRUSTY_IPC_H_
26 #define TRUSTY_TRUSTY_IPC_H_
27 
28 #include <trusty/sysdeps.h>
29 #include <trusty/trusty_dev.h>
30 
31 /*
32  * handle_t is an opaque 32 bit value that is used to reference an
33  * Trusty IPC channel
34  */
35 typedef uint32_t handle_t;
36 
37 #define INVALID_IPC_HANDLE 0
38 
39 /*
40  * Error codes returned by Trusty IPC device function calls
41  */
42 enum trusty_err {
43     TRUSTY_ERR_NONE = 0,
44     TRUSTY_ERR_GENERIC = -1,
45     TRUSTY_ERR_NOT_SUPPORTED = -2,
46     TRUSTY_ERR_NO_MEMORY = -3,
47     TRUSTY_ERR_INVALID_ARGS = -4,
48     TRUSTY_ERR_SECOS_ERR = -5,
49     TRUSTY_ERR_MSG_TOO_BIG = -6,
50     TRUSTY_ERR_NO_MSG = -7,
51     TRUSTY_ERR_CHANNEL_CLOSED = -8,
52     TRUSTY_ERR_SEND_BLOCKED = -9,
53 };
54 /*
55  * Return codes for successful Trusty IPC events (failures return trusty_err)
56  */
57 enum trusty_event_result {
58     TRUSTY_EVENT_HANDLED = 1,
59     TRUSTY_EVENT_NONE = 2,
60 };
61 
62 /*
63  * Combination of these values are used for the event field
64  * of trusty_ipc_event structure.
65  */
66 enum trusty_ipc_event_type {
67     IPC_HANDLE_POLL_NONE = 0x0,
68     IPC_HANDLE_POLL_READY = 0x1,
69     IPC_HANDLE_POLL_ERROR = 0x2,
70     IPC_HANDLE_POLL_HUP = 0x4,
71     IPC_HANDLE_POLL_MSG = 0x8,
72     IPC_HANDLE_POLL_SEND_UNBLOCKED = 0x10,
73 };
74 
75 struct trusty_dev;
76 struct trusty_ipc_chan;
77 
78 /*
79  * Trusty IPC event
80  *
81  * @event:  event type
82  * @handle: handle this event is related to
83  * @cookie: cookie associated with handle
84  */
85 struct trusty_ipc_event {
86     uint32_t event;
87     uint32_t handle;
88     uint64_t cookie;
89 };
90 
91 struct trusty_ipc_iovec {
92     void* base;
93     size_t len;
94 };
95 
96 /*
97  * Trusty IPC device
98  *
99  * @buf_vaddr: virtual address of shared buffer associated with device
100  * @buf_size:  size of shared buffer
101  * @buf_ns:    physical address info of shared buffer
102  * @tdev:      trusty device
103  */
104 struct trusty_ipc_dev {
105     void* buf_vaddr;
106     size_t buf_size;
107     trusty_shared_mem_id_t buf_id;
108     struct ns_mem_page_info buf_ns;
109     struct trusty_dev* tdev;
110 };
111 
112 /*
113  * Trusty IPC event handlers.
114  */
115 struct trusty_ipc_ops {
116     int (*on_raw_event)(struct trusty_ipc_chan* chan,
117                         struct trusty_ipc_event* evt);
118     int (*on_connect_complete)(struct trusty_ipc_chan* chan);
119     int (*on_send_unblocked)(struct trusty_ipc_chan* chan);
120     int (*on_message)(struct trusty_ipc_chan* chan);
121     int (*on_disconnect)(struct trusty_ipc_chan* chan);
122 };
123 
124 /*
125  * Trusty IPC channel.
126  *
127  * @ops_ctx:  refers to additional data that may be used by trusty_ipc_ops
128  * @handle:   identifier for channel
129  * @complete: completion status of last event on channel
130  * @dev:      Trusty IPC device used by channel, initialized with
131               trusty_ipc_dev_create
132  * @ops:      callbacks for Trusty events
133  */
134 struct trusty_ipc_chan {
135     void* ops_ctx;
136     handle_t handle;
137     volatile int complete;
138     struct trusty_ipc_dev* dev;
139     struct trusty_ipc_ops* ops;
140 };
141 
142 /*
143  * Creates new Trusty IPC device on @tdev. Allocates shared buffer, and calls
144  * trusty_dev_init_ipc to register with secure side. Returns a trusty_err.
145  *
146  * @ipc_dev:  new Trusty IPC device to be initialized
147  * @tdev:     associated Trusty device
148  * @shared_buf_size: size of shared buffer to be allocated
149  */
150 int trusty_ipc_dev_create(struct trusty_ipc_dev** ipc_dev,
151                           struct trusty_dev* tdev,
152                           size_t shared_buf_size);
153 /*
154  * Shutdown @dev. Frees shared buffer, and calls trusty_dev_shutdown_ipc
155  * to shutdown on the secure side.
156  */
157 void trusty_ipc_dev_shutdown(struct trusty_ipc_dev* dev);
158 
159 /*
160  * Calls into secure OS to initiate a new connection to a Trusty IPC service.
161  * Returns handle for the new channel, a trusty_err on error.
162  *
163  * @dev:    Trusty IPC device initialized with trusty_ipc_dev_create
164  * @port:   name of port to connect to on secure side
165  * @cookie: cookie associated with new channel.
166  */
167 int trusty_ipc_dev_connect(struct trusty_ipc_dev* dev,
168                            const char* port,
169                            uint64_t cookie);
170 /*
171  * Calls into secure OS to close connection to Trusty IPC service.
172  * Returns a trusty_err.
173  *
174  * @dev:  Trusty IPC device
175  * @chan: handle for connection, opened with trusty_ipc_dev_connect
176  */
177 int trusty_ipc_dev_close(struct trusty_ipc_dev* dev, handle_t chan);
178 
179 /*
180  * Calls into secure OS to check if there is a pending event. Returns a bool.
181  *
182  * @dev:   Trusty IPC device
183  * @chan:  handle for connection. Must be 0 which indicates any connection.
184  */
185 bool trusty_ipc_dev_has_event(struct trusty_ipc_dev* dev, handle_t chan);
186 
187 /*
188  * Calls into secure OS to receive pending event. Returns a trusty_err.
189  *
190  * @dev:   Trusty IPC device
191  * @chan:  handle for connection
192  * @event: pointer to output event struct
193  */
194 int trusty_ipc_dev_get_event(struct trusty_ipc_dev* dev,
195                              handle_t chan,
196                              struct trusty_ipc_event* event);
197 /*
198  * Calls into secure OS to send message to channel. Returns a trusty_err.
199  *
200  * @dev:      Trusty IPC device
201  * @chan:     handle for connection
202  * @iovs:     contains messages to be sent
203  * @iovs_cnt: number of iovecs to be sent
204  */
205 int trusty_ipc_dev_send(struct trusty_ipc_dev* dev,
206                         handle_t chan,
207                         const struct trusty_ipc_iovec* iovs,
208                         size_t iovs_cnt);
209 /*
210  * Calls into secure OS to receive message on channel. Returns number of bytes
211  * received on success, trusty_err on failure.
212  *
213  * @dev:      Trusty IPC device
214  * @chan:     handle for connection
215  * @iovs:     contains received messages
216  * @iovs_cnt: number of iovecs received
217  */
218 int trusty_ipc_dev_recv(struct trusty_ipc_dev* dev,
219                         handle_t chan,
220                         const struct trusty_ipc_iovec* iovs,
221                         size_t iovs_cnt);
222 
223 void trusty_ipc_dev_idle(struct trusty_ipc_dev* dev, bool event_poll);
224 
225 /*
226  * Initializes @chan with default values and @dev.
227  */
228 void trusty_ipc_chan_init(struct trusty_ipc_chan* chan,
229                           struct trusty_ipc_dev* dev);
230 /*
231  * Calls trusty_ipc_dev_connect to get a handle for channel.
232  * Returns a trusty_err.
233  *
234  * @chan: channel to initialize with new handle
235  * @port: name of port to connect to on secure side
236  * @wait: flag to wait for connect to complete by polling for
237  *        IPC_HANDLE_POLL_READY event
238  */
239 int trusty_ipc_connect(struct trusty_ipc_chan* chan,
240                        const char* port,
241                        bool wait);
242 /*
243  * Calls trusty_ipc_dev_close and invalidates @chan. Returns a trusty_err.
244  */
245 int trusty_ipc_close(struct trusty_ipc_chan* chan);
246 /*
247  * Calls trusty_ipc_dev_get_event to poll @dev for events. Handles
248  * events by calling appropriate callbacks. Returns nonnegative on success.
249  */
250 int trusty_ipc_poll_for_event(struct trusty_ipc_dev* dev);
251 /*
252  * Calls trusty_ipc_dev_send to send a message. Returns a trusty_err.
253  *
254  * @chan:     handle for connection
255  * @iovs:     contains messages to be sent
256  * @iovs_cnt: number of iovecs to be sent
257  * @wait:     flag to wait for send to complete
258  */
259 int trusty_ipc_send(struct trusty_ipc_chan* chan,
260                     const struct trusty_ipc_iovec* iovs,
261                     size_t iovs_cnt,
262                     bool wait);
263 /*
264  * Calls trusty_ipc_dev_recv to receive a message. Return number of bytes
265  * received on success, trusty_err on failure.
266  *
267  * @chan:     handle for connection
268  * @iovs:     contains received messages
269  * @iovs_cnt: number of iovecs received
270  * @wait:     flag to wait for a message to receive
271  */
272 int trusty_ipc_recv(struct trusty_ipc_chan* chan,
273                     const struct trusty_ipc_iovec* iovs,
274                     size_t iovs_cnt,
275                     bool wait);
276 
277 #endif /* TRUSTY_TRUSTY_IPC_H_ */
278