Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / sharkctl.cpp
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim: set ts=8 sw=4 et tw=80:
3  *
4  * ***** BEGIN LICENSE BLOCK *****
5  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * Copyright (C) 2010 Patrick Walton <pcwalton@mimiga.net>
18  *
19  * Contributor(s):
20  *      Andreas Gal <gal@mozilla.com>
21  *
22  * Alternatively, the contents of this file may be used under the terms of
23  * either of the GNU General Public License Version 2 or later (the "GPL"),
24  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
25  * in which case the provisions of the GPL or the LGPL are applicable instead
26  * of those above. If you wish to allow use of your version of this file only
27  * under the terms of either the GPL or the LGPL, and not to allow others to
28  * use your version of this file under the terms of the MPL, indicate your
29  * decision by deleting the provisions above and replace them with the notice
30  * and other provisions required by the GPL or the LGPL. If you do not delete
31  * the provisions above, a recipient may use your version of this file under
32  * the terms of any one of the MPL, the GPL or the LGPL.
33  *
34  * ***** END LICENSE BLOCK ***** */
35
36 #ifdef __APPLE__
37
38 #include "sharkctl.h"
39
40 #include "sharkctl.h"
41 #include <stddef.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <unistd.h>
45
46 #include "jsutil.h"
47
48 #define SHARK_MSG_ACQUIRE   0x29a
49 #define SHARK_MSG_RELEASE   0x29b
50 #define SHARK_MSG_STOP      0x29c
51 #define SHARK_MSG_START     0x29d
52
53 #define RECV_SIZEOF(ty) offsetof(ty, out)
54
55 // Private API in libSystem.dylib
56 extern "C" void bootstrap_look_up(mach_port_t special_port, const char *name,
57                                   mach_port_t *dest_port);
58
59 struct chud_client_acquire_msg {
60     mach_msg_header_t hdr;
61     uint32_t unk0;          // always 0
62     uint32_t unk1;          // always 1
63     uint32_t pid;
64     uint32_t out[2];
65 };
66
67 struct chud_client_start_msg {
68     mach_msg_header_t hdr;
69     uint32_t unk0;          // always 1
70     uint32_t name0;
71     uint32_t arg2;          // always 6
72     uint8_t unk1;           // always 0
73     uint8_t unk2;           // always 1
74     uint8_t unk3;           // uninitialized
75     uint8_t unk4;           // always 1
76     uint32_t unk5;          // always 0
77     uint32_t unk6;          // always 1
78     uint32_t name1;         // same as name0
79 };
80
81 struct chud_client_stop_msg {
82     mach_msg_header_t hdr;
83     uint32_t out[5];
84 };
85
86 struct chud_client_release_msg {
87     mach_msg_header_t hdr;
88     uint32_t unk0;          // always 0
89     uint32_t unk1;          // always 1
90     uint32_t pid;
91     uint32_t out[2];
92 };
93
94 static mach_port_t
95 CreatePort(void)
96 {
97     mach_port_t bootstrap_port, shark_port = 0;
98     task_get_special_port(mach_task_self(), TASK_BOOTSTRAP_PORT,
99                           &bootstrap_port);
100     bootstrap_look_up(bootstrap_port, "CHUD_IPC", &shark_port);
101     return shark_port;
102 }
103
104 static mach_msg_return_t
105 Connect(mach_port_t shark_port)
106 {
107     mach_port_t reply_port = mig_get_reply_port();
108
109     struct chud_client_acquire_msg msg;
110     msg.hdr.msgh_bits = 0x1513;
111     msg.hdr.msgh_size = sizeof(mach_msg_header_t);
112     msg.hdr.msgh_remote_port = shark_port;
113     msg.hdr.msgh_local_port = reply_port;
114     msg.hdr.msgh_reserved = 0;
115     msg.hdr.msgh_id = SHARK_MSG_ACQUIRE;
116     msg.unk0 = 0;
117     msg.unk1 = 1;
118     msg.pid = getpid();
119
120     JS_ASSERT(RECV_SIZEOF(struct chud_client_acquire_msg) == 0x24);
121     JS_ASSERT(sizeof(msg) == 0x2c);
122     mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG,
123                                         RECV_SIZEOF(struct chud_client_acquire_msg),
124                                         sizeof(msg), reply_port, 0, 0);
125     mig_dealloc_reply_port(reply_port);
126     return result;
127 }
128
129 static mach_msg_return_t
130 Start(mach_port_t shark_port, uint32_t name)
131 {
132     mach_port_t reply_port = mig_get_reply_port();
133
134     struct chud_client_start_msg msg;
135     msg.hdr.msgh_bits = 0x80001513;
136     msg.hdr.msgh_size = sizeof(mach_msg_header_t);
137     msg.hdr.msgh_remote_port = shark_port;
138     msg.hdr.msgh_local_port = reply_port;
139     msg.hdr.msgh_reserved = 0;
140     msg.hdr.msgh_id = SHARK_MSG_START;
141     msg.unk0 = 1;
142     msg.name0 = name;
143     msg.arg2 = 6;
144     msg.unk1 = 0;
145     msg.unk2 = 1;
146     msg.unk3 = 0;
147     msg.unk4 = 1;
148     msg.unk5 = 0;
149     msg.unk6 = 1;
150     msg.name1 = name;
151
152     JS_ASSERT(sizeof(msg) == 0x34);
153     mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG,
154                                         sizeof(msg), 0x30, reply_port, 0, 0);
155     mig_dealloc_reply_port(reply_port);
156     return result;
157 }
158
159 mach_msg_return_t
160 Stop(mach_port_t shark_port)
161 {
162     mach_port_t reply_port = mig_get_reply_port();
163
164     struct chud_client_stop_msg msg;
165     msg.hdr.msgh_bits = 0x1513;
166     msg.hdr.msgh_size = sizeof(mach_msg_header_t);
167     msg.hdr.msgh_remote_port = shark_port;
168     msg.hdr.msgh_local_port = reply_port;
169     msg.hdr.msgh_reserved = 0;
170     msg.hdr.msgh_id = SHARK_MSG_STOP;
171
172     JS_ASSERT(RECV_SIZEOF(struct chud_client_stop_msg) == 0x18);
173     JS_ASSERT(sizeof(msg) == 0x2c);
174     mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG,
175                                         RECV_SIZEOF(struct chud_client_stop_msg),
176                                         sizeof(msg), reply_port, 0, 0);
177     mig_dealloc_reply_port(reply_port);
178     return result;
179 }
180
181 static mach_msg_return_t
182 Disconnect(mach_port_t shark_port)
183 {
184     mach_port_t reply_port = mig_get_reply_port();
185
186     struct chud_client_release_msg msg;
187     msg.hdr.msgh_bits = 0x1513;
188     msg.hdr.msgh_size = sizeof(mach_msg_header_t);
189     msg.hdr.msgh_remote_port = shark_port;
190     msg.hdr.msgh_local_port = reply_port;
191     msg.hdr.msgh_reserved = 0;
192     msg.hdr.msgh_id = SHARK_MSG_RELEASE;
193     msg.unk0 = 0;
194     msg.unk1 = 1;
195     msg.pid = getpid();
196
197     JS_ASSERT(RECV_SIZEOF(struct chud_client_release_msg) == 0x24);
198     JS_ASSERT(sizeof(msg) == 0x2c);
199     mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG,
200                                         RECV_SIZEOF(struct chud_client_release_msg),
201                                         sizeof(msg), reply_port, 0, 0);
202     mig_dealloc_reply_port(reply_port);
203     return result;
204 }
205
206 static mach_port_t shark_port = 0;
207 static bool connected = false;
208 static bool running = false;
209
210 namespace Shark {
211
212 bool
213 Start()
214 {
215     if (!shark_port && !(shark_port = CreatePort()))
216         return false;
217     if (!connected && Connect(shark_port))
218         return false;
219     connected = true;
220     if (!running && ::Start(shark_port, 0xdeadbeef))
221         return false;
222     return running = true;
223 };
224
225 void
226 Stop()
227 {
228     if (!shark_port || !connected)
229         return;
230     ::Stop(shark_port);
231     running = false;
232     Disconnect(shark_port);
233     connected = false;
234 }
235
236 }
237
238 #endif