Merge "ueventd.rc: Add /dev/uhid for bluedroid" into jb-mr1-dev
diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk
index fe46706..15083f4 100644
--- a/debuggerd/Android.mk
+++ b/debuggerd/Android.mk
@@ -1,6 +1,6 @@
 # Copyright 2005 The Android Open Source Project
 
-ifneq ($(filter arm x86,$(TARGET_ARCH)),)
+ifneq ($(filter arm mips x86,$(TARGET_ARCH)),)
 
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c
index 8009631..55222c5 100644
--- a/debuggerd/debuggerd.c
+++ b/debuggerd/debuggerd.c
@@ -330,7 +330,10 @@
                     case SIGFPE:
                     case SIGSEGV:
                     case SIGPIPE:
-                    case SIGSTKFLT: {
+#ifdef SIGSTKFLT
+                    case SIGSTKFLT:
+#endif
+                        {
                         XLOG("stopped -- fatal signal\n");
                         /*
                          * Send a SIGSTOP to the process to make all of
@@ -424,7 +427,9 @@
     signal(SIGFPE, SIG_DFL);
     signal(SIGSEGV, SIG_DFL);
     signal(SIGPIPE, SIG_DFL);
+#ifdef SIGSTKFLT
     signal(SIGSTKFLT, SIG_DFL);
+#endif
 
     logsocket = socket_local_client("logd",
             ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_DGRAM);
diff --git a/debuggerd/mips/crashglue.S b/debuggerd/mips/crashglue.S
new file mode 100644
index 0000000..70a6641
--- /dev/null
+++ b/debuggerd/mips/crashglue.S
@@ -0,0 +1,48 @@
+	.set	noat
+
+	.globl crash1
+	.globl crashnostack
+
+crash1:
+	li	$0,0xdead0000+0
+	li	$1,0xdead0000+1
+	li	$2,0xdead0000+2
+	li	$3,0xdead0000+3
+	li	$4,0xdead0000+4
+	li	$5,0xdead0000+5
+	li	$6,0xdead0000+6
+	li	$7,0xdead0000+7
+	li	$8,0xdead0000+8
+	li	$9,0xdead0000+9
+	li	$10,0xdead0000+10
+	li	$11,0xdead0000+11
+	li	$12,0xdead0000+12
+	li	$13,0xdead0000+13
+	li	$14,0xdead0000+14
+	li	$15,0xdead0000+15
+	li	$16,0xdead0000+16
+	li	$17,0xdead0000+17
+	li	$18,0xdead0000+18
+	li	$19,0xdead0000+19
+	li	$20,0xdead0000+20
+	li	$21,0xdead0000+21
+	li	$22,0xdead0000+22
+	li	$23,0xdead0000+23
+	li	$24,0xdead0000+24
+	li	$25,0xdead0000+25
+	li	$26,0xdead0000+26
+	li	$27,0xdead0000+27
+	li	$28,0xdead0000+28
+	# don't trash the stack otherwise the signal handler won't run
+	#li	$29,0xdead0000+29
+	li	$30,0xdead0000+30
+	li	$31,0xdead0000+31
+
+	lw	$zero,($0)
+	b .
+
+
+crashnostack:
+	li	$sp, 0
+	lw	$zero,($0)
+	b .
diff --git a/debuggerd/mips/machine.c b/debuggerd/mips/machine.c
new file mode 100644
index 0000000..dba1711
--- /dev/null
+++ b/debuggerd/mips/machine.c
@@ -0,0 +1,178 @@
+/* system/debuggerd/debuggerd.c
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/ptrace.h>
+
+#include <corkscrew/ptrace.h>
+
+#include <linux/user.h>
+
+#include "../utility.h"
+#include "../machine.h"
+
+/* enable to dump memory pointed to by every register */
+#define DUMP_MEMORY_FOR_ALL_REGISTERS 1
+
+#define R(x) ((unsigned int)(x))
+
+static void dump_memory(log_t* log, pid_t tid, uintptr_t addr, bool at_fault) {
+    char code_buffer[64];       /* actual 8+1+((8+1)*4) + 1 == 45 */
+    char ascii_buffer[32];      /* actual 16 + 1 == 17 */
+    uintptr_t p, end;
+
+    p = addr & ~3;
+    p -= 32;
+    if (p > addr) {
+        /* catch underflow */
+        p = 0;
+    }
+    end = p + 80;
+    /* catch overflow; 'end - p' has to be multiples of 16 */
+    while (end < p)
+        end -= 16;
+
+    /* Dump the code around PC as:
+     *  addr     contents                             ascii
+     *  00008d34 ef000000 e8bd0090 e1b00000 512fff1e  ............../Q
+     *  00008d44 ea00b1f9 e92d0090 e3a070fc ef000000  ......-..p......
+     */
+    while (p < end) {
+        char* asc_out = ascii_buffer;
+
+        sprintf(code_buffer, "%08x ", p);
+
+        int i;
+        for (i = 0; i < 4; i++) {
+            /*
+             * If we see (data == -1 && errno != 0), we know that the ptrace
+             * call failed, probably because we're dumping memory in an
+             * unmapped or inaccessible page.  I don't know if there's
+             * value in making that explicit in the output -- it likely
+             * just complicates parsing and clarifies nothing for the
+             * enlightened reader.
+             */
+            long data = ptrace(PTRACE_PEEKTEXT, tid, (void*)p, NULL);
+            sprintf(code_buffer + strlen(code_buffer), "%08lx ", data);
+
+            int j;
+            for (j = 0; j < 4; j++) {
+                /*
+                 * Our isprint() allows high-ASCII characters that display
+                 * differently (often badly) in different viewers, so we
+                 * just use a simpler test.
+                 */
+                char val = (data >> (j*8)) & 0xff;
+                if (val >= 0x20 && val < 0x7f) {
+                    *asc_out++ = val;
+                } else {
+                    *asc_out++ = '.';
+                }
+            }
+            p += 4;
+        }
+        *asc_out = '\0';
+        _LOG(log, !at_fault, "    %s %s\n", code_buffer, ascii_buffer);
+    }
+}
+
+/*
+ * If configured to do so, dump memory around *all* registers
+ * for the crashing thread.
+ */
+void dump_memory_and_code(const ptrace_context_t* context __attribute((unused)),
+        log_t* log, pid_t tid, bool at_fault) {
+    pt_regs_mips_t r;
+    if(ptrace(PTRACE_GETREGS, tid, 0, &r)) {
+        return;
+    }
+
+    if (at_fault && DUMP_MEMORY_FOR_ALL_REGISTERS) {
+        static const char REG_NAMES[] = "$0atv0v1a0a1a2a3t0t1t2t3t4t5t6t7s0s1s2s3s4s5s6s7t8t9k0k1gpsps8ra";
+
+        for (int reg = 0; reg < 32; reg++) {
+            /* skip uninteresting registers */
+            if (reg == 0 /* $0 */
+                || reg == 26 /* $k0 */
+                || reg == 27 /* $k1 */
+                || reg == 31 /* $ra (done below) */
+               )
+               continue;
+
+            uintptr_t addr = R(r.regs[reg]);
+
+            /*
+             * Don't bother if it looks like a small int or ~= null, or if
+             * it's in the kernel area.
+             */
+            if (addr < 4096 || addr >= 0x80000000) {
+                continue;
+            }
+
+            _LOG(log, false, "\nmemory near %.2s:\n", &REG_NAMES[reg * 2]);
+            dump_memory(log, tid, addr, at_fault);
+        }
+    }
+
+    unsigned int pc = R(r.cp0_epc);
+    unsigned int ra = R(r.regs[31]);
+
+    _LOG(log, !at_fault, "\ncode around pc:\n");
+    dump_memory(log, tid, (uintptr_t)pc, at_fault);
+
+    if (pc != ra) {
+        _LOG(log, !at_fault, "\ncode around ra:\n");
+        dump_memory(log, tid, (uintptr_t)ra, at_fault);
+    }
+}
+
+void dump_registers(const ptrace_context_t* context __attribute((unused)),
+        log_t* log, pid_t tid, bool at_fault)
+{
+    pt_regs_mips_t r;
+    bool only_in_tombstone = !at_fault;
+
+    if(ptrace(PTRACE_GETREGS, tid, 0, &r)) {
+        _LOG(log, only_in_tombstone, "cannot get registers: %s\n", strerror(errno));
+        return;
+    }
+
+    _LOG(log, only_in_tombstone, " zr %08x  at %08x  v0 %08x  v1 %08x\n",
+     R(r.regs[0]), R(r.regs[1]), R(r.regs[2]), R(r.regs[3]));
+    _LOG(log, only_in_tombstone, " a0 %08x  a1 %08x  a2 %08x  a3 %08x\n",
+     R(r.regs[4]), R(r.regs[5]), R(r.regs[6]), R(r.regs[7]));
+    _LOG(log, only_in_tombstone, " t0 %08x  t1 %08x  t2 %08x  t3 %08x\n",
+     R(r.regs[8]), R(r.regs[9]), R(r.regs[10]), R(r.regs[11]));
+    _LOG(log, only_in_tombstone, " t4 %08x  t5 %08x  t6 %08x  t7 %08x\n",
+     R(r.regs[12]), R(r.regs[13]), R(r.regs[14]), R(r.regs[15]));
+    _LOG(log, only_in_tombstone, " s0 %08x  s1 %08x  s2 %08x  s3 %08x\n",
+     R(r.regs[16]), R(r.regs[17]), R(r.regs[18]), R(r.regs[19]));
+    _LOG(log, only_in_tombstone, " s4 %08x  s5 %08x  s6 %08x  s7 %08x\n",
+     R(r.regs[20]), R(r.regs[21]), R(r.regs[22]), R(r.regs[23]));
+    _LOG(log, only_in_tombstone, " t8 %08x  t9 %08x  k0 %08x  k1 %08x\n",
+     R(r.regs[24]), R(r.regs[25]), R(r.regs[26]), R(r.regs[27]));
+    _LOG(log, only_in_tombstone, " gp %08x  sp %08x  s8 %08x  ra %08x\n",
+     R(r.regs[28]), R(r.regs[29]), R(r.regs[30]), R(r.regs[31]));
+    _LOG(log, only_in_tombstone, " hi %08x  lo %08x bva %08x epc %08x\n",
+     R(r.hi), R(r.lo), R(r.cp0_badvaddr), R(r.cp0_epc));
+}
diff --git a/debuggerd/tombstone.c b/debuggerd/tombstone.c
index 27ab3fe..012337b 100644
--- a/debuggerd/tombstone.c
+++ b/debuggerd/tombstone.c
@@ -76,7 +76,9 @@
     case SIGFPE:     return "SIGFPE";
     case SIGSEGV:    return "SIGSEGV";
     case SIGPIPE:    return "SIGPIPE";
+#ifdef SIGSTKFLT
     case SIGSTKFLT:  return "SIGSTKFLT";
+#endif
     case SIGSTOP:    return "SIGSTOP";
     default:         return "?";
     }
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 60aed42..538b5be 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -58,6 +58,12 @@
     { "ro",         MS_RDONLY },
     { "rw",         0 },
     { "remount",    MS_REMOUNT },
+    { "bind",       MS_BIND },
+    { "rec",        MS_REC },
+    { "unbindable", MS_UNBINDABLE },
+    { "private",    MS_PRIVATE },
+    { "slave",      MS_SLAVE },
+    { "shared",     MS_SHARED },
     { "defaults",   0 },
     { 0,            0 },
 };
