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 #pragma once
18
19 #if defined(__TRUSTY__) and !defined(__QL_TIPC__)
20 #include <assert.h>
21 #include <lib/tidl/android-base/unique_fd.h>
22 #include <lib/tipc/tipc.h>
23 #include <lib/tipc/tipc_srv.h>
24 #include <lk/compiler.h>
25 #include <lk/err_ptr.h>
26 #include <stdbool.h>
27 #include <stdint.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #include <trusty_ipc.h>
31 #include <uapi/trusty_uuid.h>
32
33 #include <array>
34 #include <type_traits>
35 #include <utility>
36 #endif
37
38 #if defined(__QL_TIPC__)
39 #include <lib/tidl/tidl_ql_tipc.h>
40 #include <trusty/sysdeps.h>
41 #include <trusty/trusty_ipc.h>
42 #endif
43
44 #define TIDL_PACKED_ATTR __PACKED
45
46 namespace tidl {
47
48 #if !defined(__QL_TIPC__)
49 template <typename T, size_t N>
50 using Array = std::array<T, N>;
51
52 template <typename T>
move(T && x)53 auto&& move(T&& x) {
54 return std::move(x);
55 }
56 #endif
57
58 using Handle = handle_t;
59
60 #if defined(__QL_TIPC__)
61 class handle {
62 public:
handle()63 handle() : mFd(INVALID_IPC_HANDLE) {}
handle(Handle fd)64 handle(Handle fd) : mFd(fd) {}
~handle()65 ~handle() { (void)reset(); }
ok()66 bool ok() const { return mFd != INVALID_IPC_HANDLE; }
67 int reset();
68 int reset(Handle fd);
69 Handle get();
70
71 private:
72 Handle mFd;
73 };
74 #endif // #if defined(__QL_TIPC__)
75
76 struct TIDL_PACKED_ATTR RequestHeader {
77 uint32_t cmd;
78 uint32_t resp_payload_size;
79 };
80
81 struct TIDL_PACKED_ATTR ResponseHeader {
82 uint32_t cmd;
83 uint32_t resp_payload_size;
84 int32_t rc;
85 };
86
87 #if !defined(__QL_TIPC__)
88 class TIDL_PACKED_ATTR ParcelFileDescriptor {
89 public:
90 android::base::unique_fd handle;
91
92 // Handle methods
93 static constexpr uint32_t num_handles = 1;
send_handles(handle_t * & hptr)94 void send_handles(handle_t*& hptr) { *hptr++ = handle.release(); }
recv_handles(handle_t * & hptr)95 void recv_handles(handle_t*& hptr) { handle.reset(*hptr++); }
96
97 private:
98 // struct trusty_shm from Android has 2 32-bit fields
99 // so we reserve the space for the second one here
100 __UNUSED uint32_t reserved;
101 };
102 STATIC_ASSERT(sizeof(ParcelFileDescriptor) == 2 * sizeof(uint32_t));
103 #endif
104
105 // Default implementation for all types without handles
106 template <typename T, typename = void>
107 class HandleOps {
108 public:
109 static constexpr uint32_t num_handles = 0;
send_handles(void *,handle_t * & hptr)110 static void send_handles(void*, handle_t*& hptr) {}
recv_handles(void *,handle_t * & hptr)111 static void recv_handles(void*, handle_t*& hptr) {}
112 };
113
114 // HasHandleMembers<T> is equal to void for all types T
115 // that have the 3 members we need for HandleOps, and
116 // doesn't exist for any other types (triggering SFINAE below)
117 #if !defined(__QL_TIPC__)
118 template <typename T>
119 using HasHandleMembers = std::void_t<
120 decltype(T::num_handles),
121 decltype(std::declval<T>().send_handles(std::declval<handle_t*&>())),
122 decltype(std::declval<T>().recv_handles(std::declval<handle_t*&>()))>;
123
124 // Specialization for types that implement their own handle methods
125 template <typename T>
126 class HandleOps<T, HasHandleMembers<T>> {
127 public:
128 static constexpr uint32_t num_handles = T::num_handles;
send_handles(void * x,handle_t * & hptr)129 static void send_handles(void* x, handle_t*& hptr) {
130 reinterpret_cast<T*>(x)->send_handles(hptr);
131 }
recv_handles(void * x,handle_t * & hptr)132 static void recv_handles(void* x, handle_t*& hptr) {
133 reinterpret_cast<T*>(x)->recv_handles(hptr);
134 }
135 };
136 #endif
137
138 class Payload {
139 public:
Payload()140 Payload() : mData(nullptr), mSize(0) {}
Payload(uint8_t * data,uint32_t size)141 Payload(uint8_t* data, uint32_t size) : mData(data), mSize(size) {}
142 Payload(const Payload&) = delete;
143 Payload& operator=(const Payload&) = delete;
144
Payload(Payload && other)145 Payload(Payload&& other) : mData(other.mData), mSize(other.mSize) {
146 other.reset();
147 }
148
149 Payload& operator=(Payload&& other) {
150 mData = other.mData;
151 mSize = other.mSize;
152 other.reset();
153 return *this;
154 }
155
data()156 const uint8_t* data() const { return mData; }
157
data()158 uint8_t* data() { return mData; }
159
size()160 uint32_t size() const { return mSize; }
161
resize(uint32_t size)162 void resize(uint32_t size) { mSize = size; }
163
164 private:
165 uint8_t* mData;
166 uint32_t mSize;
167
reset()168 void reset() {
169 mData = nullptr;
170 mSize = 0;
171 }
172 };
173
174 template <uint32_t S>
175 class FixedPayload {
176 static const uint32_t mSize = S;
177
178 public:
FixedPayload()179 FixedPayload() {}
FixedPayload(uint8_t * data)180 FixedPayload(uint8_t* data) { memcpy(mData, data, S); }
181
FixedPayload(const FixedPayload<S> & payload)182 FixedPayload(const FixedPayload<S>& payload) {
183 memcpy(mData, payload.data(), S);
184 }
185
186 FixedPayload& operator=(const FixedPayload<S>& payload) {
187 memcpy(mData, payload.data(), S);
188 return *this;
189 }
190
191 FixedPayload<S>& operator=(FixedPayload<S>&& other) {
192 memcpy(mData, other.mData, S);
193 return *this;
194 }
195
data()196 const uint8_t* data() const { return mData; }
197
data()198 uint8_t* data() { return mData; }
199
size()200 uint32_t size() const { return mSize; }
201
202 private:
203 uint8_t mData[S];
204 };
205
206 #if !defined(__QL_TIPC__)
207 class Service {
208 public:
209 using Port = struct tipc_port;
210 using PortAcl = struct tipc_port_acl;
211 using Ops = struct tipc_srv_ops;
212 using HandleSet = struct tipc_hset*;
213
214 Service() = delete;
Service(const char *,const char * port_name,uint32_t msg_max_size,const PortAcl * acl,const Ops * ops)215 Service(const char*,
216 const char* port_name,
217 uint32_t msg_max_size,
218 const PortAcl* acl,
219 const Ops* ops)
220 : mPort(), mOpsPtr(ops) {
221 mPort.name = port_name;
222 mPort.msg_max_size = msg_max_size;
223 mPort.msg_queue_len = 1;
224 mPort.acl = acl;
225 mPort.priv = this;
226 }
227
set_max_channels(uint32_t max_chan_cnt)228 void set_max_channels(uint32_t max_chan_cnt) {
229 mMaxChannels = max_chan_cnt;
230 }
231
add_service(HandleSet hset)232 int add_service(HandleSet hset) {
233 return tipc_add_service(hset, &mPort, 1, mMaxChannels, mOpsPtr);
234 }
235
run_service(void)236 int run_service(void) {
237 HandleSet hset = tipc_hset_create();
238 if (IS_ERR(hset)) {
239 return PTR_ERR(hset);
240 }
241 int rc = add_service(hset);
242 if (rc < 0) {
243 return rc;
244 }
245 return tipc_run_event_loop(hset);
246 }
247
248 protected:
get_payload_buffer(Payload &,uint32_t size,bool)249 virtual int get_payload_buffer(Payload&, uint32_t size, bool) {
250 if (!size) {
251 return NO_ERROR;
252 }
253 return ERR_NOT_IMPLEMENTED;
254 }
255
free_payload_buffer(Payload)256 virtual void free_payload_buffer(Payload) {}
257
258 Port mPort;
259 uint32_t mMaxChannels = 1;
260
261 private:
262 const Ops* mOpsPtr;
263 };
264 #endif // #if !defined(__QL_TIPC__)
265
266 namespace ipc {
267
268 #if !defined(__QL_TIPC__)
269 int connect(const char* path, uint32_t flags, android::base::unique_fd& out_fd);
270 #else
271 int connect(const char* path, uint32_t flags, ::tidl::handle& out_fd);
272 #endif
273
274 int send(handle_t chan,
275 const void* buf,
276 size_t len,
277 handle_t* handles,
278 uint32_t num_handles);
279 int recv(handle_t chan,
280 size_t min_sz,
281 void* buf,
282 size_t buf_sz,
283 handle_t* handles,
284 uint32_t num_handles);
285 int send(handle_t chan,
286 const void* hdr,
287 size_t hdr_len,
288 const void* payload1,
289 size_t payload1_len,
290 handle_t* handles,
291 uint32_t num_handles);
292 int recv(handle_t chan,
293 size_t min_sz,
294 void* buf1,
295 size_t buf1_sz,
296 void* buf2,
297 size_t buf2_sz,
298 handle_t* handles,
299 uint32_t num_handles);
300 int send(handle_t chan,
301 const void* hdr,
302 size_t hdr_len,
303 const void* payload1,
304 size_t payload1_len,
305 const void* payload2,
306 size_t payload2_len,
307 handle_t* handles,
308 uint32_t num_handles);
309 int recv(handle_t chan,
310 size_t min_sz,
311 void* buf1,
312 size_t buf1_sz,
313 void* buf2,
314 size_t buf2_sz,
315 void* buf3,
316 size_t buf3_sz,
317 handle_t* handles,
318 uint32_t num_handles);
319 int wait_for_msg(handle_t chan);
320 } // namespace ipc
321
322 } // namespace tidl
323