1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <lib/tidl/android-base/unique_fd.h>
18 #include <trusty_ipc.h>
19 #include <uapi/err.h>
20
21 namespace tidl {
22 namespace ipc {
23
connect(const char * path,uint32_t flags,android::base::unique_fd & out_fd)24 int connect(const char* path,
25 uint32_t flags,
26 android::base::unique_fd& out_fd) {
27 int rc = ::connect(path, flags);
28 if (rc < 0) {
29 return rc;
30 }
31
32 out_fd.reset(static_cast<handle_t>(rc));
33 return NO_ERROR;
34 }
35
send(handle_t chan,const void * buf,size_t len,handle_t * handles,uint32_t num_handles)36 int send(handle_t chan,
37 const void* buf,
38 size_t len,
39 handle_t* handles,
40 uint32_t num_handles) {
41 struct iovec iov = {
42 .iov_base = (void*)buf,
43 .iov_len = len,
44 };
45 ipc_msg_t msg = {
46 .num_iov = 1,
47 .iov = &iov,
48 .num_handles = num_handles,
49 .handles = handles,
50 };
51 return send_msg(chan, &msg);
52 }
53
recv(handle_t chan,size_t min_sz,void * buf,size_t buf_sz,handle_t * handles,uint32_t num_handles)54 int recv(handle_t chan,
55 size_t min_sz,
56 void* buf,
57 size_t buf_sz,
58 handle_t* handles,
59 uint32_t num_handles) {
60 int rc;
61 ipc_msg_info_t msg_inf;
62
63 rc = get_msg(chan, &msg_inf);
64 if (rc)
65 return rc;
66
67 if (msg_inf.len < min_sz || msg_inf.len > buf_sz) {
68 /* unexpected msg size: buffer too small or too big */
69 rc = ERR_BAD_LEN;
70 } else {
71 struct iovec iov = {
72 .iov_base = buf,
73 .iov_len = buf_sz,
74 };
75 ipc_msg_t msg = {
76 .num_iov = 1,
77 .iov = &iov,
78 .num_handles = num_handles,
79 .handles = handles,
80 };
81 rc = read_msg(chan, msg_inf.id, 0, &msg);
82 }
83
84 put_msg(chan, msg_inf.id);
85 return rc;
86 }
87
send(handle_t chan,const void * hdr,size_t hdr_len,const void * payload1,size_t payload1_len,handle_t * handles,uint32_t num_handles)88 int send(handle_t chan,
89 const void* hdr,
90 size_t hdr_len,
91 const void* payload1,
92 size_t payload1_len,
93 handle_t* handles,
94 uint32_t num_handles) {
95 struct iovec iovs[] = {
96 {
97 .iov_base = (void*)hdr,
98 .iov_len = hdr_len,
99 },
100 {
101 .iov_base = (void*)payload1,
102 .iov_len = payload1_len,
103 },
104 };
105 ipc_msg_t msg = {
106 .num_iov = static_cast<uint32_t>(countof(iovs)),
107 .iov = iovs,
108 .num_handles = num_handles,
109 .handles = handles,
110 };
111 return send_msg(chan, &msg);
112 }
113
recv(handle_t chan,size_t min_sz,void * buf1,size_t buf1_sz,void * buf2,size_t buf2_sz,handle_t * handles,uint32_t num_handles)114 int recv(handle_t chan,
115 size_t min_sz,
116 void* buf1,
117 size_t buf1_sz,
118 void* buf2,
119 size_t buf2_sz,
120 handle_t* handles,
121 uint32_t num_handles) {
122 int rc;
123 ipc_msg_info_t msg_inf;
124
125 rc = get_msg(chan, &msg_inf);
126 if (rc)
127 return rc;
128
129 if (msg_inf.len < min_sz || (msg_inf.len > (buf1_sz + buf2_sz))) {
130 /* unexpected msg size: buffer too small or too big */
131 rc = ERR_BAD_LEN;
132 } else {
133 struct iovec iovs[] = {
134 {
135 .iov_base = buf1,
136 .iov_len = buf1_sz,
137 },
138 {
139 .iov_base = buf2,
140 .iov_len = buf2_sz,
141 },
142 };
143 ipc_msg_t msg = {
144 .num_iov = static_cast<uint32_t>(countof(iovs)),
145 .iov = iovs,
146 .num_handles = num_handles,
147 .handles = handles,
148 };
149 rc = read_msg(chan, msg_inf.id, 0, &msg);
150 }
151
152 put_msg(chan, msg_inf.id);
153 return rc;
154 }
155
send(handle_t chan,const void * hdr,size_t hdr_len,const void * payload1,size_t payload1_len,const void * payload2,size_t payload2_len,handle_t * handles,uint32_t num_handles)156 int send(handle_t chan,
157 const void* hdr,
158 size_t hdr_len,
159 const void* payload1,
160 size_t payload1_len,
161 const void* payload2,
162 size_t payload2_len,
163 handle_t* handles,
164 uint32_t num_handles) {
165 struct iovec iovs[] = {
166 {
167 .iov_base = (void*)hdr,
168 .iov_len = hdr_len,
169 },
170 {
171 .iov_base = (void*)payload1,
172 .iov_len = payload1_len,
173 },
174 {
175 .iov_base = (void*)payload2,
176 .iov_len = payload2_len,
177 },
178 };
179 ipc_msg_t msg = {
180 .num_iov = static_cast<uint32_t>(countof(iovs)),
181 .iov = iovs,
182 .num_handles = num_handles,
183 .handles = handles,
184 };
185 return send_msg(chan, &msg);
186 }
187
recv(handle_t chan,size_t min_sz,void * buf1,size_t buf1_sz,void * buf2,size_t buf2_sz,void * buf3,size_t buf3_sz,handle_t * handles,uint32_t num_handles)188 int recv(handle_t chan,
189 size_t min_sz,
190 void* buf1,
191 size_t buf1_sz,
192 void* buf2,
193 size_t buf2_sz,
194 void* buf3,
195 size_t buf3_sz,
196 handle_t* handles,
197 uint32_t num_handles) {
198 int rc;
199 ipc_msg_info_t msg_inf;
200
201 rc = get_msg(chan, &msg_inf);
202 if (rc)
203 return rc;
204
205 if (msg_inf.len < min_sz || (msg_inf.len > (buf1_sz + buf2_sz + buf3_sz))) {
206 /* unexpected msg size: buffer too small or too big */
207 rc = ERR_BAD_LEN;
208 } else {
209 struct iovec iovs[] = {
210 {
211 .iov_base = buf1,
212 .iov_len = buf1_sz,
213 },
214 {
215 .iov_base = buf2,
216 .iov_len = buf2_sz,
217 },
218 {
219 .iov_base = buf3,
220 .iov_len = buf3_sz,
221 },
222 };
223 ipc_msg_t msg = {
224 .num_iov = static_cast<uint32_t>(countof(iovs)),
225 .iov = iovs,
226 .num_handles = num_handles,
227 .handles = handles,
228 };
229 rc = read_msg(chan, msg_inf.id, 0, &msg);
230 }
231
232 put_msg(chan, msg_inf.id);
233 return rc;
234 }
235
wait_for_msg(handle_t chan)236 int wait_for_msg(handle_t chan) {
237 uevent_t event = UEVENT_INITIAL_VALUE(event);
238 int rc = wait(chan, &event, INFINITE_TIME);
239 if (rc != NO_ERROR) {
240 return rc;
241 }
242
243 if (event.event & IPC_HANDLE_POLL_HUP) {
244 return ERR_CHANNEL_CLOSED;
245 }
246 if (!(event.event & IPC_HANDLE_POLL_MSG)) {
247 return ERR_IO;
248 }
249
250 return NO_ERROR;
251 }
252
253 } // namespace ipc
254 } // namespace tidl
255