diff --git a/include/corkscrew/ptrace.h b/include/corkscrew/ptrace.h
index 0040c22..76276d8 100644
--- a/include/corkscrew/ptrace.h
+++ b/include/corkscrew/ptrace.h
@@ -65,6 +65,19 @@
 } pt_regs_x86_t;
 #endif
 
+#if __mips__
+/* ptrace() GET_REGS context. */
+typedef struct pt_regs_mips {
+    uint64_t regs[32];
+    uint64_t lo;
+    uint64_t hi;
+    uint64_t cp0_epc;
+    uint64_t cp0_badvaddr;
+    uint64_t cp0_status;
+    uint64_t cp0_cause;
+} pt_regs_mips_t;
+#endif
+
 /*
  * Initializes a memory structure for accessing memory from this process.
  */
diff --git a/init/builtins.c b/init/builtins.c
index 5bda7a0..bb963c1 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -322,6 +322,14 @@
         if (_chown(args[1], uid, gid) < 0) {
             return -errno;
         }
+
+        /* chown may have cleared S_ISUID and S_ISGID, chmod again */
+        if (mode & (S_ISUID | S_ISGID)) {
+            ret = _chmod(args[1], mode);
+            if (ret == -1) {
+                return -errno;
+            }
+        }
     }
 
     return 0;
