From 3a345f0df5f62d77e875a289e9aee89f0d1b526e Mon Sep 17 00:00:00 2001 From: Serban Constantinescu Date: Thu, 19 Dec 2013 09:11:41 +0000 Subject: [PATCH] ServiceManager: Fix the binder interface This patch adds support for binder transactions on 64bit systems without breaking the existing 32bit ABI. It has been tested on the Android emulator and ARMv8 Model. Most of the changes in this patch just follow the binder ABI. Change-Id: I8c37b847ea65008d56554d34d4696fe3d22f7533 Signed-off-by: Serban Constantinescu --- cmds/servicemanager/bctest.c | 2 +- cmds/servicemanager/binder.c | 80 +++++++++++++++------------ cmds/servicemanager/service_manager.c | 9 +-- 3 files changed, 51 insertions(+), 40 deletions(-) diff --git a/cmds/servicemanager/bctest.c b/cmds/servicemanager/bctest.c index 3bd18a710..e02b45d10 100644 --- a/cmds/servicemanager/bctest.c +++ b/cmds/servicemanager/bctest.c @@ -33,7 +33,7 @@ uint32_t svcmgr_lookup(struct binder_state *bs, uint32_t target, const char *nam int svcmgr_publish(struct binder_state *bs, uint32_t target, const char *name, void *ptr) { - unsigned status; + int status; unsigned iodata[512/4]; struct binder_io msg, reply; diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c index 5f206af25..7f8d0e0ed 100644 --- a/cmds/servicemanager/binder.c +++ b/cmds/servicemanager/binder.c @@ -148,9 +148,10 @@ int binder_write(struct binder_state *bs, void *data, size_t len) { struct binder_write_read bwr; int res; + bwr.write_size = len; bwr.write_consumed = 0; - bwr.write_buffer = (unsigned) data; + bwr.write_buffer = (uintptr_t) data; bwr.read_size = 0; bwr.read_consumed = 0; bwr.read_buffer = 0; @@ -169,13 +170,13 @@ void binder_send_reply(struct binder_state *bs, { struct { uint32_t cmd_free; - void *buffer; + uintptr_t buffer; uint32_t cmd_reply; struct binder_transaction_data txn; } __attribute__((packed)) data; data.cmd_free = BC_FREE_BUFFER; - data.buffer = buffer_to_free; + data.buffer = (uintptr_t) buffer_to_free; data.cmd_reply = BC_REPLY; data.txn.target.ptr = 0; data.txn.cookie = 0; @@ -197,13 +198,14 @@ void binder_send_reply(struct binder_state *bs, } int binder_parse(struct binder_state *bs, struct binder_io *bio, - uint32_t *ptr, uint32_t size, binder_handler func) + uintptr_t ptr, size_t size, binder_handler func) { int r = 1; - uint32_t *end = ptr + (size / 4); + uintptr_t end = ptr + (uintptr_t) size; while (ptr < end) { - uint32_t cmd = *ptr++; + uint32_t cmd = *(uint32_t *) ptr; + ptr += sizeof(uint32_t); #if TRACE fprintf(stderr,"%s:\n", cmd_name(cmd)); #endif @@ -217,13 +219,13 @@ int binder_parse(struct binder_state *bs, struct binder_io *bio, case BR_RELEASE: case BR_DECREFS: #if TRACE - fprintf(stderr," %08x %08x\n", ptr[0], ptr[1]); + fprintf(stderr," %p, %p\n", ptr, (ptr + sizeof(void *))); #endif - ptr += 2; + ptr += sizeof(struct binder_ptr_cookie); break; case BR_TRANSACTION: { struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr; - if ((end - ptr) * sizeof(uint32_t) < sizeof(*txn)) { + if ((end - ptr) < sizeof(*txn)) { ALOGE("parse: txn too small!\n"); return -1; } @@ -239,12 +241,12 @@ int binder_parse(struct binder_state *bs, struct binder_io *bio, res = func(bs, txn, &msg, &reply); binder_send_reply(bs, &reply, txn->data.ptr.buffer, res); } - ptr += sizeof(*txn) / sizeof(uint32_t); + ptr += sizeof(*txn); break; } case BR_REPLY: { struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr; - if ((end - ptr) * sizeof(uint32_t) < sizeof(*txn)) { + if ((end - ptr) < sizeof(*txn)) { ALOGE("parse: reply too small!\n"); return -1; } @@ -253,14 +255,15 @@ int binder_parse(struct binder_state *bs, struct binder_io *bio, bio_init_from_txn(bio, txn); bio = 0; } else { - /* todo FREE BUFFER */ + /* todo FREE BUFFER */ } - ptr += (sizeof(*txn) / sizeof(uint32_t)); + ptr += sizeof(*txn); r = 0; break; } case BR_DEAD_BINDER: { - struct binder_death *death = (void*) *ptr++; + struct binder_death *death = (struct binder_death *) *(intptr_t *)ptr; + ptr += sizeof(void *); death->func(bs, death->ptr); break; } @@ -297,13 +300,16 @@ void binder_release(struct binder_state *bs, uint32_t target) void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death) { - uint32_t cmd[3]; - cmd[0] = BC_REQUEST_DEATH_NOTIFICATION; - cmd[1] = (uint32_t) target; - cmd[2] = (uint32_t) death; - binder_write(bs, cmd, sizeof(cmd)); -} + struct { + uint32_t cmd; + struct binder_handle_cookie payload; + } __attribute__((packed)) data; + data.cmd = BC_REQUEST_DEATH_NOTIFICATION; + data.payload.handle = target; + data.payload.cookie = (uintptr_t) death; + binder_write(bs, &data, sizeof(data)); +} int binder_call(struct binder_state *bs, struct binder_io *msg, struct binder_io *reply, @@ -314,7 +320,7 @@ int binder_call(struct binder_state *bs, struct { uint32_t cmd; struct binder_transaction_data txn; - } writebuf; + } __attribute__((packed)) writebuf; unsigned readbuf[32]; if (msg->flags & BIO_F_OVERFLOW) { @@ -333,13 +339,13 @@ int binder_call(struct binder_state *bs, bwr.write_size = sizeof(writebuf); bwr.write_consumed = 0; - bwr.write_buffer = (unsigned) &writebuf; + bwr.write_buffer = (uintptr_t) &writebuf; hexdump(msg->data0, msg->data - msg->data0); for (;;) { bwr.read_size = sizeof(readbuf); bwr.read_consumed = 0; - bwr.read_buffer = (unsigned) readbuf; + bwr.read_buffer = (uintptr_t) readbuf; res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); @@ -348,7 +354,7 @@ int binder_call(struct binder_state *bs, goto fail; } - res = binder_parse(bs, reply, readbuf, bwr.read_consumed, 0); + res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0); if (res == 0) return 0; if (res < 0) goto fail; } @@ -363,19 +369,19 @@ void binder_loop(struct binder_state *bs, binder_handler func) { int res; struct binder_write_read bwr; - unsigned readbuf[32]; + uint32_t readbuf[32]; bwr.write_size = 0; bwr.write_consumed = 0; bwr.write_buffer = 0; readbuf[0] = BC_ENTER_LOOPER; - binder_write(bs, readbuf, sizeof(unsigned)); + binder_write(bs, readbuf, sizeof(uint32_t)); for (;;) { bwr.read_size = sizeof(readbuf); bwr.read_consumed = 0; - bwr.read_buffer = (unsigned) readbuf; + bwr.read_buffer = (uintptr_t) readbuf; res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); @@ -384,7 +390,7 @@ void binder_loop(struct binder_state *bs, binder_handler func) break; } - res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func); + res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func); if (res == 0) { ALOGE("binder_loop: unexpected reply?!\n"); break; @@ -401,7 +407,7 @@ void bio_init_from_txn(struct binder_io *bio, struct binder_transaction_data *tx bio->data = bio->data0 = txn->data.ptr.buffer; bio->offs = bio->offs0 = txn->data.ptr.offsets; bio->data_avail = txn->data_size; - bio->offs_avail = txn->offsets_size / 4; + bio->offs_avail = txn->offsets_size / sizeof(size_t); bio->flags = BIO_F_SHARED; } @@ -424,7 +430,7 @@ void bio_init(struct binder_io *bio, void *data, bio->flags = 0; } -static void *bio_alloc(struct binder_io *bio, uint32_t size) +static void *bio_alloc(struct binder_io *bio, size_t size) { size = (size + 3) & (~3); if (size > bio->data_avail) { @@ -442,11 +448,15 @@ void binder_done(struct binder_state *bs, struct binder_io *msg, struct binder_io *reply) { + struct { + uint32_t cmd; + uintptr_t buffer; + } __attribute__((packed)) data; + if (reply->flags & BIO_F_SHARED) { - uint32_t cmd[2]; - cmd[0] = BC_FREE_BUFFER; - cmd[1] = (uint32_t) reply->data0; - binder_write(bs, cmd, sizeof(cmd)); + data.cmd = BC_FREE_BUFFER; + data.buffer = (uintptr_t) reply->data0; + binder_write(bs, &data, sizeof(data)); reply->flags = 0; } } @@ -599,7 +609,7 @@ static struct flat_binder_object *_bio_get_obj(struct binder_io *bio) size_t n; size_t off = bio->data - bio->data0; - /* TODO: be smarter about this? */ + /* TODO: be smarter about this? */ for (n = 0; n < bio->offs_avail; n++) { if (bio->offs[n] == off) return bio_get(bio, sizeof(struct flat_binder_object)); diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c index c6735ee98..f8212e8ba 100644 --- a/cmds/servicemanager/service_manager.c +++ b/cmds/servicemanager/service_manager.c @@ -135,8 +135,8 @@ uint16_t svcmgr_id[] = { uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid) { struct svcinfo *si; - si = find_svc(s, len); + si = find_svc(s, len); //ALOGI("check_service('%s') handle = %x\n", str8(s), si ? si->handle : 0); if (si && si->handle) { if (!si->allow_isolated) { @@ -158,6 +158,7 @@ int do_add_service(struct binder_state *bs, uint32_t handle, uid_t uid, int allow_isolated) { struct svcinfo *si; + //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s), handle, // allow_isolated ? "allow_isolated" : "!allow_isolated", uid); @@ -213,8 +214,8 @@ int svcmgr_handler(struct binder_state *bs, uint32_t strict_policy; int allow_isolated; -// ALOGI("target=%p code=%d pid=%d uid=%d\n", -// txn->target, txn->code, txn->sender_pid, txn->sender_euid); + //ALOGI("target=%x code=%d pid=%d uid=%d\n", + // txn->target.handle, txn->code, txn->sender_pid, txn->sender_euid); if (txn->target.handle != svcmgr_handle) return -1; @@ -250,7 +251,7 @@ int svcmgr_handler(struct binder_state *bs, break; case SVC_MGR_LIST_SERVICES: { - unsigned n = bio_get_uint32(msg); + uint32_t n = bio_get_uint32(msg); si = svclist; while ((n-- > 0) && si)