blob: d1ab05f13d52d830a0583eefaff777c037b5dca7 [file] [log] [blame]
Mike Lockwood94afecf2012-10-24 10:45:23 -07001/* Copyright 2008 The Android Open Source Project
2 */
3
Arve Hjønnevåg399b6c32014-01-28 21:25:12 -08004#include <inttypes.h>
Mike Lockwood94afecf2012-10-24 10:45:23 -07005#include <stdio.h>
6#include <stdlib.h>
Elliott Hughes824e30e2015-01-29 22:32:32 -08007#include <string.h>
Mike Lockwood94afecf2012-10-24 10:45:23 -07008#include <errno.h>
9#include <unistd.h>
10#include <fcntl.h>
11#include <sys/mman.h>
12
13#include "binder.h"
14
15#define MAX_BIO_SIZE (1 << 30)
16
17#define TRACE 0
18
19#define LOG_TAG "Binder"
20#include <cutils/log.h>
21
Serban Constantinescubcf38882014-01-10 13:56:27 +000022void bio_init_from_txn(struct binder_io *io, struct binder_transaction_data *txn);
Mike Lockwood94afecf2012-10-24 10:45:23 -070023
24#if TRACE
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000025void hexdump(void *_data, size_t len)
Mike Lockwood94afecf2012-10-24 10:45:23 -070026{
27 unsigned char *data = _data;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000028 size_t count;
Mike Lockwood94afecf2012-10-24 10:45:23 -070029
30 for (count = 0; count < len; count++) {
31 if ((count & 15) == 0)
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000032 fprintf(stderr,"%04zu:", count);
Mike Lockwood94afecf2012-10-24 10:45:23 -070033 fprintf(stderr," %02x %c", *data,
34 (*data < 32) || (*data > 126) ? '.' : *data);
35 data++;
36 if ((count & 15) == 15)
37 fprintf(stderr,"\n");
38 }
39 if ((count & 15) != 0)
40 fprintf(stderr,"\n");
41}
42
Serban Constantinescubcf38882014-01-10 13:56:27 +000043void binder_dump_txn(struct binder_transaction_data *txn)
Mike Lockwood94afecf2012-10-24 10:45:23 -070044{
Serban Constantinescubcf38882014-01-10 13:56:27 +000045 struct flat_binder_object *obj;
Arve Hjønnevåg399b6c32014-01-28 21:25:12 -080046 binder_size_t *offs = (binder_size_t *)(uintptr_t)txn->data.ptr.offsets;
47 size_t count = txn->offsets_size / sizeof(binder_size_t);
Mike Lockwood94afecf2012-10-24 10:45:23 -070048
Arve Hjønnevåg399b6c32014-01-28 21:25:12 -080049 fprintf(stderr," target %016"PRIx64" cookie %016"PRIx64" code %08x flags %08x\n",
50 (uint64_t)txn->target.ptr, (uint64_t)txn->cookie, txn->code, txn->flags);
51 fprintf(stderr," pid %8d uid %8d data %"PRIu64" offs %"PRIu64"\n",
52 txn->sender_pid, txn->sender_euid, (uint64_t)txn->data_size, (uint64_t)txn->offsets_size);
53 hexdump((void *)(uintptr_t)txn->data.ptr.buffer, txn->data_size);
Mike Lockwood94afecf2012-10-24 10:45:23 -070054 while (count--) {
Arve Hjønnevåg399b6c32014-01-28 21:25:12 -080055 obj = (struct flat_binder_object *) (((char*)(uintptr_t)txn->data.ptr.buffer) + *offs++);
56 fprintf(stderr," - type %08x flags %08x ptr %016"PRIx64" cookie %016"PRIx64"\n",
57 obj->type, obj->flags, (uint64_t)obj->binder, (uint64_t)obj->cookie);
Mike Lockwood94afecf2012-10-24 10:45:23 -070058 }
59}
60
61#define NAME(n) case n: return #n
62const char *cmd_name(uint32_t cmd)
63{
64 switch(cmd) {
65 NAME(BR_NOOP);
66 NAME(BR_TRANSACTION_COMPLETE);
67 NAME(BR_INCREFS);
68 NAME(BR_ACQUIRE);
69 NAME(BR_RELEASE);
70 NAME(BR_DECREFS);
71 NAME(BR_TRANSACTION);
72 NAME(BR_REPLY);
73 NAME(BR_FAILED_REPLY);
74 NAME(BR_DEAD_REPLY);
75 NAME(BR_DEAD_BINDER);
76 default: return "???";
77 }
78}
79#else
80#define hexdump(a,b) do{} while (0)
81#define binder_dump_txn(txn) do{} while (0)
82#endif
83
84#define BIO_F_SHARED 0x01 /* needs to be buffer freed */
85#define BIO_F_OVERFLOW 0x02 /* ran out of space */
86#define BIO_F_IOERROR 0x04
87#define BIO_F_MALLOCED 0x08 /* needs to be free()'d */
88
89struct binder_state
90{
91 int fd;
92 void *mapped;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000093 size_t mapsize;
Mike Lockwood94afecf2012-10-24 10:45:23 -070094};
95
Serban Constantinescu9b738bb2014-01-10 15:48:29 +000096struct binder_state *binder_open(size_t mapsize)
Mike Lockwood94afecf2012-10-24 10:45:23 -070097{
98 struct binder_state *bs;
Serban Constantinescua44542c2014-01-30 15:16:45 +000099 struct binder_version vers;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700100
101 bs = malloc(sizeof(*bs));
102 if (!bs) {
103 errno = ENOMEM;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000104 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700105 }
106
107 bs->fd = open("/dev/binder", O_RDWR);
108 if (bs->fd < 0) {
109 fprintf(stderr,"binder: cannot open device (%s)\n",
110 strerror(errno));
111 goto fail_open;
112 }
113
Serban Constantinescua44542c2014-01-30 15:16:45 +0000114 if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
115 (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
116 fprintf(stderr, "binder: driver version differs from user space\n");
117 goto fail_open;
118 }
119
Mike Lockwood94afecf2012-10-24 10:45:23 -0700120 bs->mapsize = mapsize;
121 bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
122 if (bs->mapped == MAP_FAILED) {
123 fprintf(stderr,"binder: cannot map device (%s)\n",
124 strerror(errno));
125 goto fail_map;
126 }
127
Mike Lockwood94afecf2012-10-24 10:45:23 -0700128 return bs;
129
130fail_map:
131 close(bs->fd);
132fail_open:
133 free(bs);
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000134 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700135}
136
137void binder_close(struct binder_state *bs)
138{
139 munmap(bs->mapped, bs->mapsize);
140 close(bs->fd);
141 free(bs);
142}
143
144int binder_become_context_manager(struct binder_state *bs)
145{
146 return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
147}
148
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000149int binder_write(struct binder_state *bs, void *data, size_t len)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700150{
151 struct binder_write_read bwr;
152 int res;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000153
Mike Lockwood94afecf2012-10-24 10:45:23 -0700154 bwr.write_size = len;
155 bwr.write_consumed = 0;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000156 bwr.write_buffer = (uintptr_t) data;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700157 bwr.read_size = 0;
158 bwr.read_consumed = 0;
159 bwr.read_buffer = 0;
160 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
161 if (res < 0) {
162 fprintf(stderr,"binder_write: ioctl failed (%s)\n",
163 strerror(errno));
164 }
165 return res;
166}
167
168void binder_send_reply(struct binder_state *bs,
169 struct binder_io *reply,
Arve Hjønnevåg399b6c32014-01-28 21:25:12 -0800170 binder_uintptr_t buffer_to_free,
Mike Lockwood94afecf2012-10-24 10:45:23 -0700171 int status)
172{
173 struct {
174 uint32_t cmd_free;
Arve Hjønnevåg399b6c32014-01-28 21:25:12 -0800175 binder_uintptr_t buffer;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700176 uint32_t cmd_reply;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000177 struct binder_transaction_data txn;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700178 } __attribute__((packed)) data;
179
180 data.cmd_free = BC_FREE_BUFFER;
Arve Hjønnevåg399b6c32014-01-28 21:25:12 -0800181 data.buffer = buffer_to_free;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700182 data.cmd_reply = BC_REPLY;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000183 data.txn.target.ptr = 0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700184 data.txn.cookie = 0;
185 data.txn.code = 0;
186 if (status) {
187 data.txn.flags = TF_STATUS_CODE;
188 data.txn.data_size = sizeof(int);
Serban Constantinescubcf38882014-01-10 13:56:27 +0000189 data.txn.offsets_size = 0;
Arve Hjønnevåg399b6c32014-01-28 21:25:12 -0800190 data.txn.data.ptr.buffer = (uintptr_t)&status;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000191 data.txn.data.ptr.offsets = 0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700192 } else {
193 data.txn.flags = 0;
194 data.txn.data_size = reply->data - reply->data0;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000195 data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0);
Arve Hjønnevåg399b6c32014-01-28 21:25:12 -0800196 data.txn.data.ptr.buffer = (uintptr_t)reply->data0;
197 data.txn.data.ptr.offsets = (uintptr_t)reply->offs0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700198 }
199 binder_write(bs, &data, sizeof(data));
200}
201
202int binder_parse(struct binder_state *bs, struct binder_io *bio,
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000203 uintptr_t ptr, size_t size, binder_handler func)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700204{
205 int r = 1;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000206 uintptr_t end = ptr + (uintptr_t) size;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700207
208 while (ptr < end) {
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000209 uint32_t cmd = *(uint32_t *) ptr;
210 ptr += sizeof(uint32_t);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700211#if TRACE
212 fprintf(stderr,"%s:\n", cmd_name(cmd));
213#endif
214 switch(cmd) {
215 case BR_NOOP:
216 break;
217 case BR_TRANSACTION_COMPLETE:
218 break;
219 case BR_INCREFS:
220 case BR_ACQUIRE:
221 case BR_RELEASE:
222 case BR_DECREFS:
223#if TRACE
Arve Hjønnevåg399b6c32014-01-28 21:25:12 -0800224 fprintf(stderr," %p, %p\n", (void *)ptr, (void *)(ptr + sizeof(void *)));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700225#endif
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000226 ptr += sizeof(struct binder_ptr_cookie);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700227 break;
228 case BR_TRANSACTION: {
Serban Constantinescubcf38882014-01-10 13:56:27 +0000229 struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000230 if ((end - ptr) < sizeof(*txn)) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700231 ALOGE("parse: txn too small!\n");
232 return -1;
233 }
234 binder_dump_txn(txn);
235 if (func) {
236 unsigned rdata[256/4];
237 struct binder_io msg;
238 struct binder_io reply;
239 int res;
240
241 bio_init(&reply, rdata, sizeof(rdata), 4);
242 bio_init_from_txn(&msg, txn);
243 res = func(bs, txn, &msg, &reply);
Serban Constantinescubcf38882014-01-10 13:56:27 +0000244 binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700245 }
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000246 ptr += sizeof(*txn);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700247 break;
248 }
249 case BR_REPLY: {
Serban Constantinescubcf38882014-01-10 13:56:27 +0000250 struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000251 if ((end - ptr) < sizeof(*txn)) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700252 ALOGE("parse: reply too small!\n");
253 return -1;
254 }
255 binder_dump_txn(txn);
256 if (bio) {
257 bio_init_from_txn(bio, txn);
258 bio = 0;
259 } else {
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000260 /* todo FREE BUFFER */
Mike Lockwood94afecf2012-10-24 10:45:23 -0700261 }
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000262 ptr += sizeof(*txn);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700263 r = 0;
264 break;
265 }
266 case BR_DEAD_BINDER: {
Arve Hjønnevåg399b6c32014-01-28 21:25:12 -0800267 struct binder_death *death = (struct binder_death *)(uintptr_t) *(binder_uintptr_t *)ptr;
268 ptr += sizeof(binder_uintptr_t);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700269 death->func(bs, death->ptr);
270 break;
271 }
272 case BR_FAILED_REPLY:
273 r = -1;
274 break;
275 case BR_DEAD_REPLY:
276 r = -1;
277 break;
278 default:
279 ALOGE("parse: OOPS %d\n", cmd);
280 return -1;
281 }
282 }
283
284 return r;
285}
286
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000287void binder_acquire(struct binder_state *bs, uint32_t target)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700288{
289 uint32_t cmd[2];
290 cmd[0] = BC_ACQUIRE;
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000291 cmd[1] = target;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700292 binder_write(bs, cmd, sizeof(cmd));
293}
294
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000295void binder_release(struct binder_state *bs, uint32_t target)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700296{
297 uint32_t cmd[2];
298 cmd[0] = BC_RELEASE;
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000299 cmd[1] = target;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700300 binder_write(bs, cmd, sizeof(cmd));
301}
302
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000303void binder_link_to_death(struct binder_state *bs, uint32_t target, struct binder_death *death)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700304{
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000305 struct {
306 uint32_t cmd;
307 struct binder_handle_cookie payload;
308 } __attribute__((packed)) data;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700309
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000310 data.cmd = BC_REQUEST_DEATH_NOTIFICATION;
311 data.payload.handle = target;
312 data.payload.cookie = (uintptr_t) death;
313 binder_write(bs, &data, sizeof(data));
314}
Mike Lockwood94afecf2012-10-24 10:45:23 -0700315
316int binder_call(struct binder_state *bs,
317 struct binder_io *msg, struct binder_io *reply,
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000318 uint32_t target, uint32_t code)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700319{
320 int res;
321 struct binder_write_read bwr;
322 struct {
323 uint32_t cmd;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000324 struct binder_transaction_data txn;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000325 } __attribute__((packed)) writebuf;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700326 unsigned readbuf[32];
327
328 if (msg->flags & BIO_F_OVERFLOW) {
329 fprintf(stderr,"binder: txn buffer overflow\n");
330 goto fail;
331 }
332
333 writebuf.cmd = BC_TRANSACTION;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000334 writebuf.txn.target.handle = target;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700335 writebuf.txn.code = code;
336 writebuf.txn.flags = 0;
337 writebuf.txn.data_size = msg->data - msg->data0;
Serban Constantinescubcf38882014-01-10 13:56:27 +0000338 writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0);
Arve Hjønnevåg399b6c32014-01-28 21:25:12 -0800339 writebuf.txn.data.ptr.buffer = (uintptr_t)msg->data0;
340 writebuf.txn.data.ptr.offsets = (uintptr_t)msg->offs0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700341
342 bwr.write_size = sizeof(writebuf);
343 bwr.write_consumed = 0;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000344 bwr.write_buffer = (uintptr_t) &writebuf;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000345
Mike Lockwood94afecf2012-10-24 10:45:23 -0700346 hexdump(msg->data0, msg->data - msg->data0);
347 for (;;) {
348 bwr.read_size = sizeof(readbuf);
349 bwr.read_consumed = 0;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000350 bwr.read_buffer = (uintptr_t) readbuf;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700351
352 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
353
354 if (res < 0) {
355 fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
356 goto fail;
357 }
358
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000359 res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700360 if (res == 0) return 0;
361 if (res < 0) goto fail;
362 }
363
364fail:
365 memset(reply, 0, sizeof(*reply));
366 reply->flags |= BIO_F_IOERROR;
367 return -1;
368}
369
370void binder_loop(struct binder_state *bs, binder_handler func)
371{
372 int res;
373 struct binder_write_read bwr;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000374 uint32_t readbuf[32];
Mike Lockwood94afecf2012-10-24 10:45:23 -0700375
376 bwr.write_size = 0;
377 bwr.write_consumed = 0;
378 bwr.write_buffer = 0;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000379
Mike Lockwood94afecf2012-10-24 10:45:23 -0700380 readbuf[0] = BC_ENTER_LOOPER;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000381 binder_write(bs, readbuf, sizeof(uint32_t));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700382
383 for (;;) {
384 bwr.read_size = sizeof(readbuf);
385 bwr.read_consumed = 0;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000386 bwr.read_buffer = (uintptr_t) readbuf;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700387
388 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
389
390 if (res < 0) {
391 ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
392 break;
393 }
394
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000395 res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700396 if (res == 0) {
397 ALOGE("binder_loop: unexpected reply?!\n");
398 break;
399 }
400 if (res < 0) {
401 ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
402 break;
403 }
404 }
405}
406
Serban Constantinescubcf38882014-01-10 13:56:27 +0000407void bio_init_from_txn(struct binder_io *bio, struct binder_transaction_data *txn)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700408{
Arve Hjønnevåg399b6c32014-01-28 21:25:12 -0800409 bio->data = bio->data0 = (char *)(intptr_t)txn->data.ptr.buffer;
410 bio->offs = bio->offs0 = (binder_size_t *)(intptr_t)txn->data.ptr.offsets;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700411 bio->data_avail = txn->data_size;
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000412 bio->offs_avail = txn->offsets_size / sizeof(size_t);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700413 bio->flags = BIO_F_SHARED;
414}
415
416void bio_init(struct binder_io *bio, void *data,
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000417 size_t maxdata, size_t maxoffs)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700418{
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000419 size_t n = maxoffs * sizeof(size_t);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700420
421 if (n > maxdata) {
422 bio->flags = BIO_F_OVERFLOW;
423 bio->data_avail = 0;
424 bio->offs_avail = 0;
425 return;
426 }
427
428 bio->data = bio->data0 = (char *) data + n;
429 bio->offs = bio->offs0 = data;
430 bio->data_avail = maxdata - n;
431 bio->offs_avail = maxoffs;
432 bio->flags = 0;
433}
434
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000435static void *bio_alloc(struct binder_io *bio, size_t size)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700436{
437 size = (size + 3) & (~3);
438 if (size > bio->data_avail) {
439 bio->flags |= BIO_F_OVERFLOW;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000440 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700441 } else {
442 void *ptr = bio->data;
443 bio->data += size;
444 bio->data_avail -= size;
445 return ptr;
446 }
447}
448
449void binder_done(struct binder_state *bs,
450 struct binder_io *msg,
451 struct binder_io *reply)
452{
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000453 struct {
454 uint32_t cmd;
455 uintptr_t buffer;
456 } __attribute__((packed)) data;
457
Mike Lockwood94afecf2012-10-24 10:45:23 -0700458 if (reply->flags & BIO_F_SHARED) {
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000459 data.cmd = BC_FREE_BUFFER;
460 data.buffer = (uintptr_t) reply->data0;
461 binder_write(bs, &data, sizeof(data));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700462 reply->flags = 0;
463 }
464}
465
Serban Constantinescubcf38882014-01-10 13:56:27 +0000466static struct flat_binder_object *bio_alloc_obj(struct binder_io *bio)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700467{
Serban Constantinescubcf38882014-01-10 13:56:27 +0000468 struct flat_binder_object *obj;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700469
470 obj = bio_alloc(bio, sizeof(*obj));
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000471
Mike Lockwood94afecf2012-10-24 10:45:23 -0700472 if (obj && bio->offs_avail) {
473 bio->offs_avail--;
474 *bio->offs++ = ((char*) obj) - ((char*) bio->data0);
475 return obj;
476 }
477
478 bio->flags |= BIO_F_OVERFLOW;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000479 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700480}
481
482void bio_put_uint32(struct binder_io *bio, uint32_t n)
483{
484 uint32_t *ptr = bio_alloc(bio, sizeof(n));
485 if (ptr)
486 *ptr = n;
487}
488
489void bio_put_obj(struct binder_io *bio, void *ptr)
490{
Serban Constantinescubcf38882014-01-10 13:56:27 +0000491 struct flat_binder_object *obj;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700492
493 obj = bio_alloc_obj(bio);
494 if (!obj)
495 return;
496
497 obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
498 obj->type = BINDER_TYPE_BINDER;
Arve Hjønnevåg399b6c32014-01-28 21:25:12 -0800499 obj->binder = (uintptr_t)ptr;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700500 obj->cookie = 0;
501}
502
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000503void bio_put_ref(struct binder_io *bio, uint32_t handle)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700504{
Serban Constantinescubcf38882014-01-10 13:56:27 +0000505 struct flat_binder_object *obj;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700506
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000507 if (handle)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700508 obj = bio_alloc_obj(bio);
509 else
510 obj = bio_alloc(bio, sizeof(*obj));
511
512 if (!obj)
513 return;
514
515 obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
516 obj->type = BINDER_TYPE_HANDLE;
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000517 obj->handle = handle;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700518 obj->cookie = 0;
519}
520
521void bio_put_string16(struct binder_io *bio, const uint16_t *str)
522{
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000523 size_t len;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700524 uint16_t *ptr;
525
526 if (!str) {
527 bio_put_uint32(bio, 0xffffffff);
528 return;
529 }
530
531 len = 0;
532 while (str[len]) len++;
533
534 if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
535 bio_put_uint32(bio, 0xffffffff);
536 return;
537 }
538
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000539 /* Note: The payload will carry 32bit size instead of size_t */
540 bio_put_uint32(bio, (uint32_t) len);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700541 len = (len + 1) * sizeof(uint16_t);
542 ptr = bio_alloc(bio, len);
543 if (ptr)
544 memcpy(ptr, str, len);
545}
546
547void bio_put_string16_x(struct binder_io *bio, const char *_str)
548{
549 unsigned char *str = (unsigned char*) _str;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000550 size_t len;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700551 uint16_t *ptr;
552
553 if (!str) {
554 bio_put_uint32(bio, 0xffffffff);
555 return;
556 }
557
558 len = strlen(_str);
559
560 if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
561 bio_put_uint32(bio, 0xffffffff);
562 return;
563 }
564
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000565 /* Note: The payload will carry 32bit size instead of size_t */
Mike Lockwood94afecf2012-10-24 10:45:23 -0700566 bio_put_uint32(bio, len);
567 ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t));
568 if (!ptr)
569 return;
570
571 while (*str)
572 *ptr++ = *str++;
573 *ptr++ = 0;
574}
575
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000576static void *bio_get(struct binder_io *bio, size_t size)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700577{
578 size = (size + 3) & (~3);
579
580 if (bio->data_avail < size){
581 bio->data_avail = 0;
582 bio->flags |= BIO_F_OVERFLOW;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000583 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700584 } else {
585 void *ptr = bio->data;
586 bio->data += size;
587 bio->data_avail -= size;
588 return ptr;
589 }
590}
591
592uint32_t bio_get_uint32(struct binder_io *bio)
593{
594 uint32_t *ptr = bio_get(bio, sizeof(*ptr));
595 return ptr ? *ptr : 0;
596}
597
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000598uint16_t *bio_get_string16(struct binder_io *bio, size_t *sz)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700599{
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000600 size_t len;
601
602 /* Note: The payload will carry 32bit size instead of size_t */
603 len = (size_t) bio_get_uint32(bio);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700604 if (sz)
605 *sz = len;
606 return bio_get(bio, (len + 1) * sizeof(uint16_t));
607}
608
Serban Constantinescubcf38882014-01-10 13:56:27 +0000609static struct flat_binder_object *_bio_get_obj(struct binder_io *bio)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700610{
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000611 size_t n;
612 size_t off = bio->data - bio->data0;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700613
Serban Constantinescu3a345f02013-12-19 09:11:41 +0000614 /* TODO: be smarter about this? */
Mike Lockwood94afecf2012-10-24 10:45:23 -0700615 for (n = 0; n < bio->offs_avail; n++) {
616 if (bio->offs[n] == off)
Serban Constantinescubcf38882014-01-10 13:56:27 +0000617 return bio_get(bio, sizeof(struct flat_binder_object));
Mike Lockwood94afecf2012-10-24 10:45:23 -0700618 }
619
620 bio->data_avail = 0;
621 bio->flags |= BIO_F_OVERFLOW;
Serban Constantinescu9b738bb2014-01-10 15:48:29 +0000622 return NULL;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700623}
624
Serban Constantinescu5fb1b882014-01-30 14:07:34 +0000625uint32_t bio_get_ref(struct binder_io *bio)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700626{
Serban Constantinescubcf38882014-01-10 13:56:27 +0000627 struct flat_binder_object *obj;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700628
629 obj = _bio_get_obj(bio);
630 if (!obj)
631 return 0;
632
633 if (obj->type == BINDER_TYPE_HANDLE)
Serban Constantinescubcf38882014-01-10 13:56:27 +0000634 return obj->handle;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700635
636 return 0;
637}