@@ -339,6 +347,12 @@
     { "ro",         MS_RDONLY },
     { "rw",         0 },
     { "remount",    MS_REMOUNT },
+    { "bind",       MS_BIND },
+    { "rec",        MS_REC },
+    { "unbindable", MS_UNBINDABLE },
+    { "private",    MS_PRIVATE },
+    { "slave",      MS_SLAVE },
+    { "shared",     MS_SHARED },
     { "defaults",   0 },
     { 0,            0 },
 };
diff --git a/init/devices.c b/init/devices.c
index 4ffc885..c30303f 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -600,6 +600,9 @@
      } else if (!strncmp(uevent->subsystem, "graphics", 8)) {
          base = "/dev/graphics/";
          make_dir(base, 0755);
+     } else if (!strncmp(uevent->subsystem, "drm", 3)) {
+         base = "/dev/dri/";
+         make_dir(base, 0755);
      } else if (!strncmp(uevent->subsystem, "oncrpc", 6)) {
          base = "/dev/oncrpc/";
          make_dir(base, 0755);
diff --git a/init/property_service.c b/init/property_service.c
index 5eb0a8a..c378aeb 100755
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -81,7 +81,7 @@
     { "sys.",             AID_SYSTEM,   0 },
     { "service.",         AID_SYSTEM,   0 },
     { "wlan.",            AID_SYSTEM,   0 },
-    { "bluetooth.",       AID_SYSTEM,   0 },
+    { "bluetooth.",       AID_BLUETOOTH,   0 },
     { "dhcp.",            AID_SYSTEM,   0 },
     { "dhcp.",            AID_DHCP,     0 },
     { "debug.",           AID_SYSTEM,   0 },
diff --git a/init/signal_handler.c b/init/signal_handler.c
index b170132..abccb40 100644
--- a/init/signal_handler.c
+++ b/init/signal_handler.c
@@ -131,11 +131,9 @@
     int s[2];
 
     struct sigaction act;
-
+    memset(&act, 0, sizeof(act));
     act.sa_handler = sigchld_handler;
     act.sa_flags = SA_NOCLDSTOP;
-    act.sa_mask = 0;
-    act.sa_restorer = NULL;
     sigaction(SIGCHLD, &act, 0);
 
     /* create a signalling mechanism for the sigchld handler */
diff --git a/libcorkscrew/Android.mk b/libcorkscrew/Android.mk
index 9019986..2786d8f 100644
--- a/libcorkscrew/Android.mk
+++ b/libcorkscrew/Android.mk
@@ -42,6 +42,12 @@
 LOCAL_SRC_FILES += $(x86_src_files)
 LOCAL_CFLAGS += -DCORKSCREW_HAVE_ARCH
 endif
+ifeq ($(TARGET_ARCH),mips)
+LOCAL_SRC_FILES += \
+	arch-mips/backtrace-mips.c \
+	arch-mips/ptrace-mips.c
+LOCAL_CFLAGS += -DCORKSCREW_HAVE_ARCH
+endif
 
 LOCAL_SHARED_LIBRARIES += libdl libcutils libgccdemangle
 
diff --git a/libcorkscrew/arch-mips/backtrace-mips.c b/libcorkscrew/arch-mips/backtrace-mips.c
new file mode 100644
index 0000000..07d4a24
--- /dev/null
+++ b/libcorkscrew/arch-mips/backtrace-mips.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Backtracing functions for mips
+ */
+
+#define LOG_TAG "Corkscrew"
+//#define LOG_NDEBUG 0
+
+#include "../backtrace-arch.h"
+#include "../backtrace-helper.h"
+#include <corkscrew/ptrace.h>
+
+#include <stdlib.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <limits.h>
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <sys/exec_elf.h>
+#include <cutils/log.h>
+
+/* For PTRACE_GETREGS */
+typedef struct {
+    /* FIXME: check this definition */
+    uint64_t regs[32];
+    uint64_t lo;
+    uint64_t hi;
+    uint64_t epc;
+    uint64_t badvaddr;
+    uint64_t status;
+    uint64_t cause;
+} user_regs_struct;
+
+/* Machine context at the time a signal was raised. */
+typedef struct ucontext {
+    /* FIXME: use correct definition */
+    uint32_t sp;
+    uint32_t ra;
+    uint32_t pc;
+} ucontext_t;
+
+/* Unwind state. */
+typedef struct {
+    uint32_t sp;
+    uint32_t ra;
+    uint32_t pc;
+} unwind_state_t;
+
+uintptr_t rewind_pc_arch(const memory_t* memory, uintptr_t pc) {
+    if (pc == 0)
+        return pc;
+    if ((pc & 1) == 0)
+        return pc-8;            /* jal/bal/jalr + branch delay slot */
+    return pc;
+}
+
+static ssize_t unwind_backtrace_common(const memory_t* memory,
+        const map_info_t* map_info_list,
+        unwind_state_t* state, backtrace_frame_t* backtrace,
+        size_t ignore_depth, size_t max_depth) {
+    size_t ignored_frames = 0;
+    size_t returned_frames = 0;
+
+    for (size_t index = 0; returned_frames < max_depth; index++) {
+        uintptr_t pc = index ? rewind_pc_arch(memory, state->pc) : state->pc;
+        backtrace_frame_t* frame;
+        uintptr_t addr;
+        int maxcheck = 1024;
+        int stack_size = 0, ra_offset = 0;
+        bool found_start = false;
+
+        frame = add_backtrace_entry(pc, backtrace, ignore_depth,
+                                    max_depth, &ignored_frames, &returned_frames);
+
+        if (frame)
+            frame->stack_top = state->sp;
+
+        ALOGV("#%d: frame=%p pc=%08x sp=%08x\n", index, frame, frame->absolute_pc, frame->stack_top);
+
+        for (addr = state->pc; maxcheck-- > 0 && !found_start; addr -= 4) {
+            uint32_t op;
+            if (!try_get_word(memory, addr, &op))
+                break;
+
+            // ALOGV("@0x%08x: 0x%08x\n", addr, op);
+            switch (op & 0xffff0000) {
+            case 0x27bd0000: // addiu sp, imm
+                {
+                    // looking for stack being decremented
+                    int32_t immediate = ((((int)op) << 16) >> 16);
+                    if (immediate < 0) {
+                        stack_size = -immediate;
+                        found_start = true;
+                        ALOGV("@0x%08x: found stack adjustment=%d\n", addr, stack_size);
+                    }
+                }
+                break;
+            case 0xafbf0000: // sw ra, imm(sp)
+                ra_offset = ((((int)op) << 16) >> 16);
+                ALOGV("@0x%08x: found ra offset=%d\n", addr, ra_offset);
+                break;
+            case 0x3c1c0000: // lui gp
+                    ALOGV("@0x%08x: found function boundary\n", addr);
+                found_start = true;
+                break;
+            default:
+                break;
+            }
+        }
+
+        if (ra_offset) {
+            uint32_t next_ra;
+            if (!try_get_word(memory, state->sp + ra_offset, &next_ra))
+                break;
+            state->ra = next_ra;
+            ALOGV("New ra: 0x%08x\n", state->ra);
+        }
+
+        if (stack_size) {
+            if (frame)
+                frame->stack_size = stack_size;
+            state->sp += stack_size;
+            ALOGV("New sp: 0x%08x\n", state->sp);
+        }
+
+        if (state->pc == state->ra && stack_size == 0)
+            break;
+
+        if (state->ra == 0)
+            break;
+
+        state->pc = state->ra;
+    }
+
+    ALOGV("returning %d frames\n", returned_frames);
+
+    return returned_frames;
+}
+
+ssize_t unwind_backtrace_signal_arch(siginfo_t* siginfo, void* sigcontext,
+        const map_info_t* map_info_list,
+        backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
+    const ucontext_t* uc = (const ucontext_t*)sigcontext;
+
+    unwind_state_t state;
+    state.sp = uc->sp;
+    state.pc = uc->pc;
+    state.ra = uc->ra;
+
+    ALOGV("unwind_backtrace_signal_arch: ignore_depth=%d max_depth=%d pc=0x%08x sp=0x%08x ra=0x%08x\n",
+          ignore_depth, max_depth, state.pc, state.sp, state.ra);
+
+    memory_t memory;
+    init_memory(&memory, map_info_list);
+    return unwind_backtrace_common(&memory, map_info_list,
+            &state, backtrace, ignore_depth, max_depth);
+}
+
+ssize_t unwind_backtrace_ptrace_arch(pid_t tid, const ptrace_context_t* context,
+        backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
+
+    user_regs_struct regs;
+    if (ptrace(PTRACE_GETREGS, tid, 0, &regs)) {
+        return -1;
+    }
+
+    unwind_state_t state;
+    state.sp = regs.regs[29];
+    state.ra = regs.regs[31];
+    state.pc = regs.epc;
+
+    ALOGV("unwind_backtrace_ptrace_arch: ignore_depth=%d max_depth=%d pc=0x%08x sp=0x%08x ra=0x%08x\n",
+          ignore_depth, max_depth, state.pc, state.sp, state.ra);
+
+    memory_t memory;
+    init_memory_ptrace(&memory, tid);
+    return unwind_backtrace_common(&memory, context->map_info_list,
+            &state, backtrace, ignore_depth, max_depth);
+}
diff --git a/libcorkscrew/arch-mips/ptrace-mips.c b/libcorkscrew/arch-mips/ptrace-mips.c
new file mode 100644
index 0000000..f0ea110
--- /dev/null
+++ b/libcorkscrew/arch-mips/ptrace-mips.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Corkscrew"
+//#define LOG_NDEBUG 0
+
+#include "../ptrace-arch.h"
+
+#include <cutils/log.h>
+
+void load_ptrace_map_info_data_arch(pid_t pid, map_info_t* mi, map_info_data_t* data) {
+}
+
+void free_ptrace_map_info_data_arch(map_info_t* mi, map_info_data_t* data) {
+}
diff --git a/libcorkscrew/arch-x86/backtrace-x86.c b/libcorkscrew/arch-x86/backtrace-x86.c
index 01d9ed5..6cdb0c8 100644
--- a/libcorkscrew/arch-x86/backtrace-x86.c
+++ b/libcorkscrew/arch-x86/backtrace-x86.c
@@ -55,13 +55,13 @@
     uint32_t esp;
 } unwind_state_t;
 
