michael@0: /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifdef __APPLE__ michael@0: michael@0: #include "sharkctl.h" michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: michael@0: #include "jsutil.h" michael@0: michael@0: #define SHARK_MSG_ACQUIRE 0x29a michael@0: #define SHARK_MSG_RELEASE 0x29b michael@0: #define SHARK_MSG_STOP 0x29c michael@0: #define SHARK_MSG_START 0x29d michael@0: michael@0: #define RECV_SIZEOF(ty) offsetof(ty, out) michael@0: michael@0: // Private API in libSystem.dylib michael@0: extern "C" void bootstrap_look_up(mach_port_t special_port, const char *name, michael@0: mach_port_t *dest_port); michael@0: michael@0: struct chud_client_acquire_msg { michael@0: mach_msg_header_t hdr; michael@0: uint32_t unk0; // always 0 michael@0: uint32_t unk1; // always 1 michael@0: uint32_t pid; michael@0: uint32_t out[2]; michael@0: }; michael@0: michael@0: struct chud_client_start_msg { michael@0: mach_msg_header_t hdr; michael@0: uint32_t unk0; // always 1 michael@0: uint32_t name0; michael@0: uint32_t arg2; // always 6 michael@0: uint8_t unk1; // always 0 michael@0: uint8_t unk2; // always 1 michael@0: uint8_t unk3; // uninitialized michael@0: uint8_t unk4; // always 1 michael@0: uint32_t unk5; // always 0 michael@0: uint32_t unk6; // always 1 michael@0: uint32_t name1; // same as name0 michael@0: }; michael@0: michael@0: struct chud_client_stop_msg { michael@0: mach_msg_header_t hdr; michael@0: uint32_t out[5]; michael@0: }; michael@0: michael@0: struct chud_client_release_msg { michael@0: mach_msg_header_t hdr; michael@0: uint32_t unk0; // always 0 michael@0: uint32_t unk1; // always 1 michael@0: uint32_t pid; michael@0: uint32_t out[2]; michael@0: }; michael@0: michael@0: static mach_port_t michael@0: CreatePort(void) michael@0: { michael@0: mach_port_t bootstrap_port, shark_port = 0; michael@0: task_get_special_port(mach_task_self(), TASK_BOOTSTRAP_PORT, michael@0: &bootstrap_port); michael@0: bootstrap_look_up(bootstrap_port, "CHUD_IPC", &shark_port); michael@0: return shark_port; michael@0: } michael@0: michael@0: static mach_msg_return_t michael@0: Connect(mach_port_t shark_port) michael@0: { michael@0: mach_port_t reply_port = mig_get_reply_port(); michael@0: michael@0: struct chud_client_acquire_msg msg; michael@0: msg.hdr.msgh_bits = 0x1513; michael@0: msg.hdr.msgh_size = sizeof(mach_msg_header_t); michael@0: msg.hdr.msgh_remote_port = shark_port; michael@0: msg.hdr.msgh_local_port = reply_port; michael@0: msg.hdr.msgh_reserved = 0; michael@0: msg.hdr.msgh_id = SHARK_MSG_ACQUIRE; michael@0: msg.unk0 = 0; michael@0: msg.unk1 = 1; michael@0: msg.pid = getpid(); michael@0: michael@0: JS_ASSERT(RECV_SIZEOF(struct chud_client_acquire_msg) == 0x24); michael@0: JS_ASSERT(sizeof(msg) == 0x2c); michael@0: mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG, michael@0: RECV_SIZEOF(struct chud_client_acquire_msg), michael@0: sizeof(msg), reply_port, 0, 0); michael@0: mig_dealloc_reply_port(reply_port); michael@0: return result; michael@0: } michael@0: michael@0: static mach_msg_return_t michael@0: Start(mach_port_t shark_port, uint32_t name) michael@0: { michael@0: mach_port_t reply_port = mig_get_reply_port(); michael@0: michael@0: struct chud_client_start_msg msg; michael@0: msg.hdr.msgh_bits = 0x80001513; michael@0: msg.hdr.msgh_size = sizeof(mach_msg_header_t); michael@0: msg.hdr.msgh_remote_port = shark_port; michael@0: msg.hdr.msgh_local_port = reply_port; michael@0: msg.hdr.msgh_reserved = 0; michael@0: msg.hdr.msgh_id = SHARK_MSG_START; michael@0: msg.unk0 = 1; michael@0: msg.name0 = name; michael@0: msg.arg2 = 6; michael@0: msg.unk1 = 0; michael@0: msg.unk2 = 1; michael@0: msg.unk3 = 0; michael@0: msg.unk4 = 1; michael@0: msg.unk5 = 0; michael@0: msg.unk6 = 1; michael@0: msg.name1 = name; michael@0: michael@0: JS_ASSERT(sizeof(msg) == 0x34); michael@0: mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG, michael@0: sizeof(msg), 0x30, reply_port, 0, 0); michael@0: mig_dealloc_reply_port(reply_port); michael@0: return result; michael@0: } michael@0: michael@0: mach_msg_return_t michael@0: Stop(mach_port_t shark_port) michael@0: { michael@0: mach_port_t reply_port = mig_get_reply_port(); michael@0: michael@0: struct chud_client_stop_msg msg; michael@0: msg.hdr.msgh_bits = 0x1513; michael@0: msg.hdr.msgh_size = sizeof(mach_msg_header_t); michael@0: msg.hdr.msgh_remote_port = shark_port; michael@0: msg.hdr.msgh_local_port = reply_port; michael@0: msg.hdr.msgh_reserved = 0; michael@0: msg.hdr.msgh_id = SHARK_MSG_STOP; michael@0: michael@0: JS_ASSERT(RECV_SIZEOF(struct chud_client_stop_msg) == 0x18); michael@0: JS_ASSERT(sizeof(msg) == 0x2c); michael@0: mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG, michael@0: RECV_SIZEOF(struct chud_client_stop_msg), michael@0: sizeof(msg), reply_port, 0, 0); michael@0: mig_dealloc_reply_port(reply_port); michael@0: return result; michael@0: } michael@0: michael@0: static mach_msg_return_t michael@0: Disconnect(mach_port_t shark_port) michael@0: { michael@0: mach_port_t reply_port = mig_get_reply_port(); michael@0: michael@0: struct chud_client_release_msg msg; michael@0: msg.hdr.msgh_bits = 0x1513; michael@0: msg.hdr.msgh_size = sizeof(mach_msg_header_t); michael@0: msg.hdr.msgh_remote_port = shark_port; michael@0: msg.hdr.msgh_local_port = reply_port; michael@0: msg.hdr.msgh_reserved = 0; michael@0: msg.hdr.msgh_id = SHARK_MSG_RELEASE; michael@0: msg.unk0 = 0; michael@0: msg.unk1 = 1; michael@0: msg.pid = getpid(); michael@0: michael@0: JS_ASSERT(RECV_SIZEOF(struct chud_client_release_msg) == 0x24); michael@0: JS_ASSERT(sizeof(msg) == 0x2c); michael@0: mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG, michael@0: RECV_SIZEOF(struct chud_client_release_msg), michael@0: sizeof(msg), reply_port, 0, 0); michael@0: mig_dealloc_reply_port(reply_port); michael@0: return result; michael@0: } michael@0: michael@0: static mach_port_t shark_port = 0; michael@0: static bool connected = false; michael@0: static bool running = false; michael@0: michael@0: namespace Shark { michael@0: michael@0: bool michael@0: Start() michael@0: { michael@0: if (!shark_port && !(shark_port = CreatePort())) michael@0: return false; michael@0: if (!connected && Connect(shark_port)) michael@0: return false; michael@0: connected = true; michael@0: if (!running && ::Start(shark_port, 0xdeadbeef)) michael@0: return false; michael@0: return running = true; michael@0: } michael@0: michael@0: void michael@0: Stop() michael@0: { michael@0: if (!shark_port || !connected) michael@0: return; michael@0: ::Stop(shark_port); michael@0: running = false; michael@0: Disconnect(shark_port); michael@0: connected = false; michael@0: } michael@0: michael@0: } michael@0: michael@0: #endif