|
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: set ts=8 sts=4 et sw=4 tw=99: |
|
3 * This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifdef __APPLE__ |
|
8 |
|
9 #include "sharkctl.h" |
|
10 #include <stddef.h> |
|
11 #include <stdio.h> |
|
12 #include <stdlib.h> |
|
13 #include <unistd.h> |
|
14 |
|
15 #include "jsutil.h" |
|
16 |
|
17 #define SHARK_MSG_ACQUIRE 0x29a |
|
18 #define SHARK_MSG_RELEASE 0x29b |
|
19 #define SHARK_MSG_STOP 0x29c |
|
20 #define SHARK_MSG_START 0x29d |
|
21 |
|
22 #define RECV_SIZEOF(ty) offsetof(ty, out) |
|
23 |
|
24 // Private API in libSystem.dylib |
|
25 extern "C" void bootstrap_look_up(mach_port_t special_port, const char *name, |
|
26 mach_port_t *dest_port); |
|
27 |
|
28 struct chud_client_acquire_msg { |
|
29 mach_msg_header_t hdr; |
|
30 uint32_t unk0; // always 0 |
|
31 uint32_t unk1; // always 1 |
|
32 uint32_t pid; |
|
33 uint32_t out[2]; |
|
34 }; |
|
35 |
|
36 struct chud_client_start_msg { |
|
37 mach_msg_header_t hdr; |
|
38 uint32_t unk0; // always 1 |
|
39 uint32_t name0; |
|
40 uint32_t arg2; // always 6 |
|
41 uint8_t unk1; // always 0 |
|
42 uint8_t unk2; // always 1 |
|
43 uint8_t unk3; // uninitialized |
|
44 uint8_t unk4; // always 1 |
|
45 uint32_t unk5; // always 0 |
|
46 uint32_t unk6; // always 1 |
|
47 uint32_t name1; // same as name0 |
|
48 }; |
|
49 |
|
50 struct chud_client_stop_msg { |
|
51 mach_msg_header_t hdr; |
|
52 uint32_t out[5]; |
|
53 }; |
|
54 |
|
55 struct chud_client_release_msg { |
|
56 mach_msg_header_t hdr; |
|
57 uint32_t unk0; // always 0 |
|
58 uint32_t unk1; // always 1 |
|
59 uint32_t pid; |
|
60 uint32_t out[2]; |
|
61 }; |
|
62 |
|
63 static mach_port_t |
|
64 CreatePort(void) |
|
65 { |
|
66 mach_port_t bootstrap_port, shark_port = 0; |
|
67 task_get_special_port(mach_task_self(), TASK_BOOTSTRAP_PORT, |
|
68 &bootstrap_port); |
|
69 bootstrap_look_up(bootstrap_port, "CHUD_IPC", &shark_port); |
|
70 return shark_port; |
|
71 } |
|
72 |
|
73 static mach_msg_return_t |
|
74 Connect(mach_port_t shark_port) |
|
75 { |
|
76 mach_port_t reply_port = mig_get_reply_port(); |
|
77 |
|
78 struct chud_client_acquire_msg msg; |
|
79 msg.hdr.msgh_bits = 0x1513; |
|
80 msg.hdr.msgh_size = sizeof(mach_msg_header_t); |
|
81 msg.hdr.msgh_remote_port = shark_port; |
|
82 msg.hdr.msgh_local_port = reply_port; |
|
83 msg.hdr.msgh_reserved = 0; |
|
84 msg.hdr.msgh_id = SHARK_MSG_ACQUIRE; |
|
85 msg.unk0 = 0; |
|
86 msg.unk1 = 1; |
|
87 msg.pid = getpid(); |
|
88 |
|
89 JS_ASSERT(RECV_SIZEOF(struct chud_client_acquire_msg) == 0x24); |
|
90 JS_ASSERT(sizeof(msg) == 0x2c); |
|
91 mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG, |
|
92 RECV_SIZEOF(struct chud_client_acquire_msg), |
|
93 sizeof(msg), reply_port, 0, 0); |
|
94 mig_dealloc_reply_port(reply_port); |
|
95 return result; |
|
96 } |
|
97 |
|
98 static mach_msg_return_t |
|
99 Start(mach_port_t shark_port, uint32_t name) |
|
100 { |
|
101 mach_port_t reply_port = mig_get_reply_port(); |
|
102 |
|
103 struct chud_client_start_msg msg; |
|
104 msg.hdr.msgh_bits = 0x80001513; |
|
105 msg.hdr.msgh_size = sizeof(mach_msg_header_t); |
|
106 msg.hdr.msgh_remote_port = shark_port; |
|
107 msg.hdr.msgh_local_port = reply_port; |
|
108 msg.hdr.msgh_reserved = 0; |
|
109 msg.hdr.msgh_id = SHARK_MSG_START; |
|
110 msg.unk0 = 1; |
|
111 msg.name0 = name; |
|
112 msg.arg2 = 6; |
|
113 msg.unk1 = 0; |
|
114 msg.unk2 = 1; |
|
115 msg.unk3 = 0; |
|
116 msg.unk4 = 1; |
|
117 msg.unk5 = 0; |
|
118 msg.unk6 = 1; |
|
119 msg.name1 = name; |
|
120 |
|
121 JS_ASSERT(sizeof(msg) == 0x34); |
|
122 mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG, |
|
123 sizeof(msg), 0x30, reply_port, 0, 0); |
|
124 mig_dealloc_reply_port(reply_port); |
|
125 return result; |
|
126 } |
|
127 |
|
128 mach_msg_return_t |
|
129 Stop(mach_port_t shark_port) |
|
130 { |
|
131 mach_port_t reply_port = mig_get_reply_port(); |
|
132 |
|
133 struct chud_client_stop_msg msg; |
|
134 msg.hdr.msgh_bits = 0x1513; |
|
135 msg.hdr.msgh_size = sizeof(mach_msg_header_t); |
|
136 msg.hdr.msgh_remote_port = shark_port; |
|
137 msg.hdr.msgh_local_port = reply_port; |
|
138 msg.hdr.msgh_reserved = 0; |
|
139 msg.hdr.msgh_id = SHARK_MSG_STOP; |
|
140 |
|
141 JS_ASSERT(RECV_SIZEOF(struct chud_client_stop_msg) == 0x18); |
|
142 JS_ASSERT(sizeof(msg) == 0x2c); |
|
143 mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG, |
|
144 RECV_SIZEOF(struct chud_client_stop_msg), |
|
145 sizeof(msg), reply_port, 0, 0); |
|
146 mig_dealloc_reply_port(reply_port); |
|
147 return result; |
|
148 } |
|
149 |
|
150 static mach_msg_return_t |
|
151 Disconnect(mach_port_t shark_port) |
|
152 { |
|
153 mach_port_t reply_port = mig_get_reply_port(); |
|
154 |
|
155 struct chud_client_release_msg msg; |
|
156 msg.hdr.msgh_bits = 0x1513; |
|
157 msg.hdr.msgh_size = sizeof(mach_msg_header_t); |
|
158 msg.hdr.msgh_remote_port = shark_port; |
|
159 msg.hdr.msgh_local_port = reply_port; |
|
160 msg.hdr.msgh_reserved = 0; |
|
161 msg.hdr.msgh_id = SHARK_MSG_RELEASE; |
|
162 msg.unk0 = 0; |
|
163 msg.unk1 = 1; |
|
164 msg.pid = getpid(); |
|
165 |
|
166 JS_ASSERT(RECV_SIZEOF(struct chud_client_release_msg) == 0x24); |
|
167 JS_ASSERT(sizeof(msg) == 0x2c); |
|
168 mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG, |
|
169 RECV_SIZEOF(struct chud_client_release_msg), |
|
170 sizeof(msg), reply_port, 0, 0); |
|
171 mig_dealloc_reply_port(reply_port); |
|
172 return result; |
|
173 } |
|
174 |
|
175 static mach_port_t shark_port = 0; |
|
176 static bool connected = false; |
|
177 static bool running = false; |
|
178 |
|
179 namespace Shark { |
|
180 |
|
181 bool |
|
182 Start() |
|
183 { |
|
184 if (!shark_port && !(shark_port = CreatePort())) |
|
185 return false; |
|
186 if (!connected && Connect(shark_port)) |
|
187 return false; |
|
188 connected = true; |
|
189 if (!running && ::Start(shark_port, 0xdeadbeef)) |
|
190 return false; |
|
191 return running = true; |
|
192 } |
|
193 |
|
194 void |
|
195 Stop() |
|
196 { |
|
197 if (!shark_port || !connected) |
|
198 return; |
|
199 ::Stop(shark_port); |
|
200 running = false; |
|
201 Disconnect(shark_port); |
|
202 connected = false; |
|
203 } |
|
204 |
|
205 } |
|
206 |
|
207 #endif |