From aeccb4a7a3aee8e47a33f00dedc8d3ee04b636be Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 7 Jan 2011 12:45:17 -0800 Subject: [PATCH] Initial commit --- sharkctl.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++ sharkctl.h | 20 +++++++ test.c | 35 +++++++++++ 3 files changed, 223 insertions(+) create mode 100644 sharkctl.c create mode 100644 sharkctl.h create mode 100644 test.c diff --git a/sharkctl.c b/sharkctl.c new file mode 100644 index 0000000..fae154a --- /dev/null +++ b/sharkctl.c @@ -0,0 +1,168 @@ +// +// Shark control +// +// Patrick Walton +// + +#include "sharkctl.h" +#include +#include +#include +#include +#include + +#define SHARK_MSG_ACQUIRE 0x29a +#define SHARK_MSG_RELEASE 0x29b +#define SHARK_MSG_STOP 0x29c +#define SHARK_MSG_START 0x29d + +#define RECV_SIZEOF(ty) offsetof(ty, out) + +// Private API in libSystem.dylib +extern void bootstrap_look_up(mach_port_t special_port, const char *name, + mach_port_t *dest_port); + +struct chud_client_acquire_msg { + mach_msg_header_t hdr; + uint32_t unk0; // always 0 + uint32_t unk1; // always 1 + uint32_t pid; + uint32_t out[2]; +}; + +struct chud_client_start_msg { + mach_msg_header_t hdr; + uint32_t unk0; // always 1 + uint32_t name0; + uint32_t arg2; // always 6 + uint8_t unk1; // always 0 + uint8_t unk2; // always 1 + uint8_t unk3; // uninitialized + uint8_t unk4; // always 1 + uint32_t unk5; // always 0 + uint32_t unk6; // always 1 + uint32_t name1; // same as name0 +}; + +struct chud_client_stop_msg { + mach_msg_header_t hdr; + uint32_t out[5]; +}; + +struct chud_client_release_msg { + mach_msg_header_t hdr; + uint32_t unk0; // always 0 + uint32_t unk1; // always 1 + uint32_t pid; + uint32_t out[2]; +}; + +mach_port_t sharkctl_create_port(void) { + mach_port_t bootstrap_port, shark_port = 0; + task_get_special_port(mach_task_self(), TASK_BOOTSTRAP_PORT, + &bootstrap_port); + bootstrap_look_up(bootstrap_port, "CHUD_IPC", &shark_port); + return shark_port; +} + +mach_msg_return_t sharkctl_connect(mach_port_t shark_port) { + mach_port_t reply_port = mig_get_reply_port(); + + struct chud_client_acquire_msg msg; + msg.hdr.msgh_bits = 0x1513; + msg.hdr.msgh_size = sizeof(mach_msg_header_t); + msg.hdr.msgh_remote_port = shark_port; + msg.hdr.msgh_local_port = reply_port; + msg.hdr.msgh_reserved = 0; + msg.hdr.msgh_id = SHARK_MSG_ACQUIRE; + msg.unk0 = 0; + msg.unk1 = 1; + msg.pid = getpid(); + + assert(RECV_SIZEOF(struct chud_client_acquire_msg) == 0x24); + assert(sizeof(msg) == 0x2c); + mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG, + RECV_SIZEOF(struct + chud_client_acquire_msg), + sizeof(msg), reply_port, 0, 0); + + mig_dealloc_reply_port(reply_port); + return result; +} + +mach_msg_return_t sharkctl_start(mach_port_t shark_port, uint32_t name) { + mach_port_t reply_port = mig_get_reply_port(); + + struct chud_client_start_msg msg; + msg.hdr.msgh_bits = 0x80001513; + msg.hdr.msgh_size = sizeof(mach_msg_header_t); + msg.hdr.msgh_remote_port = shark_port; + msg.hdr.msgh_local_port = reply_port; + msg.hdr.msgh_reserved = 0; + msg.hdr.msgh_id = SHARK_MSG_START; + msg.unk0 = 1; + msg.name0 = name; + msg.arg2 = 6; + msg.unk1 = 0; + msg.unk2 = 1; + msg.unk3 = 0; + msg.unk4 = 1; + msg.unk5 = 0; + msg.unk6 = 1; + msg.name1 = name; + + assert(sizeof(msg) == 0x34); + mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG, + sizeof(msg), 0x30, reply_port, 0, 0); + + mig_dealloc_reply_port(reply_port); + return result; +} + +mach_msg_return_t sharkctl_stop(mach_port_t shark_port) { + mach_port_t reply_port = mig_get_reply_port(); + + struct chud_client_stop_msg msg; + msg.hdr.msgh_bits = 0x1513; + msg.hdr.msgh_size = sizeof(mach_msg_header_t); + msg.hdr.msgh_remote_port = shark_port; + msg.hdr.msgh_local_port = reply_port; + msg.hdr.msgh_reserved = 0; + msg.hdr.msgh_id = SHARK_MSG_STOP; + + assert(RECV_SIZEOF(struct chud_client_stop_msg) == 0x18); + assert(sizeof(msg) == 0x2c); + mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG, + RECV_SIZEOF(struct + chud_client_stop_msg), + sizeof(msg), reply_port, 0, 0); + + mig_dealloc_reply_port(reply_port); + return result; +} + +mach_msg_return_t sharkctl_disconnect(mach_port_t shark_port) { + mach_port_t reply_port = mig_get_reply_port(); + + struct chud_client_release_msg msg; + msg.hdr.msgh_bits = 0x1513; + msg.hdr.msgh_size = sizeof(mach_msg_header_t); + msg.hdr.msgh_remote_port = shark_port; + msg.hdr.msgh_local_port = reply_port; + msg.hdr.msgh_reserved = 0; + msg.hdr.msgh_id = SHARK_MSG_RELEASE; + msg.unk0 = 0; + msg.unk1 = 1; + msg.pid = getpid(); + + assert(RECV_SIZEOF(struct chud_client_release_msg) == 0x24); + assert(sizeof(msg) == 0x2c); + mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG, + RECV_SIZEOF(struct + chud_client_release_msg), + sizeof(msg), reply_port, 0, 0); + + mig_dealloc_reply_port(reply_port); + return result; +} + diff --git a/sharkctl.h b/sharkctl.h new file mode 100644 index 0000000..9b3d317 --- /dev/null +++ b/sharkctl.h @@ -0,0 +1,20 @@ +// +// Shark control +// +// Patrick Walton +// + +#ifndef SHARKCTL_H +#define SHARKCTL_H + +#include +#include + +mach_port_t sharkctl_create_port(void); +mach_msg_return_t sharkctl_connect(mach_port_t shark_port); +mach_msg_return_t sharkctl_start(mach_port_t shark_port, uint32_t name); +mach_msg_return_t sharkctl_stop(mach_port_t shark_port); +mach_msg_return_t sharkctl_disconnect(mach_port_t shark_port); + +#endif + diff --git a/test.c b/test.c new file mode 100644 index 0000000..6c8af95 --- /dev/null +++ b/test.c @@ -0,0 +1,35 @@ +// +// Shark control test program +// +// Patrick Walton +// + +#include "sharkctl.h" +#include + +int fact(int n) { + if (n == 1) + return 1; + return n + fact(n - 1); +} + +int main() { + mach_port_t shark_port = sharkctl_create_port(); + printf("port: %x\n", shark_port); + mach_msg_return_t result = sharkctl_connect(shark_port); + printf("connect: %x\n", result); + result = sharkctl_start(shark_port, 0xdeadbeef); + printf("start: %x\n", result); + + int i; + for (i = 0; i < 100000; i++) + fact(1000); + + result = sharkctl_stop(shark_port); + printf("stop: %x\n", result); + result = sharkctl_disconnect(shark_port); + printf("disconnect: %x\n", result); + + return 0; +} +