-uintptr_t rewind_pc_arch(const memory_t* memory, uintptr_t pc) {
+uintptr_t rewind_pc_arch(const memory_t* memory __attribute__((unused)), uintptr_t pc) {
     // TODO: Implement for x86.
     return pc;
 }
 
 static ssize_t unwind_backtrace_common(const memory_t* memory,
-        const map_info_t* map_info_list,
+        const map_info_t* map_info_list __attribute__((unused)),
         unwind_state_t* state, backtrace_frame_t* backtrace,
         size_t ignore_depth, size_t max_depth) {
     size_t ignored_frames = 0;
@@ -90,7 +90,7 @@
     return returned_frames;
 }
 
-ssize_t unwind_backtrace_signal_arch(siginfo_t* siginfo, void* sigcontext,
+ssize_t unwind_backtrace_signal_arch(siginfo_t* siginfo __attribute__((unused)), void* sigcontext,
         const map_info_t* map_info_list,
         backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) {
     const ucontext_t* uc = (const ucontext_t*)sigcontext;
diff --git a/libcorkscrew/arch-x86/ptrace-x86.c b/libcorkscrew/arch-x86/ptrace-x86.c
index f0ea110..07cfd3a 100644
--- a/libcorkscrew/arch-x86/ptrace-x86.c
+++ b/libcorkscrew/arch-x86/ptrace-x86.c
@@ -21,8 +21,11 @@
 
 #include <cutils/log.h>
 
-void load_ptrace_map_info_data_arch(pid_t pid, map_info_t* mi, map_info_data_t* data) {
+void load_ptrace_map_info_data_arch(pid_t pid __attribute__((unused)),
+                                    map_info_t* mi __attribute__((unused)),
+                                    map_info_data_t* data __attribute__((unused))) {
 }
 
-void free_ptrace_map_info_data_arch(map_info_t* mi, map_info_data_t* data) {
+void free_ptrace_map_info_data_arch(map_info_t* mi __attribute__((unused)),
+                                    map_info_data_t* data __attribute__((unused))) {
 }
diff --git a/libcorkscrew/backtrace.c b/libcorkscrew/backtrace.c
index eec53a2..3697d18 100644
--- a/libcorkscrew/backtrace.c
+++ b/libcorkscrew/backtrace.c
@@ -124,7 +124,7 @@
     size_t returned_frames;
 } g_unwind_signal_state;
 
-static void unwind_backtrace_thread_signal_handler(int n, siginfo_t* siginfo, void* sigcontext) {
+static void unwind_backtrace_thread_signal_handler(int n __attribute__((unused)), siginfo_t* siginfo, void* sigcontext) {
     if (!android_atomic_acquire_cas(gettid(), STATE_DUMPING, &g_unwind_signal_state.tid_state)) {
         g_unwind_signal_state.returned_frames = unwind_backtrace_signal_arch(
                 siginfo, sigcontext,
@@ -305,7 +305,7 @@
     }
 }
 
-void format_backtrace_line(unsigned frameNumber, const backtrace_frame_t* frame,
+void format_backtrace_line(unsigned frameNumber, const backtrace_frame_t* frame __attribute__((unused)),
         const backtrace_symbol_t* symbol, char* buffer, size_t bufferSize) {
     const char* mapName = symbol->map_name ? symbol->map_name : "<unknown>";
     const char* symbolName = symbol->demangled_name ? symbol->demangled_name : symbol->symbol_name;
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index e62c3ea..64ff522 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -15,6 +15,10 @@
 copy_from += etc/vold.fstab
 endif
 
+ifeq ($(TARGET_PRODUCT),full_mips)
+copy_from += etc/vold.fstab
+endif
+
 # the /system/etc/init.goldfish.sh is needed to enable emulator support
 # in the system image. In theory, we don't need these for -user builds
 # which are device-specific. However, these builds require at the moment
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index 43a687f..3889298 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -18,6 +18,9 @@
 # gpu driver for adreno200 is globally accessible
 /dev/kgsl                 0666   root       root
 
+# kms driver for drm based gpu
+/dev/dri/*                0666   root       graphics
+
 # these should not be world writable
 /dev/diag                 0660   radio      radio
 /dev/diag_arm9            0660   radio      radio
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index 877a524..8d87ee9 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -1314,11 +1314,23 @@
             source_path = arg;
         else if (!dest_path)
             dest_path = arg;
-        else if (!uid)
-            uid = strtoul(arg, 0, 10);
-        else if (!gid)
-            gid = strtoul(arg, 0, 10);
-        else {
+        else if (!uid) {
+            char* endptr = NULL;
+            errno = 0;
+            uid = strtoul(arg, &endptr, 10);
+            if (*endptr != '\0' || errno != 0) {
+                ERROR("Invalid uid");
+                return usage();
+            }
+        } else if (!gid) {
+            char* endptr = NULL;
+            errno = 0;
+            gid = strtoul(arg, &endptr, 10);
+            if (*endptr != '\0' || errno != 0) {
+                ERROR("Invalid gid");
+                return usage();
+            }
+        } else {
             ERROR("too many arguments\n");
             return usage();
         }