diff options
Diffstat (limited to 'libc')
63 files changed, 3241 insertions, 271 deletions
diff --git a/libc/Android.mk b/libc/Android.mk index aae80da5d..30af6ca12 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -187,7 +187,6 @@ libc_common_src_files := \ string/strcat.c \ string/strchr.c \ string/strcoll.c \ - string/strcpy.c \ string/strcspn.c \ string/strdup.c \ string/strerror.c \ @@ -354,13 +353,16 @@ libc_common_src_files += \ arch-arm/bionic/setjmp.S \ arch-arm/bionic/sigsetjmp.S \ arch-arm/bionic/strlen.c.arm \ + arch-arm/bionic/strcpy.S \ + arch-arm/bionic/strcmp.S \ arch-arm/bionic/syscall.S \ string/memmove.c.arm \ string/bcopy.c \ - string/strcmp.c \ string/strncmp.c \ unistd/socketcalls.c + + # These files need to be arm so that gdbserver # can set breakpoints in them without messing # up any thumb code. @@ -403,6 +405,7 @@ libc_common_src_files += \ arch-x86/string/strncmp_wrapper.S \ arch-x86/string/strlen_wrapper.S \ bionic/pthread-rwlocks.c \ + string/strcpy.c \ bionic/pthread-timers.c \ bionic/ptrace.c @@ -442,6 +445,7 @@ libc_common_src_files += \ string/memcmp.c \ string/strlen.c \ bionic/pthread-rwlocks.c \ + string/strcpy.c \ bionic/pthread-timers.c \ bionic/ptrace.c \ unistd/socketcalls.c @@ -494,6 +498,9 @@ ifeq ($(TARGET_ARCH),arm) ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true) libc_common_cflags += -DHAVE_ARM_TLS_REGISTER endif + ifeq ($(TARGET_HAVE_TEGRA_ERRATA_657451),true) + libc_common_cflags += -DHAVE_TEGRA_ERRATA_657451 + endif else # !arm ifeq ($(TARGET_ARCH),x86) libc_crt_target_cflags := -m32 @@ -516,6 +523,10 @@ endif # libc_crt_target_cflags += -I$(LOCAL_PATH)/private +ifeq ($(BOARD_USE_NASTY_PTHREAD_CREATE_HACK),true) + libc_common_cflags += -DNASTY_PTHREAD_CREATE_HACK +endif + ifeq ($(TARGET_ARCH),arm) libc_crt_target_cflags += -DCRT_LEGACY_WORKAROUND endif @@ -597,6 +608,14 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(libc_common_src_files) LOCAL_CFLAGS := $(libc_common_cflags) +ifdef NEEDS_ARM_ERRATA_754319_754320 +asm_flags := \ + --defsym NEEDS_ARM_ERRATA_754319_754320_ASM=1 + +LOCAL_CFLAGS+= \ + $(foreach f,$(asm_flags),-Wa,"$(f)") +endif + ifeq ($(TARGET_ARCH),arm) LOCAL_CFLAGS += -DCRT_LEGACY_WORKAROUND endif diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT index 0850b8282..a2b7a32ce 100644 --- a/libc/SYSCALLS.TXT +++ b/libc/SYSCALLS.TXT @@ -173,7 +173,7 @@ int __timer_gettime:timer_gettime(timer_t, struct itimerspec*) int __timer_getoverrun:timer_getoverrun(timer_t) 260,262 int __timer_delete:timer_delete(timer_t) 261,263 int utimes(const char*, const struct timeval tvp[2]) 269, 271 - +int adjtimex(struct timex *) 124 # signals int sigaction(int, const struct sigaction *, struct sigaction *) 67 int sigprocmask(int, const sigset_t *, sigset_t *) 126 @@ -264,3 +264,9 @@ int eventfd:eventfd2(unsigned int, int) 356,328 # ARM-specific ARM_NR_BASE == 0x0f0000 == 983040 int __set_tls:ARM_set_tls(void*) 983045,-1 int cacheflush:ARM_cacheflush(long start, long end, long flags) 983042,-1 + +# busybox: 2010-01-17 +int stime(time_t *) 25 +int swapon(const char *, int) 87 +int swapoff(const char *) 115 +pid_t getsid(pid_t pid) 147 diff --git a/libc/arch-arm/bionic/arm_memcpy.S b/libc/arch-arm/bionic/arm_memcpy.S new file mode 100644 index 000000000..ae1cf1ad1 --- /dev/null +++ b/libc/arch-arm/bionic/arm_memcpy.S @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2011 Texas Instruments + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + .text + .fpu neon + .code 32 + .align 4 + + +/* r0 - dest */ +/* r1 - src */ +/* r2 - length */ + .global memcpy +memcpy: + .fnstart +#if defined TARGET_BOARD_PLATFORM == omap4 +#define CACHE_LINE_SIZE 32 +#else +#define CACHE_LINE_SIZE 64 +#endif + CMP r2,#3 + BLS _BMLIB_memcpy_lastbytes + ANDS r12,r0,#3 + BEQ l1; + LDRB r3,[r1],#1 + CMP r12,#2 + ADD r2,r2,r12 + LDRLSB r12, [r1], #1 + STRB r3,[r0],#1 + LDRCCB r3,[r1],#1 + STRLSB r12,[r0],#1 + SUB r2,r2,#4 + STRCCB r3,[r0],#1 +l1: + ANDS r3,r1,#3 + BEQ _BMLIB_aeabi_memcpy4 +l3: + SUBS r2,r2,#8 + BCC l2 + LDR r3,[r1],#4 + LDR r12,[r1],#4 + STR r3,[r0],#4 + STR r12,[r0],#4 + B l3 +l2: + ADDS r2,r2,#4 + LDRPL r3,[r1],#4 + STRPL r3,[r0],#4 + MOV r0,r0 +_BMLIB_memcpy_lastbytes: + LSLS r2,r2,#31 + LDRCSB r3,[r1],#1 + LDRCSB r12,[r1],#1 + LDRMIB r2,[r1],#1 + STRCSB r3,[r0],#1 + STRCSB r12,[r0],#1 + STRMIB r2,[r0],#1 + BX lr + +_BMLIB_aeabi_memcpy4: + PUSH {r4-r8,lr} + SUBS r2,r2,#0x20 + BCC l4 + DSB +#ifndef NOPLD + PLD [r1, #0] + PLD [r1, #(CACHE_LINE_SIZE*1)] + PLD [r1, #(CACHE_LINE_SIZE*2)] + PLD [r1, #(CACHE_LINE_SIZE*3)] + PLD [r1, #(CACHE_LINE_SIZE*4)] +#endif +l5: +#ifndef NOPLD + PLD [r1, #(CACHE_LINE_SIZE*5)] +#endif + LDMCS r1!,{r3-r8,r12,lr} + STMCS r0!,{r3-r8,r12,lr} + SUBS r2,r2,#0x20 + BCS l5 +l4: + LSLS r12,r2,#28 + LDMCS r1!,{r3,r4,r12,lr} + STMCS r0!,{r3,r4,r12,lr} + LDMMI r1!,{r3,r4} + STMMI r0!,{r3,r4} + POP {r4-r8,lr} + LSLS r12,r2,#30 + LDRCS r3,[r1],#4 + STRCS r3,[r0],#4 + BXEQ lr +_BMLIB_memcpy_lastbytes_aligned: + LSLS r2,r2,#31 + LDRCSH r3,[r1],#2 + LDRMIB r2,[r1],#1 + STRCSH r3,[r0],#2 + STRMIB r2,[r0],#1 + BX lr + .fnend diff --git a/libc/arch-arm/bionic/ffs.S b/libc/arch-arm/bionic/ffs.S index f11141c97..052b46a53 100644 --- a/libc/arch-arm/bionic/ffs.S +++ b/libc/arch-arm/bionic/ffs.S @@ -36,47 +36,14 @@ * 6 bits as an index into the table. This algorithm should be a win * over the checking each bit in turn as per the C compiled version. * - * under ARMv5 there's an instruction called CLZ (count leading Zero's) that - * could be used - * - * This is the ffs algorithm devised by d.seal and posted to comp.sys.arm on - * 16 Feb 1994. + * since ARMv5 there's an instruction called CLZ (count leading Zero's) */ ENTRY(ffs) /* Standard trick to isolate bottom bit in r0 or 0 if r0 = 0 on entry */ rsb r1, r0, #0 ands r0, r0, r1 -#ifndef __ARM_ARCH_5__ - /* - * now r0 has at most one set bit, call this X - * if X = 0, all further instructions are skipped - */ - adrne r2, .L_ffs_table - orrne r0, r0, r0, lsl #4 /* r0 = X * 0x11 */ - orrne r0, r0, r0, lsl #6 /* r0 = X * 0x451 */ - rsbne r0, r0, r0, lsl #16 /* r0 = X * 0x0450fbaf */ - - /* now lookup in table indexed on top 6 bits of r0 */ - ldrneb r0, [ r2, r0, lsr #26 ] - - bx lr - -.text; -.type .L_ffs_table, _ASM_TYPE_OBJECT; -.L_ffs_table: -/* 0 1 2 3 4 5 6 7 */ - .byte 0, 1, 2, 13, 3, 7, 0, 14 /* 0- 7 */ - .byte 4, 0, 8, 0, 0, 0, 0, 15 /* 8-15 */ - .byte 11, 5, 0, 0, 9, 0, 0, 26 /* 16-23 */ - .byte 0, 0, 0, 0, 0, 22, 28, 16 /* 24-31 */ - .byte 32, 12, 6, 0, 0, 0, 0, 0 /* 32-39 */ - .byte 10, 0, 0, 25, 0, 0, 21, 27 /* 40-47 */ - .byte 31, 0, 0, 0, 0, 24, 0, 20 /* 48-55 */ - .byte 30, 0, 23, 19, 29, 18, 17, 0 /* 56-63 */ -#else clzne r0, r0 rsbne r0, r0, #32 bx lr -#endif diff --git a/libc/arch-arm/bionic/memcpy.S b/libc/arch-arm/bionic/memcpy.S index ba55996ec..79e878951 100644 --- a/libc/arch-arm/bionic/memcpy.S +++ b/libc/arch-arm/bionic/memcpy.S @@ -141,6 +141,9 @@ memcpy: strcsb ip, [r0], #1 strcsb lr, [r0], #1 +.ifdef NEEDS_ARM_ERRATA_754319_754320_ASM + VMOV s0,s0 @ NOP for ARM Errata +.endif ldmfd sp!, {r0, lr} bx lr .fnend diff --git a/libc/arch-arm/bionic/strcmp.S b/libc/arch-arm/bionic/strcmp.S new file mode 100644 index 000000000..9fdbd567e --- /dev/null +++ b/libc/arch-arm/bionic/strcmp.S @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2011 The Android Open Source Project + * Copyright (c) 2008 ARM Ltd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <machine/cpu-features.h> + + .text + + .global strcmp + .type strcmp, %function + .align 4 + +#ifdef __ARMEB__ +#define SHFT2LSB lsl +#define SHFT2LSBEQ lsleq +#define SHFT2MSB lsr +#define SHFT2MSBEQ lsreq +#define MSB 0x000000ff +#define LSB 0xff000000 +#else +#define SHFT2LSB lsr +#define SHFT2LSBEQ lsreq +#define SHFT2MSB lsl +#define SHFT2MSBEQ lsleq +#define MSB 0xff000000 +#define LSB 0x000000ff +#endif + +#define magic1(REG) REG +#define magic2(REG) REG, lsl #7 + +strcmp: + .fnstart + PLD(r0, #0) + PLD(r1, #0) + eor r2, r0, r1 + tst r2, #3 + + /* Strings not at same byte offset from a word boundary. */ + bne .Lstrcmp_unaligned + ands r2, r0, #3 + bic r0, r0, #3 + bic r1, r1, #3 + ldr ip, [r0], #4 + it eq + ldreq r3, [r1], #4 + beq 1f + + /* Although s1 and s2 have identical initial alignment, they are + * not currently word aligned. Rather than comparing bytes, + * make sure that any bytes fetched from before the addressed + * bytes are forced to 0xff. Then they will always compare + * equal. + */ + eor r2, r2, #3 + lsl r2, r2, #3 + mvn r3, #MSB + SHFT2LSB r2, r3, r2 + ldr r3, [r1], #4 + orr ip, ip, r2 + orr r3, r3, r2 +1: + /* Load the 'magic' constant 0x01010101. */ + str r4, [sp, #-4]! + mov r4, #1 + orr r4, r4, r4, lsl #8 + orr r4, r4, r4, lsl #16 + .p2align 2 +4: + PLD(r0, #8) + PLD(r1, #8) + sub r2, ip, magic1(r4) + cmp ip, r3 + itttt eq + + /* check for any zero bytes in first word */ + biceq r2, r2, ip + tsteq r2, magic2(r4) + ldreq ip, [r0], #4 + ldreq r3, [r1], #4 + beq 4b +2: + /* There's a zero or a different byte in the word */ + SHFT2MSB r0, ip, #24 + SHFT2LSB ip, ip, #8 + cmp r0, #1 + it cs + cmpcs r0, r3, SHFT2MSB #24 + it eq + SHFT2LSBEQ r3, r3, #8 + beq 2b + /* On a big-endian machine, r0 contains the desired byte in bits + * 0-7; on a little-endian machine they are in bits 24-31. In + * both cases the other bits in r0 are all zero. For r3 the + * interesting byte is at the other end of the word, but the + * other bits are not necessarily zero. We need a signed result + * representing the differnece in the unsigned bytes, so for the + * little-endian case we can't just shift the interesting bits up. + */ +#ifdef __ARMEB__ + sub r0, r0, r3, lsr #24 +#else + and r3, r3, #255 + /* No RSB instruction in Thumb2 */ +#ifdef __thumb2__ + lsr r0, r0, #24 + sub r0, r0, r3 +#else + rsb r0, r3, r0, lsr #24 +#endif +#endif + ldr r4, [sp], #4 + bx lr + .fnend + +.Lstrcmp_unaligned: + wp1 .req r0 + wp2 .req r1 + b1 .req r2 + w1 .req r4 + w2 .req r5 + t1 .req ip + @ r3 is scratch + + /* First of all, compare bytes until wp1(sp1) is word-aligned. */ +1: + tst wp1, #3 + beq 2f + ldrb r2, [wp1], #1 + ldrb r3, [wp2], #1 + cmp r2, #1 + it cs + cmpcs r2, r3 + beq 1b + sub r0, r2, r3 + bx lr + +2: + str r5, [sp, #-4]! + str r4, [sp, #-4]! + mov b1, #1 + orr b1, b1, b1, lsl #8 + orr b1, b1, b1, lsl #16 + + and t1, wp2, #3 + bic wp2, wp2, #3 + ldr w1, [wp1], #4 + ldr w2, [wp2], #4 + cmp t1, #2 + beq 2f + bhi 3f + + /* Critical inner Loop: Block with 3 bytes initial overlap */ + .p2align 2 +1: + bic t1, w1, #MSB + cmp t1, w2, SHFT2LSB #8 + sub r3, w1, b1 + bic r3, r3, w1 + bne 4f + ands r3, r3, b1, lsl #7 + it eq + ldreq w2, [wp2], #4 + bne 5f + eor t1, t1, w1 + cmp t1, w2, SHFT2MSB #24 + bne 6f + ldr w1, [wp1], #4 + b 1b +4: + SHFT2LSB w2, w2, #8 + b 8f + +5: +#ifdef __ARMEB__ + /* The syndrome value may contain false ones if the string ends + * with the bytes 0x01 0x00 + */ + tst w1, #0xff000000 + itt ne + tstne w1, #0x00ff0000 + tstne w1, #0x0000ff00 + beq 7f +#else + bics r3, r3, #0xff000000 + bne 7f +#endif + ldrb w2, [wp2] + SHFT2LSB t1, w1, #24 +#ifdef __ARMEB__ + lsl w2, w2, #24 +#endif + b 8f + +6: + SHFT2LSB t1, w1, #24 + and w2, w2, #LSB + b 8f + + /* Critical inner Loop: Block with 2 bytes initial overlap */ + .p2align 2 +2: + SHFT2MSB t1, w1, #16 + sub r3, w1, b1 + SHFT2LSB t1, t1, #16 + bic r3, r3, w1 + cmp t1, w2, SHFT2LSB #16 + bne 4f + ands r3, r3, b1, lsl #7 + it eq + ldreq w2, [wp2], #4 + bne 5f + eor t1, t1, w1 + cmp t1, w2, SHFT2MSB #16 + bne 6f + ldr w1, [wp1], #4 + b 2b + +5: +#ifdef __ARMEB__ + /* The syndrome value may contain false ones if the string ends + * with the bytes 0x01 0x00 + */ + tst w1, #0xff000000 + it ne + tstne w1, #0x00ff0000 + beq 7f +#else + lsls r3, r3, #16 + bne 7f +#endif + ldrh w2, [wp2] + SHFT2LSB t1, w1, #16 +#ifdef __ARMEB__ + lsl w2, w2, #16 +#endif + b 8f + +6: + SHFT2MSB w2, w2, #16 + SHFT2LSB t1, w1, #16 +4: + SHFT2LSB w2, w2, #16 + b 8f + + /* Critical inner Loop: Block with 1 byte initial overlap */ + .p2align 2 +3: + and t1, w1, #LSB + cmp t1, w2, SHFT2LSB #24 + sub r3, w1, b1 + bic r3, r3, w1 + bne 4f + ands r3, r3, b1, lsl #7 + it eq + ldreq w2, [wp2], #4 + bne 5f + eor t1, t1, w1 + cmp t1, w2, SHFT2MSB #8 + bne 6f + ldr w1, [wp1], #4 + b 3b +4: + SHFT2LSB w2, w2, #24 + b 8f +5: + /* The syndrome value may contain false ones if the string ends + * with the bytes 0x01 0x00 + */ + tst w1, #LSB + beq 7f + ldr w2, [wp2], #4 +6: + SHFT2LSB t1, w1, #8 + bic w2, w2, #MSB + b 8f +7: + mov r0, #0 + ldr r4, [sp], #4 + ldr r5, [sp], #4 + bx lr + +8: + and r2, t1, #LSB + and r0, w2, #LSB + cmp r0, #1 + it cs + cmpcs r0, r2 + itt eq + SHFT2LSBEQ t1, t1, #8 + SHFT2LSBEQ w2, w2, #8 + beq 8b + sub r0, r2, r0 + ldr r4, [sp], #4 + ldr r5, [sp], #4 + bx lr diff --git a/libc/arch-arm/bionic/strcpy.S b/libc/arch-arm/bionic/strcpy.S new file mode 100644 index 000000000..70c353f79 --- /dev/null +++ b/libc/arch-arm/bionic/strcpy.S @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * Copyright (c) 2008 ARM Ltd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Android adaptation and tweak by Jim Huang <jserv@0xlab.org>. + */ + +#include <machine/cpu-features.h> + + .text + + .global strcpy + .type strcpy, %function + .align 4 + +strcpy: + .fnstart + PLD(r1, #0) + eor r2, r0, r1 + mov ip, r0 + tst r2, #3 + bne 4f + tst r1, #3 + bne 3f +5: + str r5, [sp, #-4]! + mov r5, #0x01 + orr r5, r5, r5, lsl #8 + orr r5, r5, r5, lsl #16 + + str r4, [sp, #-4]! + tst r1, #4 + ldr r3, [r1], #4 + beq 2f + sub r2, r3, r5 + bics r2, r2, r3 + tst r2, r5, lsl #7 + itt eq + streq r3, [ip], #4 + ldreq r3, [r1], #4 + bne 1f + /* Inner loop. We now know that r1 is 64-bit aligned, so we + can safely fetch up to two words. This allows us to avoid + load stalls. */ + .p2align 2 +2: + PLD(r1, #8) + ldr r4, [r1], #4 + sub r2, r3, r5 + bics r2, r2, r3 + tst r2, r5, lsl #7 + sub r2, r4, r5 + bne 1f + str r3, [ip], #4 + bics r2, r2, r4 + tst r2, r5, lsl #7 + itt eq + ldreq r3, [r1], #4 + streq r4, [ip], #4 + beq 2b + mov r3, r4 +1: +#ifdef __ARMEB__ + rors r3, r3, #24 +#endif + strb r3, [ip], #1 + tst r3, #0xff +#ifdef __ARMEL__ + ror r3, r3, #8 +#endif + bne 1b + ldr r4, [sp], #4 + ldr r5, [sp], #4 + bx lr + + /* Strings have the same offset from word alignment, but it's + not zero. */ +3: + tst r1, #1 + beq 1f + ldrb r2, [r1], #1 + strb r2, [ip], #1 + cmp r2, #0 + it eq + bxeq lr +1: + tst r1, #2 + beq 5b + ldrh r2, [r1], #2 +#ifdef __ARMEB__ + tst r2, #0xff00 + iteet ne + strneh r2, [ip], #2 + lsreq r2, r2, #8 + streqb r2, [ip] + tstne r2, #0xff +#else + tst r2, #0xff + itet ne + strneh r2, [ip], #2 + streqb r2, [ip] + tstne r2, #0xff00 +#endif + bne 5b + bx lr + + /* src and dst do not have a common word-alignement. Fall back to + byte copying. */ +4: + ldrb r2, [r1], #1 + strb r2, [ip], #1 + cmp r2, #0 + bne 4b + bx lr diff --git a/libc/arch-arm/include/endian.h b/libc/arch-arm/include/endian.h index 04204ed4c..e34872fcb 100644 --- a/libc/arch-arm/include/endian.h +++ b/libc/arch-arm/include/endian.h @@ -1,5 +1,86 @@ /* $OpenBSD: endian.h,v 1.3 2005/12/13 00:35:23 millert Exp $ */ +/* + * Copyright (C) 2010 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _ARM_ENDIAN_H_ +#define _ARM_ENDIAN_H_ + +#ifdef __GNUC__ + +/* NOTE: header <machine/cpu-features.h> could not be included directly + * since it defines extra macros, such as PLD. + */ +#if defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || \ + defined(__ARM_ARCH_7__) || \ + defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \ + defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \ + defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) + +/* According to RealView Assembler User's Guide, REV and REV16 are available + * in Thumb code and 16-bit instructions when used in Thumb-2 code. + * + * REV Rd, Rm + * Rd and Rm must both be Lo registers. + * + * REV16 Rd, Rm + * Rd and Rm must both be Lo registers. + */ +#ifdef __thumb__ +#define REV_LO_REG asm("r4") +#else +#define REV_LO_REG +#endif + +#define __swap16md(x) ({ \ + register u_int16_t _x REV_LO_REG = (x); \ + __asm volatile ("rev16 %0, %0" : "+r" (_x)); \ + _x; \ +}) + +#define __swap32md(x) ({ \ + register u_int32_t _x REV_LO_REG = (x); \ + __asm volatile ("rev %0, %0" : "+r" (_x)); \ + _x; \ +}) + +#define __swap64md(x) ({ \ + u_int64_t _x = (x); \ + (u_int64_t) __swap32md(_x >> 32) | \ + (u_int64_t) __swap32md(_x & 0xffffffff) << 32; \ +}) + +/* Tell sys/endian.h we have MD variants of the swap macros. */ +#define MD_SWAP + +#endif /* __ARM_ARCH__ */ +#endif /* __GNUC__ */ + #ifdef __ARMEB__ #define _BYTE_ORDER _BIG_ENDIAN #else @@ -8,3 +89,5 @@ #define __STRICT_ALIGNMENT #include <sys/types.h> #include <sys/endian.h> + +#endif /* !_ARM_ENDIAN_H_ */ diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk index ba78c1846..869e61377 100644 --- a/libc/arch-arm/syscalls.mk +++ b/libc/arch-arm/syscalls.mk @@ -123,6 +123,7 @@ syscall_src += arch-arm/syscalls/__timer_gettime.S syscall_src += arch-arm/syscalls/__timer_getoverrun.S syscall_src += arch-arm/syscalls/__timer_delete.S syscall_src += arch-arm/syscalls/utimes.S +syscall_src += arch-arm/syscalls/adjtimex.S syscall_src += arch-arm/syscalls/sigaction.S syscall_src += arch-arm/syscalls/sigprocmask.S syscall_src += arch-arm/syscalls/__sigsuspend.S @@ -175,3 +176,7 @@ syscall_src += arch-arm/syscalls/poll.S syscall_src += arch-arm/syscalls/eventfd.S syscall_src += arch-arm/syscalls/__set_tls.S syscall_src += arch-arm/syscalls/cacheflush.S +syscall_src += arch-arm/syscalls/stime.S +syscall_src += arch-arm/syscalls/swapon.S +syscall_src += arch-arm/syscalls/swapoff.S +syscall_src += arch-arm/syscalls/getsid.S diff --git a/libc/arch-arm/syscalls/adjtimex.S b/libc/arch-arm/syscalls/adjtimex.S new file mode 100644 index 000000000..c89ff1bf2 --- /dev/null +++ b/libc/arch-arm/syscalls/adjtimex.S @@ -0,0 +1,19 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type adjtimex, #function + .globl adjtimex + .align 4 + .fnstart + +adjtimex: + .save {r4, r7} + stmfd sp!, {r4, r7} + ldr r7, =__NR_adjtimex + swi #0 + ldmfd sp!, {r4, r7} + movs r0, r0 + bxpl lr + b __set_syscall_errno + .fnend diff --git a/libc/arch-arm/syscalls/getsid.S b/libc/arch-arm/syscalls/getsid.S new file mode 100644 index 000000000..6d9b3afea --- /dev/null +++ b/libc/arch-arm/syscalls/getsid.S @@ -0,0 +1,19 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type getsid, #function + .globl getsid + .align 4 + .fnstart + +getsid: + .save {r4, r7} + stmfd sp!, {r4, r7} + ldr r7, =__NR_getsid + swi #0 + ldmfd sp!, {r4, r7} + movs r0, r0 + bxpl lr + b __set_syscall_errno + .fnend diff --git a/libc/arch-arm/syscalls/stime.S b/libc/arch-arm/syscalls/stime.S new file mode 100644 index 000000000..05f131bb8 --- /dev/null +++ b/libc/arch-arm/syscalls/stime.S @@ -0,0 +1,19 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type stime, #function + .globl stime + .align 4 + .fnstart + +stime: + .save {r4, r7} + stmfd sp!, {r4, r7} + ldr r7, =__NR_stime + swi #0 + ldmfd sp!, {r4, r7} + movs r0, r0 + bxpl lr + b __set_syscall_errno + .fnend diff --git a/libc/arch-arm/syscalls/swapoff.S b/libc/arch-arm/syscalls/swapoff.S new file mode 100644 index 000000000..f1faae13c --- /dev/null +++ b/libc/arch-arm/syscalls/swapoff.S @@ -0,0 +1,19 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type swapoff, #function + .globl swapoff + .align 4 + .fnstart + +swapoff: + .save {r4, r7} + stmfd sp!, {r4, r7} + ldr r7, =__NR_swapoff + swi #0 + ldmfd sp!, {r4, r7} + movs r0, r0 + bxpl lr + b __set_syscall_errno + .fnend diff --git a/libc/arch-arm/syscalls/swapon.S b/libc/arch-arm/syscalls/swapon.S new file mode 100644 index 000000000..fb67d8168 --- /dev/null +++ b/libc/arch-arm/syscalls/swapon.S @@ -0,0 +1,19 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type swapon, #function + .globl swapon + .align 4 + .fnstart + +swapon: + .save {r4, r7} + stmfd sp!, {r4, r7} + ldr r7, =__NR_swapon + swi #0 + ldmfd sp!, {r4, r7} + movs r0, r0 + bxpl lr + b __set_syscall_errno + .fnend diff --git a/libc/arch-sh/syscalls.mk b/libc/arch-sh/syscalls.mk index a87419d96..891678594 100644 --- a/libc/arch-sh/syscalls.mk +++ b/libc/arch-sh/syscalls.mk @@ -126,6 +126,7 @@ syscall_src += arch-sh/syscalls/__timer_gettime.S syscall_src += arch-sh/syscalls/__timer_getoverrun.S syscall_src += arch-sh/syscalls/__timer_delete.S syscall_src += arch-sh/syscalls/utimes.S +syscall_src += arch-sh/syscalls/adjtimex.S syscall_src += arch-sh/syscalls/sigaction.S syscall_src += arch-sh/syscalls/sigprocmask.S syscall_src += arch-sh/syscalls/__sigsuspend.S @@ -162,3 +163,7 @@ syscall_src += arch-sh/syscalls/inotify_add_watch.S syscall_src += arch-sh/syscalls/inotify_rm_watch.S syscall_src += arch-sh/syscalls/poll.S syscall_src += arch-sh/syscalls/eventfd.S +syscall_src += arch-sh/syscalls/stime.S +syscall_src += arch-sh/syscalls/swapon.S +syscall_src += arch-sh/syscalls/swapoff.S +syscall_src += arch-sh/syscalls/getsid.S diff --git a/libc/arch-sh/syscalls/adjtimex.S b/libc/arch-sh/syscalls/adjtimex.S new file mode 100644 index 000000000..255bd4734 --- /dev/null +++ b/libc/arch-sh/syscalls/adjtimex.S @@ -0,0 +1,32 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type adjtimex, @function + .globl adjtimex + .align 4 + +adjtimex: + + /* invoke trap */ + mov.l 0f, r3 /* trap num */ + trapa #(1 + 0x10) + + /* check return value */ + cmp/pz r0 + bt __NR_adjtimex_end + + /* keep error number */ + sts.l pr, @-r15 + mov.l 1f, r1 + jsr @r1 + mov r0, r4 + lds.l @r15+, pr + +__NR_adjtimex_end: + rts + nop + + .align 2 +0: .long __NR_adjtimex +1: .long __set_syscall_errno diff --git a/libc/arch-sh/syscalls/getsid.S b/libc/arch-sh/syscalls/getsid.S new file mode 100644 index 000000000..73d5e3201 --- /dev/null +++ b/libc/arch-sh/syscalls/getsid.S @@ -0,0 +1,32 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type getsid, @function + .globl getsid + .align 4 + +getsid: + + /* invoke trap */ + mov.l 0f, r3 /* trap num */ + trapa #(1 + 0x10) + + /* check return value */ + cmp/pz r0 + bt __NR_getsid_end + + /* keep error number */ + sts.l pr, @-r15 + mov.l 1f, r1 + jsr @r1 + mov r0, r4 + lds.l @r15+, pr + +__NR_getsid_end: + rts + nop + + .align 2 +0: .long __NR_getsid +1: .long __set_syscall_errno diff --git a/libc/arch-sh/syscalls/readlinkat.S b/libc/arch-sh/syscalls/readlinkat.S new file mode 100644 index 000000000..5b23060b3 --- /dev/null +++ b/libc/arch-sh/syscalls/readlinkat.S @@ -0,0 +1,32 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type readlinkat, @function + .globl readlinkat + .align 4 + +readlinkat: + + /* invoke trap */ + mov.l 0f, r3 /* trap num */ + trapa #(4 + 0x10) + + /* check return value */ + cmp/pz r0 + bt __NR_readlinkat_end + + /* keep error number */ + sts.l pr, @-r15 + mov.l 1f, r1 + jsr @r1 + mov r0, r4 + lds.l @r15+, pr + +__NR_readlinkat_end: + rts + nop + + .align 2 +0: .long __NR_readlinkat +1: .long __set_syscall_errno diff --git a/libc/arch-sh/syscalls/signalfd.S b/libc/arch-sh/syscalls/signalfd.S new file mode 100644 index 000000000..896e90900 --- /dev/null +++ b/libc/arch-sh/syscalls/signalfd.S @@ -0,0 +1,32 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type signalfd, @function + .globl signalfd + .align 4 + +signalfd: + + /* invoke trap */ + mov.l 0f, r3 /* trap num */ + trapa #(3 + 0x10) + + /* check return value */ + cmp/pz r0 + bt __NR_signalfd_end + + /* keep error number */ + sts.l pr, @-r15 + mov.l 1f, r1 + jsr @r1 + mov r0, r4 + lds.l @r15+, pr + +__NR_signalfd_end: + rts + nop + + .align 2 +0: .long __NR_signalfd +1: .long __set_syscall_errno diff --git a/libc/arch-sh/syscalls/stime.S b/libc/arch-sh/syscalls/stime.S new file mode 100644 index 000000000..687cdff3e --- /dev/null +++ b/libc/arch-sh/syscalls/stime.S @@ -0,0 +1,32 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type stime, @function + .globl stime + .align 4 + +stime: + + /* invoke trap */ + mov.l 0f, r3 /* trap num */ + trapa #(1 + 0x10) + + /* check return value */ + cmp/pz r0 + bt __NR_stime_end + + /* keep error number */ + sts.l pr, @-r15 + mov.l 1f, r1 + jsr @r1 + mov r0, r4 + lds.l @r15+, pr + +__NR_stime_end: + rts + nop + + .align 2 +0: .long __NR_stime +1: .long __set_syscall_errno diff --git a/libc/arch-sh/syscalls/swapoff.S b/libc/arch-sh/syscalls/swapoff.S new file mode 100644 index 000000000..be980c689 --- /dev/null +++ b/libc/arch-sh/syscalls/swapoff.S @@ -0,0 +1,32 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type swapoff, @function + .globl swapoff + .align 4 + +swapoff: + + /* invoke trap */ + mov.l 0f, r3 /* trap num */ + trapa #(1 + 0x10) + + /* check return value */ + cmp/pz r0 + bt __NR_swapoff_end + + /* keep error number */ + sts.l pr, @-r15 + mov.l 1f, r1 + jsr @r1 + mov r0, r4 + lds.l @r15+, pr + +__NR_swapoff_end: + rts + nop + + .align 2 +0: .long __NR_swapoff +1: .long __set_syscall_errno diff --git a/libc/arch-sh/syscalls/swapon.S b/libc/arch-sh/syscalls/swapon.S new file mode 100644 index 000000000..7c2e1fcf4 --- /dev/null +++ b/libc/arch-sh/syscalls/swapon.S @@ -0,0 +1,32 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type swapon, @function + .globl swapon + .align 4 + +swapon: + + /* invoke trap */ + mov.l 0f, r3 /* trap num */ + trapa #(2 + 0x10) + + /* check return value */ + cmp/pz r0 + bt __NR_swapon_end + + /* keep error number */ + sts.l pr, @-r15 + mov.l 1f, r1 + jsr @r1 + mov r0, r4 + lds.l @r15+, pr + +__NR_swapon_end: + rts + nop + + .align 2 +0: .long __NR_swapon +1: .long __set_syscall_errno diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk index 420a91eb0..5a8daf94d 100644 --- a/libc/arch-x86/syscalls.mk +++ b/libc/arch-x86/syscalls.mk @@ -126,6 +126,7 @@ syscall_src += arch-x86/syscalls/__timer_gettime.S syscall_src += arch-x86/syscalls/__timer_getoverrun.S syscall_src += arch-x86/syscalls/__timer_delete.S syscall_src += arch-x86/syscalls/utimes.S +syscall_src += arch-x86/syscalls/adjtimex.S syscall_src += arch-x86/syscalls/sigaction.S syscall_src += arch-x86/syscalls/sigprocmask.S syscall_src += arch-x86/syscalls/__sigsuspend.S @@ -176,3 +177,7 @@ syscall_src += arch-x86/syscalls/inotify_add_watch.S syscall_src += arch-x86/syscalls/inotify_rm_watch.S syscall_src += arch-x86/syscalls/poll.S syscall_src += arch-x86/syscalls/eventfd.S +syscall_src += arch-x86/syscalls/stime.S +syscall_src += arch-x86/syscalls/swapon.S +syscall_src += arch-x86/syscalls/swapoff.S +syscall_src += arch-x86/syscalls/getsid.S diff --git a/libc/arch-x86/syscalls/adjtimex.S b/libc/arch-x86/syscalls/adjtimex.S new file mode 100644 index 000000000..b21260651 --- /dev/null +++ b/libc/arch-x86/syscalls/adjtimex.S @@ -0,0 +1,23 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type adjtimex, @function + .globl adjtimex + .align 4 + +adjtimex: + pushl %ebx + mov 8(%esp), %ebx + movl $__NR_adjtimex, %eax + int $0x80 + cmpl $-129, %eax + jb 1f + negl %eax + pushl %eax + call __set_errno + addl $4, %esp + orl $-1, %eax +1: + popl %ebx + ret diff --git a/libc/arch-x86/syscalls/getsid.S b/libc/arch-x86/syscalls/getsid.S new file mode 100644 index 000000000..7046b9a01 --- /dev/null +++ b/libc/arch-x86/syscalls/getsid.S @@ -0,0 +1,23 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type getsid, @function + .globl getsid + .align 4 + +getsid: + pushl %ebx + mov 8(%esp), %ebx + movl $__NR_getsid, %eax + int $0x80 + cmpl $-129, %eax + jb 1f + negl %eax + pushl %eax + call __set_errno + addl $4, %esp + orl $-1, %eax +1: + popl %ebx + ret diff --git a/libc/arch-x86/syscalls/stime.S b/libc/arch-x86/syscalls/stime.S new file mode 100644 index 000000000..609aed33f --- /dev/null +++ b/libc/arch-x86/syscalls/stime.S @@ -0,0 +1,23 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type stime, @function + .globl stime + .align 4 + +stime: + pushl %ebx + mov 8(%esp), %ebx + movl $__NR_stime, %eax + int $0x80 + cmpl $-129, %eax + jb 1f + negl %eax + pushl %eax + call __set_errno + addl $4, %esp + orl $-1, %eax +1: + popl %ebx + ret diff --git a/libc/arch-x86/syscalls/swapoff.S b/libc/arch-x86/syscalls/swapoff.S new file mode 100644 index 000000000..6782c3c56 --- /dev/null +++ b/libc/arch-x86/syscalls/swapoff.S @@ -0,0 +1,23 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type swapoff, @function + .globl swapoff + .align 4 + +swapoff: + pushl %ebx + mov 8(%esp), %ebx + movl $__NR_swapoff, %eax + int $0x80 + cmpl $-129, %eax + jb 1f + negl %eax + pushl %eax + call __set_errno + addl $4, %esp + orl $-1, %eax +1: + popl %ebx + ret diff --git a/libc/arch-x86/syscalls/swapon.S b/libc/arch-x86/syscalls/swapon.S new file mode 100644 index 000000000..f33af2886 --- /dev/null +++ b/libc/arch-x86/syscalls/swapon.S @@ -0,0 +1,26 @@ +/* autogenerated by gensyscalls.py */ +#include <sys/linux-syscalls.h> + + .text + .type swapon, @function + .globl swapon + .align 4 + +swapon: + pushl %ebx + pushl %ecx + mov 12(%esp), %ebx + mov 16(%esp), %ecx + movl $__NR_swapon, %eax + int $0x80 + cmpl $-129, %eax + jb 1f + negl %eax + pushl %eax + call __set_errno + addl $4, %esp + orl $-1, %eax +1: + popl %ecx + popl %ebx + ret diff --git a/libc/bionic/dlmalloc.c b/libc/bionic/dlmalloc.c index 19fbb7521..d30ec30ef 100644 --- a/libc/bionic/dlmalloc.c +++ b/libc/bionic/dlmalloc.c @@ -465,6 +465,13 @@ DEFAULT_MMAP_THRESHOLD default: 256K */ +#ifdef ANDROID +#define USE_BUILTIN_FFS 1 +#ifdef __arm__ +#include <machine/cpu-features.h> +#endif +#endif /* ANDROID */ + #ifndef WIN32 #ifdef _WIN32 #define WIN32 1 @@ -2394,6 +2401,17 @@ static size_t traverse_and_check(mstate m); } #else /* GNUC */ +#if defined(__ARM_ARCH__) && __ARM_ARCH__ >= 7 +#define compute_bit2idx(X, I) \ +{ \ + unsigned int J; \ + __asm__ ("rbit %0, %1\n" \ + "clz %0, %0" \ + : "=r" (J) : "r" (X)); \ + I = (bindex_t) J; \ +} + +#else /* ARM_ARCH */ #if USE_BUILTIN_FFS #define compute_bit2idx(X, I) I = ffs(X)-1 @@ -2409,6 +2427,7 @@ static size_t traverse_and_check(mstate m); N += K = Y >> (1-0) & 1; Y >>= K;\ I = (bindex_t)(N + Y);\ } +#endif /* ARM_ARCH */ #endif /* USE_BUILTIN_FFS */ #endif /* GNUC */ diff --git a/libc/bionic/malloc_debug_common.c b/libc/bionic/malloc_debug_common.c index f05576c4f..a7bd8fc85 100644 --- a/libc/bionic/malloc_debug_common.c +++ b/libc/bionic/malloc_debug_common.c @@ -84,7 +84,6 @@ static int hash_entry_compare(const void* arg1, const void* arg2) // // This is used for sorting, not determination of equality, so we don't // need to compare the bit flags. - int result; if (alloc1 > alloc2) { result = -1; } else if (alloc1 < alloc2) { diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c index 180914e2f..6b0183074 100644 --- a/libc/bionic/pthread.c +++ b/libc/bionic/pthread.c @@ -378,6 +378,13 @@ int pthread_create(pthread_t *thread_out, pthread_attr_t const * attr, return 0; } +#ifdef NASTY_PTHREAD_CREATE_HACK +int _debug_pthread_create(void *debug0, void *debug1, pthread_t *thread, + const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) +{ + return pthread_create(thread, attr, start_routine, arg); +} +#endif int pthread_attr_init(pthread_attr_t * attr) { diff --git a/libc/include/errno.h b/libc/include/errno.h index 2b2685af4..cae0e3b78 100644 --- a/libc/include/errno.h +++ b/libc/include/errno.h @@ -45,6 +45,7 @@ __BEGIN_DECLS extern int __set_errno(int error); /* internal function returning the address of the thread-specific errno */ +__attribute__((const)) extern volatile int* __errno(void); /* a macro expanding to the errno l-value */ diff --git a/libc/include/mntent.h b/libc/include/mntent.h index b83da1f2f..d45e69448 100644 --- a/libc/include/mntent.h +++ b/libc/include/mntent.h @@ -28,6 +28,7 @@ #ifndef _MNTENT_H_ #define _MNTENT_H_ +#include <sys/cdefs.h> #include <stdio.h> #define MNTTYPE_IGNORE "ignore" diff --git a/libc/include/pthread.h b/libc/include/pthread.h index 99e747aa5..6407a1991 100644 --- a/libc/include/pthread.h +++ b/libc/include/pthread.h @@ -138,10 +138,15 @@ int pthread_getattr_np(pthread_t thid, pthread_attr_t * attr); int pthread_create(pthread_t *thread, pthread_attr_t const * attr, void *(*start_routine)(void *), void * arg); +#ifdef NASTY_PTHREAD_CREATE_HACK +int _debug_pthread_create(void *debug0, void *debug1, pthread_t *thread, + const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); +#endif void pthread_exit(void * retval); int pthread_join(pthread_t thid, void ** ret_val); int pthread_detach(pthread_t thid); +__attribute__((const)) pthread_t pthread_self(void); int pthread_equal(pthread_t one, pthread_t two); diff --git a/libc/include/resolv.h b/libc/include/resolv.h index 4247d68b7..7257d343d 100644 --- a/libc/include/resolv.h +++ b/libc/include/resolv.h @@ -34,12 +34,13 @@ #include <sys/socket.h> #include <stdio.h> #include <arpa/nameser.h> +#include <netinet/in.h> __BEGIN_DECLS struct res_state; -extern struct __res_state *__res_state(void); +extern struct __res_state *__res_state(void) __attribute__((const)); #define _res (*__res_state()) /* Base-64 functions - because some code expects it there */ @@ -49,6 +50,21 @@ extern struct __res_state *__res_state(void); extern int b64_ntop(u_char const *, size_t, char *, size_t); extern int b64_pton(char const *, u_char *, size_t); +/* Set name of default interface */ +extern void _resolv_set_default_iface(const char* ifname); + +/* set name servers for an interface */ +extern void _resolv_set_nameservers_for_iface(const char* ifname, char** servers, int numservers); + +/* tell resolver of the address of an interface */ +extern void _resolv_set_addr_of_iface(const char* ifname, struct in_addr* addr); + +/* flush the cache associated with the default interface */ +extern void _resolv_flush_cache_for_default_iface(); + +/* flush the cache associated with a certain interface */ +extern void _resolv_flush_cache_for_iface(const char* ifname); + __END_DECLS #endif /* _RESOLV_H_ */ diff --git a/libc/include/sys/_system_properties.h b/libc/include/sys/_system_properties.h index 42a7f6c0f..95652c322 100644 --- a/libc/include/sys/_system_properties.h +++ b/libc/include/sys/_system_properties.h @@ -74,7 +74,8 @@ struct prop_msg }; #define PROP_MSG_SETPROP 1 - +#define PROP_MSG_SETPROP_SYNC 2 + /* ** Rules: ** diff --git a/libc/include/sys/linux-syscalls.h b/libc/include/sys/linux-syscalls.h index 9702a7a73..cb214fa30 100644 --- a/libc/include/sys/linux-syscalls.h +++ b/libc/include/sys/linux-syscalls.h @@ -105,6 +105,7 @@ #define __NR_nanosleep (__NR_SYSCALL_BASE + 162) #define __NR_getitimer (__NR_SYSCALL_BASE + 105) #define __NR_setitimer (__NR_SYSCALL_BASE + 104) +#define __NR_adjtimex (__NR_SYSCALL_BASE + 124) #define __NR_sigaction (__NR_SYSCALL_BASE + 67) #define __NR_sigprocmask (__NR_SYSCALL_BASE + 126) #define __NR_sigsuspend (__NR_SYSCALL_BASE + 72) @@ -131,6 +132,10 @@ #define __NR_sysinfo (__NR_SYSCALL_BASE + 116) #define __NR_futex (__NR_SYSCALL_BASE + 240) #define __NR_poll (__NR_SYSCALL_BASE + 168) +#define __NR_stime (__NR_SYSCALL_BASE + 25) +#define __NR_swapon (__NR_SYSCALL_BASE + 87) +#define __NR_swapoff (__NR_SYSCALL_BASE + 115) +#define __NR_getsid (__NR_SYSCALL_BASE + 147) #ifdef __arm__ #define __NR_exit_group (__NR_SYSCALL_BASE + 248) diff --git a/libc/include/sys/linux-unistd.h b/libc/include/sys/linux-unistd.h index 23853dac1..2c11db39e 100644 --- a/libc/include/sys/linux-unistd.h +++ b/libc/include/sys/linux-unistd.h @@ -137,6 +137,7 @@ int __timer_gettime (timer_t, struct itimerspec*); int __timer_getoverrun (timer_t); int __timer_delete (timer_t); int utimes (const char*, const struct timeval tvp[2]); +int adjtimex (struct timex *); int sigaction (int, const struct sigaction *, struct sigaction *); int sigprocmask (int, const sigset_t *, sigset_t *); int __sigsuspend (int unused1, int unused2, unsigned mask); @@ -205,6 +206,10 @@ int poll (struct pollfd *, unsigned int, long); int eventfd (unsigned int, int); int __set_tls (void*); int cacheflush (long start, long end, long flags); +int stime (time_t *); +int swapon (const char *, int); +int swapoff (const char *); +pid_t getsid (pid_t pid); #ifdef __cplusplus } #endif diff --git a/libc/kernel/common/linux/akm8975.h b/libc/kernel/common/linux/akm8975.h new file mode 100644 index 000000000..3e83c8d2f --- /dev/null +++ b/libc/kernel/common/linux/akm8975.h @@ -0,0 +1,92 @@ +/* + * Definitions for akm8975 compass chip. + */ +#ifndef AKM8975_H +#define AKM8975_H + +#include <linux/ioctl.h> + +#define AKM8975_I2C_NAME "akm8975" + +/* Compass device dependent definition */ + +/*! \name AK8975 register address +\anchor AK8975_REG +Defines a register address of the AK8975.*/ +#define AK8975_REG_WIA 0x00 +#define AK8975_REG_INFO 0x01 +#define AK8975_REG_ST1 0x02 +#define AK8975_REG_HXL 0x03 +#define AK8975_REG_HXH 0x04 +#define AK8975_REG_HYL 0x05 +#define AK8975_REG_HYH 0x06 +#define AK8975_REG_HZL 0x07 +#define AK8975_REG_HZH 0x08 +#define AK8975_REG_ST2 0x09 +#define AK8975_REG_CNTL 0x0A +#define AK8975_REG_RSV 0x0B +#define AK8975_REG_ASTC 0x0C +#define AK8975_REG_TS1 0x0D +#define AK8975_REG_TS2 0x0E +#define AK8975_REG_I2CDIS 0x0F + + +/*! \name AK8975 fuse-rom address +\anchor AK8975_FUSE +Defines a read-only address of the fuse ROM of the AK8975.*/ + +#define AK8975_FUSE_ASAX 0x10 +#define AK8975_FUSE_ASAY 0x11 +#define AK8975_FUSE_ASAZ 0x12 + +/*! \name AK8975 register value +\anchor AK8975_CNTL +Defines a value to be set in the Control Registers (\c CNTL) of AK8975. */ + +#define AK8975_CNTL_SNG_MEASURE 0x01 +#define AK8975_CNTL_CONT_MEASURE 0x02 +#define AK8975_CNTL_TRIG_MEASURE 0x04 +#define AK8975_CNTL_SELF_TEST 0x08 +#define AK8975_CNTL_FUSE_ACCESS 0x0F +#define AK8975_CNTL_POWER_DOWN 0x00 + +#define RBUFF_SIZE_8975 8 /* Rx buffer size */ + +#define AKMIO 0xA1 + +/* IOCTLs for AKM library */ +#define ECS_IOCTL_WRITE _IOW(AKMIO, 0x01, char[5]) +#define ECS_IOCTL_READ _IOWR(AKMIO, 0x02, char[5]) +#define ECS_IOCTL_SET_MODE _IOW(AKMIO, 0x0F, short) +#define ECS_IOCTL_GETDATA _IOR(AKMIO, 0x05, char[RBUFF_SIZE_8975+1]) +#define ECS_IOCTL_SET_YPR _IOW(AKMIO, 0x06, short[12]) +#define ECS_IOCTL_GET_OPEN_STATUS _IOR(AKMIO, 0x07, int) +#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(AKMIO, 0x08, int) +#define ECS_IOCTL_GET_DELAY _IOR(AKMIO, 0x30, short) +#define ECS_IOCTL_GET_MATRIX _IOR(AKMIO, 0x0E, short [4][3][3]) + +/* IOCTLs for APPs */ +#define ECS_IOCTL_APP_SET_MODE _IOW(AKMIO, 0x10, short) +#define ECS_IOCTL_APP_SET_MFLAG _IOW(AKMIO, 0x11, short) +#define ECS_IOCTL_APP_GET_MFLAG _IOW(AKMIO, 0x12, short) +#define ECS_IOCTL_APP_SET_AFLAG _IOW(AKMIO, 0x13, short) +#define ECS_IOCTL_APP_GET_AFLAG _IOR(AKMIO, 0x14, short) +#define ECS_IOCTL_APP_SET_TFLAG _IOR(AKMIO, 0x15, short) +#define ECS_IOCTL_APP_GET_TFLAG _IOR(AKMIO, 0x16, short) +#define ECS_IOCTL_APP_RESET_PEDOMETER _IO(AKMIO, 0x17) +#define ECS_IOCTL_APP_SET_DELAY _IOW(AKMIO, 0x18, short) +#define ECS_IOCTL_APP_GET_DELAY ECS_IOCTL_GET_DELAY + +/* Set raw magnetic vector flag */ +#define ECS_IOCTL_APP_SET_MVFLAG _IOW(AKMIO, 0x19, short) + +/* Get raw magnetic vector flag */ +#define ECS_IOCTL_APP_GET_MVFLAG _IOR(AKMIO, 0x1A, short) + +struct akm8975_platform_data { + short layouts[4][3][3]; + short irq_trigger; +}; + +#endif + diff --git a/libc/kernel/common/linux/android_pmem.h b/libc/kernel/common/linux/android_pmem.h index be0b34221..ba8522774 100644 --- a/libc/kernel/common/linux/android_pmem.h +++ b/libc/kernel/common/linux/android_pmem.h @@ -12,6 +12,15 @@ #ifndef _ANDROID_PMEM_H_ #define _ANDROID_PMEM_H_ +#include <linux/fs.h> + +#define PMEM_KERNEL_TEST_MAGIC 0xc0 +#define PMEM_KERNEL_TEST_NOMINAL_TEST_IOCTL _IO(PMEM_KERNEL_TEST_MAGIC, 1) +#define PMEM_KERNEL_TEST_ADVERSARIAL_TEST_IOCTL _IO(PMEM_KERNEL_TEST_MAGIC, 2) +#define PMEM_KERNEL_TEST_HUGE_ALLOCATION_TEST_IOCTL _IO(PMEM_KERNEL_TEST_MAGIC, 3) +#define PMEM_KERNEL_TEST_FREE_UNALLOCATED_TEST_IOCTL _IO(PMEM_KERNEL_TEST_MAGIC, 4) +#define PMEM_KERNEL_TEST_LARGE_REGION_NUMBER_TEST_IOCTL _IO(PMEM_KERNEL_TEST_MAGIC, 5) + #define PMEM_IOCTL_MAGIC 'p' #define PMEM_GET_PHYS _IOW(PMEM_IOCTL_MAGIC, 1, unsigned int) #define PMEM_MAP _IOW(PMEM_IOCTL_MAGIC, 2, unsigned int) @@ -23,27 +32,34 @@ #define PMEM_CONNECT _IOW(PMEM_IOCTL_MAGIC, 6, unsigned int) #define PMEM_GET_TOTAL_SIZE _IOW(PMEM_IOCTL_MAGIC, 7, unsigned int) -#define PMEM_CACHE_FLUSH _IOW(PMEM_IOCTL_MAGIC, 8, unsigned int) -struct android_pmem_platform_data -{ - const char* name; +#define PMEM_CACHE_FLUSH _IOW(PMEM_IOCTL_MAGIC, 8, unsigned int) - unsigned long start; +#define PMEM_CLEAN_INV_CACHES _IOW(PMEM_IOCTL_MAGIC, 11, unsigned int) +#define PMEM_CLEAN_CACHES _IOW(PMEM_IOCTL_MAGIC, 12, unsigned int) +#define PMEM_INV_CACHES _IOW(PMEM_IOCTL_MAGIC, 13, unsigned int) - unsigned long size; - - unsigned no_allocator; +#define PMEM_GET_FREE_SPACE _IOW(PMEM_IOCTL_MAGIC, 14, unsigned int) +#define PMEM_ALLOCATE_ALIGNED _IOW(PMEM_IOCTL_MAGIC, 15, unsigned int) +struct pmem_region { + unsigned long offset; + unsigned long len; +}; - unsigned cached; +struct pmem_addr { + unsigned long vaddr; + unsigned long offset; + unsigned long length; +}; - unsigned buffered; +struct pmem_freespace { + unsigned long total; + unsigned long largest; }; -struct pmem_region { - unsigned long offset; - unsigned long len; +struct pmem_allocation { + unsigned long size; + unsigned int align; }; #endif - diff --git a/libc/kernel/common/linux/msm_audio_7X30.h b/libc/kernel/common/linux/msm_audio_7X30.h new file mode 100644 index 000000000..6185a6cec --- /dev/null +++ b/libc/kernel/common/linux/msm_audio_7X30.h @@ -0,0 +1,329 @@ +/* include/linux/msm_audio.h + * + * Copyright (C) 2008 Google, Inc. + * Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __LINUX_MSM_AUDIO_H +#define __LINUX_MSM_AUDIO_H + +#include <linux/types.h> +#include <linux/ioctl.h> +#include <asm/sizes.h> + +/* PCM Audio */ + +#define AUDIO_IOCTL_MAGIC 'a' + +#define AUDIO_START _IOW(AUDIO_IOCTL_MAGIC, 0, unsigned) +#define AUDIO_STOP _IOW(AUDIO_IOCTL_MAGIC, 1, unsigned) +#define AUDIO_FLUSH _IOW(AUDIO_IOCTL_MAGIC, 2, unsigned) +#define AUDIO_GET_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 3, unsigned) +#define AUDIO_SET_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 4, unsigned) +#define AUDIO_GET_STATS _IOR(AUDIO_IOCTL_MAGIC, 5, unsigned) +#define AUDIO_ENABLE_AUDPP _IOW(AUDIO_IOCTL_MAGIC, 6, unsigned) +#define AUDIO_SET_ADRC _IOW(AUDIO_IOCTL_MAGIC, 7, unsigned) +#define AUDIO_SET_EQ _IOW(AUDIO_IOCTL_MAGIC, 8, unsigned) +#define AUDIO_SET_RX_IIR _IOW(AUDIO_IOCTL_MAGIC, 9, unsigned) +#define AUDIO_SET_VOLUME _IOW(AUDIO_IOCTL_MAGIC, 10, unsigned) +#define AUDIO_PAUSE _IOW(AUDIO_IOCTL_MAGIC, 11, unsigned) +#define AUDIO_PLAY_DTMF _IOW(AUDIO_IOCTL_MAGIC, 12, unsigned) +#define AUDIO_GET_EVENT _IOR(AUDIO_IOCTL_MAGIC, 13, unsigned) +#define AUDIO_ABORT_GET_EVENT _IOW(AUDIO_IOCTL_MAGIC, 14, unsigned) +#define AUDIO_REGISTER_PMEM _IOW(AUDIO_IOCTL_MAGIC, 15, unsigned) +#define AUDIO_DEREGISTER_PMEM _IOW(AUDIO_IOCTL_MAGIC, 16, unsigned) +#define AUDIO_ASYNC_WRITE _IOW(AUDIO_IOCTL_MAGIC, 17, unsigned) +#define AUDIO_ASYNC_READ _IOW(AUDIO_IOCTL_MAGIC, 18, unsigned) +#define AUDIO_SET_INCALL _IOW(AUDIO_IOCTL_MAGIC, 19, struct msm_voicerec_mode) +#define AUDIO_GET_NUM_SND_DEVICE _IOR(AUDIO_IOCTL_MAGIC, 20, unsigned) +#define AUDIO_GET_SND_DEVICES _IOWR(AUDIO_IOCTL_MAGIC, 21, \ + struct msm_snd_device_list) +#define AUDIO_ENABLE_SND_DEVICE _IOW(AUDIO_IOCTL_MAGIC, 22, unsigned) +#define AUDIO_DISABLE_SND_DEVICE _IOW(AUDIO_IOCTL_MAGIC, 23, unsigned) +#define AUDIO_ROUTE_STREAM _IOW(AUDIO_IOCTL_MAGIC, 24, \ + struct msm_audio_route_config) +#define AUDIO_GET_PCM_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 30, unsigned) +#define AUDIO_SET_PCM_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 31, unsigned) +#define AUDIO_SWITCH_DEVICE _IOW(AUDIO_IOCTL_MAGIC, 32, unsigned) +#define AUDIO_SET_MUTE _IOW(AUDIO_IOCTL_MAGIC, 33, unsigned) +#define AUDIO_UPDATE_ACDB _IOW(AUDIO_IOCTL_MAGIC, 34, unsigned) +#define AUDIO_START_VOICE _IOW(AUDIO_IOCTL_MAGIC, 35, unsigned) +#define AUDIO_STOP_VOICE _IOW(AUDIO_IOCTL_MAGIC, 36, unsigned) +#define AUDIO_REINIT_ACDB _IOW(AUDIO_IOCTL_MAGIC, 39, unsigned) +#define AUDIO_OUTPORT_FLUSH _IOW(AUDIO_IOCTL_MAGIC, 40, unsigned short) +#define AUDIO_SET_ERR_THRESHOLD_VALUE _IOW(AUDIO_IOCTL_MAGIC, 41, \ + unsigned short) +#define AUDIO_GET_BITSTREAM_ERROR_INFO _IOR(AUDIO_IOCTL_MAGIC, 42, \ + struct msm_audio_bitstream_error_info) +/* Qualcomm extensions */ +#define AUDIO_SET_STREAM_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 80, \ + struct msm_audio_stream_config) +#define AUDIO_GET_STREAM_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 81, \ + struct msm_audio_stream_config) +#define AUDIO_GET_SESSION_ID _IOR(AUDIO_IOCTL_MAGIC, 82, unsigned short) +#define AUDIO_GET_STREAM_INFO _IOR(AUDIO_IOCTL_MAGIC, 83, \ + struct msm_audio_bitstream_info) +#define AUDIO_SET_PAN _IOW(AUDIO_IOCTL_MAGIC, 84, unsigned) +#define AUDIO_SET_QCONCERT_PLUS _IOW(AUDIO_IOCTL_MAGIC, 85, unsigned) +#define AUDIO_SET_MBADRC _IOW(AUDIO_IOCTL_MAGIC, 86, unsigned) +#define AUDIO_SET_VOLUME_PATH _IOW(AUDIO_IOCTL_MAGIC, 87, \ + struct msm_vol_info) +#define AUDIO_SET_MAX_VOL_ALL _IOW(AUDIO_IOCTL_MAGIC, 88, unsigned) +#define AUDIO_ENABLE_AUDPRE _IOW(AUDIO_IOCTL_MAGIC, 89, unsigned) +#define AUDIO_SET_AGC _IOW(AUDIO_IOCTL_MAGIC, 90, unsigned) +#define AUDIO_SET_NS _IOW(AUDIO_IOCTL_MAGIC, 91, unsigned) +#define AUDIO_SET_TX_IIR _IOW(AUDIO_IOCTL_MAGIC, 92, unsigned) + +#define AUDIO_MAX_COMMON_IOCTL_NUM 100 + + +#define HANDSET_MIC 0x01 +#define HANDSET_SPKR 0x02 +#define HEADSET_MIC 0x03 +#define HEADSET_SPKR_MONO 0x04 +#define HEADSET_SPKR_STEREO 0x05 +#define SPKR_PHONE_MIC 0x06 +#define SPKR_PHONE_MONO 0x07 +#define SPKR_PHONE_STEREO 0x08 +#define BT_SCO_MIC 0x09 +#define BT_SCO_SPKR 0x0A +#define BT_A2DP_SPKR 0x0B +#define TTY_HEADSET_MIC 0x0C +#define TTY_HEADSET_SPKR 0x0D + +/* Default devices are not supported in a */ +/* device switching context. Only supported */ +/* for stream devices. */ +/* DO NOT USE */ +#define DEFAULT_TX 0x0E +#define DEFAULT_RX 0x0F + +#define BT_A2DP_TX 0x10 + +#define HEADSET_MONO_PLUS_SPKR_MONO_RX 0x11 +#define HEADSET_MONO_PLUS_SPKR_STEREO_RX 0x12 +#define HEADSET_STEREO_PLUS_SPKR_MONO_RX 0x13 +#define HEADSET_STEREO_PLUS_SPKR_STEREO_RX 0x14 + +#define I2S_RX 0x20 +#define I2S_TX 0x21 + +#define ADRC_ENABLE 0x0001 +#define EQ_ENABLE 0x0002 +#define IIR_ENABLE 0x0004 +#define QCONCERT_PLUS_ENABLE 0x0008 +#define MBADRC_ENABLE 0x0010 + +#define AGC_ENABLE 0x0001 +#define NS_ENABLE 0x0002 +#define TX_IIR_ENABLE 0x0004 + +#define VOC_REC_UPLINK 0x00 +#define VOC_REC_DOWNLINK 0x01 +#define VOC_REC_BOTH 0x02 + +struct msm_audio_config { + uint32_t buffer_size; + uint32_t buffer_count; + uint32_t channel_count; + uint32_t sample_rate; + uint32_t type; + uint32_t meta_field; + uint32_t bits; + uint32_t unused[3]; +}; + +struct msm_audio_stream_config { + uint32_t buffer_size; + uint32_t buffer_count; +}; + +struct msm_audio_stats { + uint32_t byte_count; + uint32_t sample_count; + uint32_t unused[2]; +}; + +struct msm_audio_pmem_info { + int fd; + void *vaddr; +}; + +struct msm_audio_aio_buf { + void *buf_addr; + uint32_t buf_len; + uint32_t data_len; + void *private_data; + unsigned short mfield_sz; /*only useful for data has meta field */ +}; + +/* Audio routing */ + +#define SND_IOCTL_MAGIC 's' + +#define SND_MUTE_UNMUTED 0 +#define SND_MUTE_MUTED 1 + +struct msm_mute_info { + uint32_t mute; + uint32_t path; +}; + +struct msm_vol_info { + uint32_t vol; + uint32_t path; +}; + +struct msm_voicerec_mode { + uint32_t rec_mode; +}; + +struct msm_snd_device_config { + uint32_t device; + uint32_t ear_mute; + uint32_t mic_mute; +}; + +#define SND_SET_DEVICE _IOW(SND_IOCTL_MAGIC, 2, struct msm_device_config *) + +#define SND_METHOD_VOICE 0 + +struct msm_snd_volume_config { + uint32_t device; + uint32_t method; + uint32_t volume; +}; + +#define SND_SET_VOLUME _IOW(SND_IOCTL_MAGIC, 3, struct msm_snd_volume_config *) + +/* Returns the number of SND endpoints supported. */ + +#define SND_GET_NUM_ENDPOINTS _IOR(SND_IOCTL_MAGIC, 4, unsigned *) + +struct msm_snd_endpoint { + int id; /* input and output */ + char name[64]; /* output only */ +}; + +/* Takes an index between 0 and one less than the number returned by + * SND_GET_NUM_ENDPOINTS, and returns the SND index and name of a + * SND endpoint. On input, the .id field contains the number of the + * endpoint, and on exit it contains the SND index, while .name contains + * the description of the endpoint. + */ + +#define SND_GET_ENDPOINT _IOWR(SND_IOCTL_MAGIC, 5, struct msm_snd_endpoint *) + + +#define SND_AVC_CTL _IOW(SND_IOCTL_MAGIC, 6, unsigned *) +#define SND_AGC_CTL _IOW(SND_IOCTL_MAGIC, 7, unsigned *) + +struct msm_audio_pcm_config { + uint32_t pcm_feedback; /* 0 - disable > 0 - enable */ + uint32_t buffer_count; /* Number of buffers to allocate */ + uint32_t buffer_size; /* Size of buffer for capturing of + PCM samples */ +}; + +#define AUDIO_EVENT_SUSPEND 0 +#define AUDIO_EVENT_RESUME 1 +#define AUDIO_EVENT_WRITE_DONE 2 +#define AUDIO_EVENT_READ_DONE 3 +#define AUDIO_EVENT_STREAM_INFO 4 +#define AUDIO_EVENT_BITSTREAM_ERROR_INFO 5 + +#define AUDIO_CODEC_TYPE_MP3 0 +#define AUDIO_CODEC_TYPE_AAC 1 + +struct msm_audio_bitstream_info { + uint32_t codec_type; + uint32_t chan_info; + uint32_t sample_rate; + uint32_t bit_stream_info; + uint32_t bit_rate; + uint32_t unused[3]; +}; + +struct msm_audio_bitstream_error_info { + uint32_t dec_id; + uint32_t err_msg_indicator; + uint32_t err_type; +}; + +union msm_audio_event_payload { + struct msm_audio_aio_buf aio_buf; + struct msm_audio_bitstream_info stream_info; + struct msm_audio_bitstream_error_info error_info; + int reserved; +}; + +struct msm_audio_event { + int event_type; + int timeout_ms; + union msm_audio_event_payload event_payload; +}; + +#define MSM_SNDDEV_CAP_RX 0x1 +#define MSM_SNDDEV_CAP_TX 0x2 +#define MSM_SNDDEV_CAP_VOICE 0x4 + +struct msm_snd_device_info { + uint32_t dev_id; + uint32_t dev_cap; /* bitmask describe capability of device */ + char dev_name[64]; +}; + +struct msm_snd_device_list { + uint32_t num_dev; /* Indicate number of device info to be retrieved */ + struct msm_snd_device_info *list; +}; + +struct msm_dtmf_config { + uint16_t path; + uint16_t dtmf_hi; + uint16_t dtmf_low; + uint16_t duration; + uint16_t tx_gain; + uint16_t rx_gain; + uint16_t mixing; +}; + +#define AUDIO_ROUTE_STREAM_VOICE_RX 0 +#define AUDIO_ROUTE_STREAM_VOICE_TX 1 +#define AUDIO_ROUTE_STREAM_PLAYBACK 2 +#define AUDIO_ROUTE_STREAM_REC 3 + +struct msm_audio_route_config { + uint32_t stream_type; + uint32_t stream_id; + uint32_t dev_id; +}; + +#define AUDIO_MAX_EQ_BANDS 12 + +struct msm_audio_eq_band { + uint16_t band_idx; /* The band index, 0 .. 11 */ + uint32_t filter_type; /* Filter band type */ + uint32_t center_freq_hz; /* Filter band center frequency */ + uint32_t filter_gain; /* Filter band initial gain (dB) */ + /* Range is +12 dB to -12 dB with 1dB increments. */ + uint32_t q_factor; +} __attribute__ ((packed)); + +struct msm_audio_eq_stream_config { + uint32_t enable; /* Number of consequtive bands specified */ + uint32_t num_bands; + struct msm_audio_eq_band eq_bands[AUDIO_MAX_EQ_BANDS]; +} __attribute__ ((packed)); + +#endif diff --git a/libc/kernel/common/linux/msm_audio_aac.h b/libc/kernel/common/linux/msm_audio_aac.h new file mode 100644 index 000000000..d9d300f30 --- /dev/null +++ b/libc/kernel/common/linux/msm_audio_aac.h @@ -0,0 +1,78 @@ +/**************************************************************************** + **************************************************************************** + *** + *** This header was automatically generated from a Linux kernel header + *** of the same name, to make information necessary for userspace to + *** call into the kernel available to libc. It contains only constants, + *** structures, and macros generated from the original header, and thus, + *** contains no copyrightable information. + *** + **************************************************************************** + ****************************************************************************/ +#ifndef __MSM_AUDIO_AAC_H +#define __MSM_AUDIO_AAC_H + +#include <linux/msm_audio.h> + +#define AUDIO_SET_AAC_CONFIG _IOW(AUDIO_IOCTL_MAGIC, (AUDIO_MAX_COMMON_IOCTL_NUM+0), unsigned) +#define AUDIO_GET_AAC_CONFIG _IOR(AUDIO_IOCTL_MAGIC, (AUDIO_MAX_COMMON_IOCTL_NUM+1), unsigned) + +#define AUDIO_SET_AAC_ENC_CONFIG _IOW(AUDIO_IOCTL_MAGIC, (AUDIO_MAX_COMMON_IOCTL_NUM+3), struct msm_audio_aac_enc_config) + +#define AUDIO_GET_AAC_ENC_CONFIG _IOR(AUDIO_IOCTL_MAGIC, (AUDIO_MAX_COMMON_IOCTL_NUM+4), struct msm_audio_aac_enc_config) + +#define AUDIO_AAC_FORMAT_ADTS -1 +#define AUDIO_AAC_FORMAT_RAW 0x0000 +#define AUDIO_AAC_FORMAT_PSUEDO_RAW 0x0001 +#define AUDIO_AAC_FORMAT_LOAS 0x0002 + +#define AUDIO_AAC_OBJECT_LC 0x0002 +#define AUDIO_AAC_OBJECT_LTP 0x0004 +#define AUDIO_AAC_OBJECT_ERLC 0x0011 +#define AUDIO_AAC_OBJECT_BSAC 0x0016 + +#define AUDIO_AAC_SEC_DATA_RES_ON 0x0001 +#define AUDIO_AAC_SEC_DATA_RES_OFF 0x0000 + +#define AUDIO_AAC_SCA_DATA_RES_ON 0x0001 +#define AUDIO_AAC_SCA_DATA_RES_OFF 0x0000 + +#define AUDIO_AAC_SPEC_DATA_RES_ON 0x0001 +#define AUDIO_AAC_SPEC_DATA_RES_OFF 0x0000 + +#define AUDIO_AAC_SBR_ON_FLAG_ON 0x0001 +#define AUDIO_AAC_SBR_ON_FLAG_OFF 0x0000 + +#define AUDIO_AAC_SBR_PS_ON_FLAG_ON 0x0001 +#define AUDIO_AAC_SBR_PS_ON_FLAG_OFF 0x0000 + +#define AUDIO_AAC_DUAL_MONO_PL_PR 0 + +#define AUDIO_AAC_DUAL_MONO_SL_SR 1 + +#define AUDIO_AAC_DUAL_MONO_SL_PR 2 + +#define AUDIO_AAC_DUAL_MONO_PL_SR 3 + +struct msm_audio_aac_config { + signed short format; + unsigned short audio_object; + unsigned short ep_config; + unsigned short aac_section_data_resilience_flag; + unsigned short aac_scalefactor_data_resilience_flag; + unsigned short aac_spectral_data_resilience_flag; + unsigned short sbr_on_flag; + unsigned short sbr_ps_on_flag; + unsigned short dual_mono_mode; + unsigned short channel_configuration; +}; + +struct msm_audio_aac_enc_config { + uint32_t channels; + uint32_t sample_rate; + uint32_t bit_rate; + uint32_t stream_format; +}; + +#endif + diff --git a/libc/kernel/common/linux/msm_mdp.h b/libc/kernel/common/linux/msm_mdp.h index c35521880..e8e815af8 100644 --- a/libc/kernel/common/linux/msm_mdp.h +++ b/libc/kernel/common/linux/msm_mdp.h @@ -1,86 +1,143 @@ -/**************************************************************************** - **************************************************************************** - *** - *** This header was automatically generated from a Linux kernel header - *** of the same name, to make information necessary for userspace to - *** call into the kernel available to libc. It contains only constants, - *** structures, and macros generated from the original header, and thus, - *** contains no copyrightable information. - *** - **************************************************************************** - ****************************************************************************/ +/* include/linux/msm_mdp.h + * + * Copyright (C) 2007 Google Incorporated + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef _MSM_MDP_H_ #define _MSM_MDP_H_ #include <linux/types.h> #define MSMFB_IOCTL_MAGIC 'm' -#define MSMFB_GRP_DISP _IOW(MSMFB_IOCTL_MAGIC, 1, unsigned int) -#define MSMFB_BLIT _IOW(MSMFB_IOCTL_MAGIC, 2, unsigned int) +#define MSMFB_GRP_DISP _IOW(MSMFB_IOCTL_MAGIC, 1, unsigned int) +#define MSMFB_BLIT _IOW(MSMFB_IOCTL_MAGIC, 2, unsigned int) +#ifdef CONFIG_MSM_MDP40 +#define MSMFB_OVERLAY_SET _IOWR(MSMFB_IOCTL_MAGIC, 135, \ + struct mdp_overlay) +#define MSMFB_OVERLAY_UNSET _IOW(MSMFB_IOCTL_MAGIC, 136, unsigned int) +#define MSMFB_OVERLAY_PLAY _IOW(MSMFB_IOCTL_MAGIC, 137, \ + struct msmfb_overlay_data) +#define MSMFB_OVERLAY_GET _IOR(MSMFB_IOCTL_MAGIC, 140, \ + struct mdp_overlay) +#endif enum { - MDP_RGB_565, - MDP_XRGB_8888, - MDP_Y_CBCR_H2V2, - MDP_ARGB_8888, - MDP_RGB_888, - MDP_Y_CRCB_H2V2, - MDP_YCRYCB_H2V1, - MDP_Y_CRCB_H2V1, - MDP_Y_CBCR_H2V1, - MDP_RGBA_8888, - MDP_BGRA_8888, - MDP_RGBX_8888, - MDP_IMGTYPE_LIMIT + MDP_RGB_565, // RGB 565 planer + MDP_XRGB_8888, // RGB 888 padded + MDP_Y_CBCR_H2V2, // Y and CbCr, pseudo planer w/ Cb is in MSB + MDP_ARGB_8888, // ARGB 888 + MDP_RGB_888, // RGB 888 planer + MDP_Y_CRCB_H2V2, // Y and CrCb, pseudo planer w/ Cr is in MSB + MDP_YCRYCB_H2V1, // YCrYCb interleave + MDP_Y_CRCB_H2V1, // Y and CrCb, pseduo planer w/ Cr is in MSB + MDP_Y_CBCR_H2V1, // Y and CrCb, pseduo planer w/ Cr is in MSB + MDP_RGBA_8888, // ARGB 888 + MDP_BGRA_8888, // ARGB 888 + MDP_RGBX_8888, // RGBX 888 +#ifdef CONFIG_MSM_MDP40 + MDP_Y_CRCB_H2V2_TILE, /* Y and CrCb, pseudo planer tile */ + MDP_Y_CBCR_H2V2_TILE, /* Y and CbCr, pseudo planer tile */ +#endif + MDP_IMGTYPE_LIMIT, // Non valid image type after this enum + MDP_IMGTYPE2_START = 0x10000, + MDP_BGR_565 = MDP_IMGTYPE2_START, /* BGR 565 planer */ + MDP_FB_FORMAT, /* framebuffer format */ + MDP_IMGTYPE_LIMIT2 /* Non valid image type after this enum */ }; enum { - PMEM_IMG, - FB_IMG, + PMEM_IMG, + FB_IMG, }; +/* flag values */ #define MDP_ROT_NOP 0 #define MDP_FLIP_LR 0x1 #define MDP_FLIP_UD 0x2 #define MDP_ROT_90 0x4 #define MDP_ROT_180 (MDP_FLIP_UD|MDP_FLIP_LR) #define MDP_ROT_270 (MDP_ROT_90|MDP_FLIP_UD|MDP_FLIP_LR) +#define MDP_ROT_MASK 0x7 #define MDP_DITHER 0x8 #define MDP_BLUR 0x10 #define MDP_BLEND_FG_PREMULT 0x20000 - +#define MDP_DEINTERLACE 0x80000000 +#define MDP_SHARPENING 0x40000000 #define MDP_TRANSP_NOP 0xffffffff #define MDP_ALPHA_NOP 0xff struct mdp_rect { - uint32_t x; - uint32_t y; - uint32_t w; - uint32_t h; + uint32_t x; + uint32_t y; + uint32_t w; + uint32_t h; }; struct mdp_img { - uint32_t width; - uint32_t height; - uint32_t format; - uint32_t offset; - int memory_id; + uint32_t width; + uint32_t height; + uint32_t format; + uint32_t offset; + int memory_id; /* the file descriptor */ }; struct mdp_blit_req { - struct mdp_img src; - struct mdp_img dst; - struct mdp_rect src_rect; - struct mdp_rect dst_rect; - uint32_t alpha; - uint32_t transp_mask; - uint32_t flags; + struct mdp_img src; + struct mdp_img dst; + struct mdp_rect src_rect; + struct mdp_rect dst_rect; + uint32_t alpha; + uint32_t transp_mask; + uint32_t flags; +#ifdef CONFIG_MSM_MDP40 + int sharpening_strength; /* -127 <--> 127, default 64 */ +#endif }; struct mdp_blit_req_list { - uint32_t count; - struct mdp_blit_req req[]; + uint32_t count; + struct mdp_blit_req req[]; }; -#endif +#ifdef CONFIG_MSM_MDP40 +struct msmfb_data { + uint32_t offset; + int memory_id; + int id; +}; + +#define MSMFB_NEW_REQUEST -1 +struct msmfb_overlay_data { + uint32_t id; + struct msmfb_data data; +}; + +struct msmfb_img { + uint32_t width; + uint32_t height; + uint32_t format; +}; + +struct mdp_overlay { + struct msmfb_img src; + struct mdp_rect src_rect; + struct mdp_rect dst_rect; + uint32_t z_order; /* stage number */ + uint32_t is_fg; /* control alpha & transp */ + uint32_t alpha; + uint32_t transp_mask; + uint32_t flags; + uint32_t id; + uint32_t user_data[8]; +}; +#endif +#endif //_MSM_MDP_H_ diff --git a/libc/kernel/common/linux/msm_q6vdec.h b/libc/kernel/common/linux/msm_q6vdec.h index 0182bfbf7..c82e12ff4 100644 --- a/libc/kernel/common/linux/msm_q6vdec.h +++ b/libc/kernel/common/linux/msm_q6vdec.h @@ -26,6 +26,7 @@ #define VDEC_IOCTL_CLOSE _IO(VDEC_IOCTL_MAGIC, 8) #define VDEC_IOCTL_FREEBUFFERS _IOW(VDEC_IOCTL_MAGIC, 9, struct vdec_buf_info) #define VDEC_IOCTL_GETDECATTRIBUTES _IOR(VDEC_IOCTL_MAGIC, 10, struct vdec_dec_attributes) +#define VDEC_IOCTL_GETVERSION _IOR(VDEC_IOCTL_MAGIC, 11, struct vdec_version) enum { VDEC_FRAME_DECODE_OK, @@ -99,7 +100,7 @@ struct vdec_config { u32 h264_nal_len_size; u32 postproc_flag; u32 fruc_enable; - u32 reserved; + u32 color_format; }; struct vdec_vc1_panscan_regions { @@ -208,5 +209,10 @@ struct vdec_dec_attributes { struct vdec_buf_desc dec_req2; }; +struct vdec_version { + u32 major; + u32 minor; +}; + #endif diff --git a/libc/kernel/common/linux/msm_rotator.h b/libc/kernel/common/linux/msm_rotator.h new file mode 100755 index 000000000..8246c89c5 --- /dev/null +++ b/libc/kernel/common/linux/msm_rotator.h @@ -0,0 +1,61 @@ +/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Code Aurora nor + * the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __MSM_ROTATOR_H__ + +#include <linux/types.h> +#include <linux/msm_mdp.h> + +#define MSM_ROTATOR_IOCTL_MAGIC 'R' + +#define MSM_ROTATOR_IOCTL_START \ + _IOWR(MSM_ROTATOR_IOCTL_MAGIC, 1, struct msm_rotator_img_info) +#define MSM_ROTATOR_IOCTL_ROTATE \ + _IOW(MSM_ROTATOR_IOCTL_MAGIC, 2, struct msm_rotator_data_info) +#define MSM_ROTATOR_IOCTL_FINISH \ + _IOW(MSM_ROTATOR_IOCTL_MAGIC, 3, int) + +struct msm_rotator_img_info { + unsigned int session_id; + struct msmfb_img src; + struct msmfb_img dst; + struct mdp_rect src_rect; + unsigned int dst_x; + unsigned int dst_y; + unsigned char rotations; + int enable; +}; + +struct msm_rotator_data_info { + int session_id; + struct msmfb_data src; + struct msmfb_data dst; +}; + +#endif + diff --git a/libc/kernel/common/linux/msm_vidc_dec.h b/libc/kernel/common/linux/msm_vidc_dec.h index 20837a739..47ea37f97 100644 --- a/libc/kernel/common/linux/msm_vidc_dec.h +++ b/libc/kernel/common/linux/msm_vidc_dec.h @@ -72,10 +72,12 @@ #define VDEC_BUFFERFLAG_EXTRADATA 0x00000040 #define VDEC_BUFFERFLAG_CODECCONFIG 0x00000080 -#define VDEC_EXTRADATA_QP 0x00000001 -#define VDEC_EXTRADATA_SEI 0x00000002 -#define VDEC_EXTRADATA_VUI 0x00000004 -#define VDEC_EXTRADATA_MB_ERROR_MAP 0x00000008 +#define VDEC_EXTRADATA_NONE 0x001 +#define VDEC_EXTRADATA_QP 0x004 +#define VDEC_EXTRADATA_MB_ERROR_MAP 0x008 +#define VDEC_EXTRADATA_SEI 0x010 +#define VDEC_EXTRADATA_VUI 0x020 +#define VDEC_EXTRADATA_VC1 0x040 #define VDEC_CMDBASE 0x800 #define VDEC_CMD_SET_INTF_VERSION (VDEC_CMDBASE) @@ -83,8 +85,8 @@ #define VDEC_IOCTL_MAGIC 'v' struct vdec_ioctl_msg { - void *inputparam; - void *outputparam; + void __user *in; + void __user *out; }; #define VDEC_IOCTL_GET_PROFILE_LEVEL_SUPPORTED _IOWR(VDEC_IOCTL_MAGIC, 0, struct vdec_ioctl_msg) @@ -134,6 +136,16 @@ struct vdec_ioctl_msg { #define VDEC_IOCTL_GET_NUMBER_INSTANCES _IOR(VDEC_IOCTL_MAGIC, 27, struct vdec_ioctl_msg) +#define VDEC_IOCTL_SET_PICTURE_ORDER _IOW(VDEC_IOCTL_MAGIC, 28, struct vdec_ioctl_msg) + +#define VDEC_IOCTL_SET_FRAME_RATE _IOW(VDEC_IOCTL_MAGIC, 29, struct vdec_ioctl_msg) + +#define VDEC_IOCTL_SET_H264_MV_BUFFER _IOW(VDEC_IOCTL_MAGIC, 30, struct vdec_ioctl_msg) + +#define VDEC_IOCTL_FREE_H264_MV_BUFFER _IOW(VDEC_IOCTL_MAGIC, 31, struct vdec_ioctl_msg) + +#define VDEC_IOCTL_GET_MV_BUFFER_SIZE _IOR(VDEC_IOCTL_MAGIC, 32, struct vdec_ioctl_msg) + enum vdec_picture { PICTURE_TYPE_I, PICTURE_TYPE_P, @@ -153,17 +165,17 @@ struct vdec_allocatorproperty { uint32_t mincount; uint32_t maxcount; uint32_t actualcount; - uint32_t buffer_size; + size_t buffer_size; uint32_t alignment; uint32_t buf_poolid; }; struct vdec_bufferpayload { - uint8_t *bufferaddr; - uint32_t buffer_len; + void __user *bufferaddr; + size_t buffer_len; int pmem_fd; - uint32_t offset; - uint32_t mmaped_size; + size_t offset; + size_t mmaped_size; }; struct vdec_setbuffer_cmd { @@ -396,6 +408,11 @@ enum vdec_output_fromat { VDEC_YUV_FORMAT_TILE_4x2 = 0x2 }; +enum vdec_output_order { + VDEC_ORDER_DISPLAY = 0x1, + VDEC_ORDER_DECODE = 0x2 +}; + struct vdec_picsize { uint32_t frame_width; uint32_t frame_height; @@ -404,26 +421,26 @@ struct vdec_picsize { }; struct vdec_seqheader { - uint8_t *ptr_seqheader; - uint32_t seq_header_len; + void __user *ptr_seqheader; + size_t seq_header_len; int pmem_fd; - uint32_t pmem_offset; + size_t pmem_offset; }; struct vdec_mberror { - uint8_t *ptr_errormap; - uint32_t err_mapsize; + void __user *ptr_errormap; + size_t err_mapsize; }; struct vdec_input_frameinfo { - uint8_t *bufferaddr; - uint32_t offset; - uint32_t datalen; + void __user *bufferaddr; + size_t offset; + size_t datalen; uint32_t flags; int64_t timestamp; void *client_data; int pmem_fd; - uint32_t pmem_offset; + size_t pmem_offset; }; struct vdec_framesize { @@ -434,12 +451,12 @@ struct vdec_framesize { }; struct vdec_output_frameinfo { - uint8_t *phy_addr; - uint8_t *bufferaddr; - uint32_t offset; - uint32_t len; + void __user *bufferaddr; + size_t offset; + size_t len; uint32_t flags; int64_t time_stamp; + enum vdec_picture pic_type; void *client_data; void *input_frame_clientdata; struct vdec_framesize framesize; @@ -454,7 +471,26 @@ struct vdec_msginfo { uint32_t status_code; uint32_t msgcode; union vdec_msgdata msgdata; - uint32_t msgdatasize; + size_t msgdatasize; }; -#endif +struct vdec_framerate { + unsigned long fps_denominator; + unsigned long fps_numerator; +}; + +struct vdec_h264_mv{ + size_t size; + int count; + int pmem_fd; + int offset; +}; + +struct vdec_mv_buff_size{ + int width; + int height; + int size; + int alignment; +}; + +#endif diff --git a/libc/kernel/common/linux/msm_vidc_enc.h b/libc/kernel/common/linux/msm_vidc_enc.h index 45437a2cf..58cc1ee2d 100644 --- a/libc/kernel/common/linux/msm_vidc_enc.h +++ b/libc/kernel/common/linux/msm_vidc_enc.h @@ -91,17 +91,18 @@ #define VEN_LEVEL_H264_2 0xE #define VEN_LEVEL_H264_2p1 0xF #define VEN_LEVEL_H264_2p2 0x10 -#define VEN_LEVEL_H264_3 0x11 -#define VEN_LEVEL_H264_3p1 0x12 - -#define VEN_LEVEL_H263_10 0x13 -#define VEN_LEVEL_H263_20 0x14 -#define VEN_LEVEL_H263_30 0x15 -#define VEN_LEVEL_H263_40 0x16 -#define VEN_LEVEL_H263_45 0x17 -#define VEN_LEVEL_H263_50 0x18 -#define VEN_LEVEL_H263_60 0x19 -#define VEN_LEVEL_H263_70 0x1A +#define VEN_LEVEL_H264_3 0x11 +#define VEN_LEVEL_H264_3p1 0x12 +#define VEN_LEVEL_H264_4 0x13 + +#define VEN_LEVEL_H263_10 0x14 +#define VEN_LEVEL_H263_20 0x15 +#define VEN_LEVEL_H263_30 0x16 +#define VEN_LEVEL_H263_40 0x17 +#define VEN_LEVEL_H263_45 0x18 +#define VEN_LEVEL_H263_50 0x19 +#define VEN_LEVEL_H263_60 0x1A +#define VEN_LEVEL_H263_70 0x1B #define VEN_ENTROPY_MODEL_CAVLC 1 #define VEN_ENTROPY_MODEL_CABAC 2 @@ -123,17 +124,19 @@ #define VEN_RC_VBR_VFR 2 #define VEN_RC_VBR_CFR 3 #define VEN_RC_CBR_VFR 4 +#define VEN_RC_CBR_CFR 5 #define VEN_FLUSH_INPUT 1 #define VEN_FLUSH_OUTPUT 2 #define VEN_FLUSH_ALL 3 -#define VEN_INPUTFMT_NV12 1 -#define VEN_INPUTFMT_NV21 2 +#define VEN_INPUTFMT_NV12 1 +#define VEN_INPUTFMT_NV21 2 +#define VEN_INPUTFMT_NV12_16M2KA 3 -#define VEN_ROTATION_0 1 -#define VEN_ROTATION_90 2 -#define VEN_ROTATION_180 3 +#define VEN_ROTATION_0 1 +#define VEN_ROTATION_90 2 +#define VEN_ROTATION_180 3 #define VEN_ROTATION_270 4 #define VEN_TIMEOUT_INFINITE 0xffffffff @@ -147,8 +150,8 @@ #define VEN_IOCTLBASE_ENC 0x850 struct venc_ioctl_msg{ - void *inputparam; - void *outputparam; + void __user *in; + void __user *out; }; #define VEN_IOCTL_SET_INTF_VERSION _IOW(VEN_IOCTLBASE_NENC, 0, struct venc_ioctl_msg) @@ -189,6 +192,12 @@ struct venc_ioctl_msg{ #define VEN_IOCTL_CMD_STOP _IO(VEN_IOCTLBASE_NENC, 19) +#define VEN_IOCTL_SET_RECON_BUFFER _IOW(VEN_IOCTLBASE_NENC, 20, struct venc_ioctl_msg) + +#define VEN_IOCTL_FREE_RECON_BUFFER _IOW(VEN_IOCTLBASE_NENC, 21, struct venc_ioctl_msg) + +#define VEN_IOCTL_GET_RECON_BUFFER_SIZE _IOW(VEN_IOCTLBASE_NENC, 22, struct venc_ioctl_msg) + #define VEN_IOCTL_SET_BASE_CFG _IOW(VEN_IOCTLBASE_ENC, 1, struct venc_ioctl_msg) #define VEN_IOCTL_GET_BASE_CFG _IOR(VEN_IOCTLBASE_ENC, 2, struct venc_ioctl_msg) @@ -259,6 +268,8 @@ struct venc_ioctl_msg{ #define VEN_IOCTL_SET_QP_RANGE _IOW(VEN_IOCTLBASE_ENC, 44, struct venc_ioctl_msg) #define VEN_IOCTL_GET_QP_RANGE _IOR(VEN_IOCTLBASE_ENC, 45, struct venc_ioctl_msg) +#define VEN_IOCTL_GET_NUMBER_INSTANCES _IOR(VEN_IOCTLBASE_ENC, 46, struct venc_ioctl_msg) + struct venc_switch{ unsigned char status; }; @@ -275,7 +286,7 @@ struct venc_allocatorproperty{ struct venc_bufferpayload{ unsigned char *pbuffer; - unsigned long nsize; + size_t sz; int fd; unsigned int offset; unsigned int maped_size; @@ -284,7 +295,7 @@ struct venc_bufferpayload{ struct venc_buffer{ unsigned char *ptrbuffer; - unsigned long size; + unsigned long sz; unsigned long len; unsigned long offset; long long timestamp; @@ -322,6 +333,7 @@ struct venc_qprange{ }; struct venc_intraperiod{ unsigned long num_pframes; + unsigned long num_bframes; }; struct venc_seqheader{ unsigned char *hdrbufptr; @@ -398,5 +410,18 @@ struct venc_msg{ struct venc_buffer buf; unsigned long msgdata_size; }; -#endif +struct venc_recon_addr{ + unsigned long buffer_size; + unsigned long pmem_fd; + unsigned long offset; +}; + +struct venc_recon_buff_size{ + int width; + int height; + int size; + int alignment; +}; + +#endif diff --git a/libc/kernel/common/linux/spi_aic3254.h b/libc/kernel/common/linux/spi_aic3254.h new file mode 100644 index 000000000..392d7ae00 --- /dev/null +++ b/libc/kernel/common/linux/spi_aic3254.h @@ -0,0 +1,151 @@ +/**************************************************************************** + **************************************************************************** + *** + *** This header was automatically generated from a Linux kernel header + *** of the same name, to make information necessary for userspace to + *** call into the kernel available to libc. It contains only constants, + *** structures, and macros generated from the original header, and thus, + *** contains no copyrightable information. + *** + **************************************************************************** + ****************************************************************************/ +#ifndef __SPI_AIC3254_H__ +#define __SPI_AIC3254_H__ + +#include <linux/ioctl.h> + +typedef struct _CODEC_SPI_CMD { + unsigned char act; + unsigned char reg; + unsigned char data; +} CODEC_SPI_CMD; + +typedef struct _CODEC_SPI_CMD_PARAM { + CODEC_SPI_CMD *data; + unsigned int len; +} CODEC_SPI_CMD_PARAM; + +struct AIC3254_PARAM { + unsigned int row_num; + unsigned int col_num; + void *cmd_data; +}; + +struct CODEC_CFG { + unsigned char tb_idx; + unsigned char index; +}; + +#define AIC3254_IOCTL_MAGIC 's' +#define AIC3254_SET_TX_PARAM _IOW(AIC3254_IOCTL_MAGIC, 0x10, unsigned) +#define AIC3254_SET_RX_PARAM _IOW(AIC3254_IOCTL_MAGIC, 0x11, unsigned) +#define AIC3254_CONFIG_TX _IOW(AIC3254_IOCTL_MAGIC, 0x12, unsigned int) +#define AIC3254_CONFIG_RX _IOW(AIC3254_IOCTL_MAGIC, 0x13, unsigned int) +#define AIC3254_SET_DSP_PARAM _IOW(AIC3254_IOCTL_MAGIC, 0x20, unsigned) +#define AIC3254_CONFIG_MEDIA _IOW(AIC3254_IOCTL_MAGIC, 0x21, unsigned int) +#define AIC3254_CONFIG_VOICE _IOW(AIC3254_IOCTL_MAGIC, 0x22, unsigned int) +#define AIC3254_CONFIG_VOLUME_L _IOW(AIC3254_IOCTL_MAGIC, 0x23, unsigned int) +#define AIC3254_CONFIG_VOLUME_R _IOW(AIC3254_IOCTL_MAGIC, 0x24, unsigned int) +#define AIC3254_POWERDOWN _IOW(AIC3254_IOCTL_MAGIC, 0x25, unsigned int) +#define AIC3254_LOOPBACK _IOW(AIC3254_IOCTL_MAGIC, 0x26, unsigned int) +#define AIC3254_DUMP_PAGES _IOW(AIC3254_IOCTL_MAGIC, 0x30, unsigned int) +#define AIC3254_READ_REG _IOWR(AIC3254_IOCTL_MAGIC, 0x31, unsigned) +#define AIC3254_WRITE_REG _IOW(AIC3254_IOCTL_MAGIC, 0x32, unsigned) +#define AIC3254_RESET _IOW(AIC3254_IOCTL_MAGIC, 0x33, unsigned int) + +#define AIC3254_MAX_PAGES 255 +#define AIC3254_MAX_REGS 128 +#define AIC3254_MAX_RETRY 10 + +#define IO_CTL_ROW_MAX 64 +#define IO_CTL_COL_MAX 1024 +#define MINIDSP_ROW_MAX 32 +#define MINIDSP_COL_MAX 16384 + +enum aic3254_uplink_mode { + INITIAL = 0, + CALL_UPLINK_IMIC_RECEIVER = 1, + CALL_UPLINK_EMIC_HEADSET, + CALL_UPLINK_IMIC_HEADSET, + CALL_UPLINK_IMIC_SPEAKER, + CALL_UPLINK_IMIC_RECEIVER_DUALMIC, + CALL_UPLINK_EMIC_HEADSET_DUALMIC, + CALL_UPLINK_IMIC_SPEAKER_DUALMIC, + CALL_UPLINK_IMIC_RECIVER_TESTSIM, + CALL_UPLINK_EMIC_HEADSET_TESTSIM, + CALL_UPLINK_IMIC_SPEAKER_TESTSIM, + VOICERECORD_IMIC = 15, + VOICERECORD_EMIC, + VIDEORECORD_IMIC, + VIDEORECORD_EMIC, + VOICERECOGNITION_IMIC, + VOICERECOGNITION_EMIC, + FM_IN_SPEAKER, + FM_IN_HEADSET, + TTY_IN_HCO, + TTY_IN_VCO, + TTY_IN_FULL, + UPLINK_OFF = 29, + UPLINK_WAKEUP, + POWER_OFF, + SLEEP_WITH_HP_IN, + VOICERECORD_IMIC_PLAYBACK_SPEAKER, + VOICERECORD_EMIC_PLAYBACK_HEADSET, + VOICERECORD_IMIC_PLAYBACK_HEADSET, +}; + +enum aic3254_downlink_mode { + CALL_DOWNLINK_IMIC_RECEIVER = 1, + CALL_DOWNLINK_EMIC_HEADSET, + CALL_DOWNLINK_IMIC_HEADSET, + CALL_DOWNLINK_IMIC_SPEAKER, + CALL_DOWNLINK_IMIC_RECEIVER_DUALMIC, + CALL_DOWNLINK_EMIC_HEADSET_DUALMIC, + CALL_DOWNLINK_IMIC_SPEAKER_DUALMIC, + CALL_DOWNLINK_IMIC_RECIVER_TESTSIM, + CALL_DOWNLINK_EMIC_HEADSET_TESTSIM, + CALL_DOWNLINK_IMIC_SPEAKER_TESTSIM, + PLAYBACK_RECEIVER, + PLAYBACK_HEADSET, + PLAYBACK_SPEAKER = 13, + RING_HEADSET_SPEAKER, + PLAYBACK_SPEAKER_ALT, + USB_AUDIO, + FM_OUT_SPEAKER = 21, + FM_OUT_HEADSET, + TTY_OUT_HCO, + TTY_OUT_VCO, + TTY_OUT_FULL, + MUSE, + HAC, + LPM_IMIC_RECEIVER, + DOWNLINK_OFF = 29, + DOWNLINK_WAKEUP, +}; + +struct aic3254_ctl_ops { + void (*tx_amp_enable)(int en); + void (*rx_amp_enable)(int en); + int (*panel_sleep_in)(void); + void (*reset_3254)(void); + void (*spibus_enable)(int en); + CODEC_SPI_CMD_PARAM *downlink_off; + CODEC_SPI_CMD_PARAM *uplink_off; + CODEC_SPI_CMD_PARAM *downlink_on; + CODEC_SPI_CMD_PARAM *uplink_on; + CODEC_SPI_CMD_PARAM *lb_dsp_init; + CODEC_SPI_CMD_PARAM *lb_downlink_receiver; + CODEC_SPI_CMD_PARAM *lb_downlink_speaker; + CODEC_SPI_CMD_PARAM *lb_downlink_headset; + CODEC_SPI_CMD_PARAM *lb_uplink_imic; + CODEC_SPI_CMD_PARAM *lb_uplink_emic; + CODEC_SPI_CMD_PARAM *lb_receiver_imic; + CODEC_SPI_CMD_PARAM *lb_speaker_imic; + CODEC_SPI_CMD_PARAM *lb_headset_emic; + CODEC_SPI_CMD_PARAM *lb_receiver_bmic; + CODEC_SPI_CMD_PARAM *lb_speaker_bmic; + CODEC_SPI_CMD_PARAM *lb_headset_bmic; +}; + +#endif + diff --git a/libc/kernel/common/linux/tpa2051d3.h b/libc/kernel/common/linux/tpa2051d3.h new file mode 100644 index 000000000..446db99ee --- /dev/null +++ b/libc/kernel/common/linux/tpa2051d3.h @@ -0,0 +1,52 @@ +/**************************************************************************** + **************************************************************************** + *** + *** This header was automatically generated from a Linux kernel header + *** of the same name, to make information necessary for userspace to + *** call into the kernel available to libc. It contains only constants, + *** structures, and macros generated from the original header, and thus, + *** contains no copyrightable information. + *** + **************************************************************************** + ****************************************************************************/ +#ifndef TPA2051D3_H +#define TPA2051D3_H + +#include <linux/ioctl.h> + +#define TPA2051D3_I2C_NAME "tpa2051d3" +#define SPKR_OUTPUT 0 +#define HEADSET_OUTPUT 1 +#define DUAL_OUTPUT 2 +#define HANDSET_OUTPUT 3 +#define MODE_CMD_LEM 9 +struct tpa2051d3_platform_data { + uint32_t gpio_tpa2051_spk_en; +}; + +struct tpa2051_config_data { + unsigned int data_len; + unsigned int mode_num; + unsigned char *cmd_data; +}; + +enum TPA2051_Mode { + TPA2051_MODE_OFF, + TPA2051_MODE_PLAYBACK_SPKR, + TPA2051_MODE_PLAYBACK_HEADSET, + TPA2051_MODE_RING, + TPA2051_MODE_VOICECALL_SPKR, + TPA2051_MODE_VOICECALL_HEADSET, + TPA2051_MODE_FM_SPKR, + TPA2051_MODE_FM_HEADSET, + TPA2051_MODE_HANDSET, + TPA2051_MAX_MODE +}; +#define TPA2051_IOCTL_MAGIC 'a' +#define TPA2051_SET_CONFIG _IOW(TPA2051_IOCTL_MAGIC, 0x01, unsigned) +#define TPA2051_READ_CONFIG _IOW(TPA2051_IOCTL_MAGIC, 0x02, unsigned) +#define TPA2051_SET_MODE _IOW(TPA2051_IOCTL_MAGIC, 0x03, unsigned) +#define TPA2051_SET_PARAM _IOW(TPA2051_IOCTL_MAGIC, 0x04, unsigned) + +#endif + diff --git a/libc/kernel/common/linux/videodev2.h b/libc/kernel/common/linux/videodev2.h index 3a91510a2..5e52ce48e 100644 --- a/libc/kernel/common/linux/videodev2.h +++ b/libc/kernel/common/linux/videodev2.h @@ -413,6 +413,9 @@ struct v4l2_window { __u32 clipcount; void __user *bitmap; __u8 global_alpha; +#ifdef OMAP_ENHANCEMENT + __u8 zorder; +#endif }; struct v4l2_captureparm { diff --git a/libc/netbsd/net/getaddrinfo.c b/libc/netbsd/net/getaddrinfo.c index e4d8c56a7..edb4f707e 100644 --- a/libc/netbsd/net/getaddrinfo.c +++ b/libc/netbsd/net/getaddrinfo.c @@ -77,10 +77,13 @@ * friends. */ +#include <fcntl.h> #include <sys/cdefs.h> #include <sys/types.h> +#include <sys/stat.h> #include <sys/param.h> #include <sys/socket.h> +#include <sys/un.h> #include <net/if.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -100,6 +103,10 @@ #include <stdarg.h> #include "nsswitch.h" +#ifdef ANDROID_CHANGES +#include <sys/system_properties.h> +#endif /* ANDROID_CHANGES */ + typedef union sockaddr_union { struct sockaddr generic; struct sockaddr_in in; @@ -391,6 +398,191 @@ _have_ipv4() { return _test_connect(PF_INET, &addr.generic, sizeof(addr.in)); } +// Returns 0 on success, else returns non-zero on error (in which case +// getaddrinfo should continue as normal) +static int +android_getaddrinfo_proxy( + const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + int sock; + const int one = 1; + struct sockaddr_un proxy_addr; + const char* cache_mode = getenv("ANDROID_DNS_MODE"); + FILE* proxy = NULL; + int success = 0; + + // Clear this at start, as we use its non-NULLness later (in the + // error path) to decide if we have to free up any memory we + // allocated in the process (before failing). + *res = NULL; + + if (cache_mode != NULL && strcmp(cache_mode, "local") == 0) { + // Don't use the proxy in local mode. This is used by the + // proxy itself. + return -1; + } + + // Temporary cautious hack to disable the DNS proxy for processes + // requesting special treatment. Ideally the DNS proxy should + // accomodate these apps, though. + char propname[PROP_NAME_MAX]; + char propvalue[PROP_VALUE_MAX]; + snprintf(propname, sizeof(propname), "net.dns1.%d", getpid()); + if (__system_property_get(propname, propvalue) > 0) { + return -1; + } + + // Bogus things we can't serialize. Don't use the proxy. + if ((hostname != NULL && + strcspn(hostname, " \n\r\t^'\"") != strlen(hostname)) || + (servname != NULL && + strcspn(servname, " \n\r\t^'\"") != strlen(servname))) { + return -1; + } + + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + return -1; + } + + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + memset(&proxy_addr, 0, sizeof(proxy_addr)); + proxy_addr.sun_family = AF_UNIX; + strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", + sizeof(proxy_addr.sun_path)); + if (TEMP_FAILURE_RETRY(connect(sock, + (const struct sockaddr*) &proxy_addr, + sizeof(proxy_addr))) != 0) { + close(sock); + return -1; + } + + // Send the request. + proxy = fdopen(sock, "r+"); + if (fprintf(proxy, "getaddrinfo %s %s %d %d %d %d", + hostname == NULL ? "^" : hostname, + servname == NULL ? "^" : servname, + hints == NULL ? -1 : hints->ai_flags, + hints == NULL ? -1 : hints->ai_family, + hints == NULL ? -1 : hints->ai_socktype, + hints == NULL ? -1 : hints->ai_protocol) < 0) { + goto exit; + } + // literal NULL byte at end, required by FrameworkListener + if (fputc(0, proxy) == EOF || + fflush(proxy) != 0) { + goto exit; + } + + int remote_rv; + if (fread(&remote_rv, sizeof(int), 1, proxy) != 1) { + goto exit; + } + + if (remote_rv != 0) { + goto exit; + } + + struct addrinfo* ai = NULL; + struct addrinfo** nextres = res; + while (1) { + uint32_t addrinfo_len; + if (fread(&addrinfo_len, sizeof(addrinfo_len), + 1, proxy) != 1) { + break; + } + addrinfo_len = ntohl(addrinfo_len); + if (addrinfo_len == 0) { + success = 1; + break; + } + + if (addrinfo_len < sizeof(struct addrinfo)) { + break; + } + struct addrinfo* ai = calloc(1, addrinfo_len + + sizeof(struct sockaddr_storage)); + if (ai == NULL) { + break; + } + + if (fread(ai, addrinfo_len, 1, proxy) != 1) { + // Error; fall through. + break; + } + + // Zero out the pointer fields we copied which aren't + // valid in this address space. + ai->ai_addr = NULL; + ai->ai_canonname = NULL; + ai->ai_next = NULL; + + // struct sockaddr + uint32_t addr_len; + if (fread(&addr_len, sizeof(addr_len), 1, proxy) != 1) { + break; + } + addr_len = ntohl(addr_len); + if (addr_len != 0) { + if (addr_len > sizeof(struct sockaddr_storage)) { + // Bogus; too big. + break; + } + struct sockaddr* addr = (struct sockaddr*)(ai + 1); + if (fread(addr, addr_len, 1, proxy) != 1) { + break; + } + ai->ai_addr = addr; + } + + // cannonname + uint32_t name_len; + if (fread(&name_len, sizeof(name_len), 1, proxy) != 1) { + break; + } + name_len = ntohl(name_len); + if (name_len != 0) { + ai->ai_canonname = (char*) malloc(name_len); + if (fread(ai->ai_canonname, name_len, 1, proxy) != 1) { + break; + } + if (ai->ai_canonname[name_len - 1] != '\0') { + // The proxy should be returning this + // NULL-terminated. + break; + } + } + + *nextres = ai; + nextres = &ai->ai_next; + ai = NULL; + } + + if (ai != NULL) { + // Clean up partially-built addrinfo that we never ended up + // attaching to the response. + freeaddrinfo(ai); + } +exit: + if (proxy != NULL) { + fclose(proxy); + } + + if (success) { + return 0; + } + + // Proxy failed; fall through to local + // resolver case. But first clean up any + // memory we might've allocated. + if (*res) { + freeaddrinfo(*res); + *res = NULL; + } + return -1; +} + int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res) @@ -537,6 +729,13 @@ getaddrinfo(const char *hostname, const char *servname, if (pai->ai_flags & AI_NUMERICHOST) ERR(EAI_NONAME); + /* + * BEGIN ANDROID CHANGES; proxying to the cache + */ + if (android_getaddrinfo_proxy(hostname, servname, hints, res) == 0) { + return 0; + } + /* * hostname as alphabetical name. * we would like to prefer AF_INET6 than AF_INET, so we'll make a diff --git a/libc/netbsd/net/getnameinfo.c b/libc/netbsd/net/getnameinfo.c index 36664435d..d3d0011b9 100644 --- a/libc/netbsd/net/getnameinfo.c +++ b/libc/netbsd/net/getnameinfo.c @@ -64,6 +64,11 @@ __RCSID("$NetBSD: getnameinfo.c,v 1.43 2006/02/17 15:58:26 ginsbach Exp $"); #include <netdb.h> #ifdef ANDROID_CHANGES #include "resolv_private.h" +#include <sys/system_properties.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/un.h> +#include <errno.h> #else #include <resolv.h> #endif @@ -124,7 +129,98 @@ int getnameinfo(const struct sockaddr* sa, socklen_t salen, char* host, size_t h } } +#ifdef ANDROID_CHANGES +/* On success length of the host name is returned. A return + * value of 0 means there's no host name associated with + * the address. On failure -1 is returned in which case + * normal execution flow shall continue. */ +static int +android_gethostbyaddr_proxy(struct hostent* hp, const void *addr, socklen_t addrLen, int addrFamily) { + + int sock; + const int one = 1; + struct sockaddr_un proxy_addr; + const char* cache_mode = getenv("ANDROID_DNS_MODE"); + FILE* proxy = NULL; + int result = -1; + + if (cache_mode != NULL && strcmp(cache_mode, "local") == 0) { + // Don't use the proxy in local mode. This is used by the + // proxy itself. + return -1; + } + + // Temporary cautious hack to disable the DNS proxy for processes + // requesting special treatment. Ideally the DNS proxy should + // accomodate these apps, though. + char propname[PROP_NAME_MAX]; + char propvalue[PROP_VALUE_MAX]; + snprintf(propname, sizeof(propname), "net.dns1.%d", getpid()); + if (__system_property_get(propname, propvalue) > 0) { + return -1; + } + // create socket + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + return -1; + } + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); + memset(&proxy_addr, 0, sizeof(proxy_addr)); + proxy_addr.sun_family = AF_UNIX; + strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd", + sizeof(proxy_addr.sun_path)); + if (TEMP_FAILURE_RETRY(connect(sock, (const struct sockaddr*) (void*) &proxy_addr, + sizeof(proxy_addr))) != 0) { + close(sock); + return -1; + } + + // send request to DnsProxyListener + proxy = fdopen(sock,"r+"); + if (proxy == NULL) { + goto exit; + } + + char buf[INET6_ADDRSTRLEN]; // big enough for IPv4 and IPv6 + const char* addrStr = inet_ntop(addrFamily, addr, &buf, sizeof(buf)); + if (addrStr == NULL) { + goto exit; + } + if (fprintf(proxy, "gethostbyaddr %s %d %d", addrStr, addrLen, addrFamily) < 0) { + goto exit; + } + + // literal NULL byte at end, required by FrameworkListener + if (fputc(0, proxy) == EOF || fflush(proxy) != 0) { + goto exit; + } + + result = 0; + uint32_t name_len; + if (fread(&name_len, sizeof(name_len), 1, proxy) != 1) { + goto exit; + } + + name_len = ntohl(name_len); + if (name_len <= 0) { + goto exit; + } + + if (fread(hp->h_name, name_len, 1, proxy) != 1) { + goto exit; + } + + result = name_len; + + exit: + if (proxy != NULL) { + fclose(proxy); + } + + return result; +} +#endif /* * getnameinfo_inet(): * Format an IPv4 or IPv6 sockaddr into a printable string. @@ -277,7 +373,21 @@ getnameinfo_inet(sa, salen, host, hostlen, serv, servlen, flags) break; } } else { +#ifdef ANDROID_CHANGES + struct hostent android_proxy_hostent; + char android_proxy_buf[MAXDNAME]; + android_proxy_hostent.h_name = android_proxy_buf; + + int hostnamelen = android_gethostbyaddr_proxy(&android_proxy_hostent, + addr, afd->a_addrlen, afd->a_af); + if (hostnamelen >= 0) { + hp = (hostnamelen > 0) ? &android_proxy_hostent : NULL; + } else { + hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); + } +#else hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); +#endif if (hp) { #if 0 diff --git a/libc/netbsd/resolv/res_cache.c b/libc/netbsd/resolv/res_cache.c index 2621a7bbf..20f37e106 100644 --- a/libc/netbsd/resolv/res_cache.c +++ b/libc/netbsd/resolv/res_cache.c @@ -27,17 +27,28 @@ */ #include "resolv_cache.h" +#include <resolv.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "pthread.h" +#include <errno.h> +#include "arpa_nameser.h" +#include <sys/system_properties.h> +#include <net/if.h> +#include <netdb.h> +#include <linux/if.h> + +#include <arpa/inet.h> +#include "resolv_private.h" + /* This code implements a small and *simple* DNS resolver cache. * - * It is only used to cache DNS answers for a maximum of CONFIG_SECONDS seconds - * in order to reduce DNS traffic. It is not supposed to be a full DNS cache, - * since we plan to implement that in the future in a dedicated process running - * on the system. + * It is only used to cache DNS answers for a time defined by the smallest TTL + * among the answer records in order to reduce DNS traffic. It is not supposed + * to be a full DNS cache, since we plan to implement that in the future in a + * dedicated process running on the system. * * Note that its design is kept simple very intentionally, i.e.: * @@ -47,9 +58,8 @@ * (this means that two similar queries that encode the DNS name * differently will be treated distinctly). * - * - the TTLs of answer RRs are ignored. our DNS resolver library does not use - * them anyway, but it means that records with a TTL smaller than - * CONFIG_SECONDS will be kept in the cache anyway. + * the smallest TTL value among the answer records are used as the time + * to keep an answer in the cache. * * this is bad, but we absolutely want to avoid parsing the answer packets * (and should be solved by the later full DNS cache process). @@ -104,7 +114,7 @@ */ #define CONFIG_SECONDS (60*10) /* 10 minutes */ -/* maximum number of entries kept in the cache. This value has been +/* default number of entries kept in the cache. This value has been * determined by browsing through various sites and counting the number * of corresponding requests. Keep in mind that our framework is currently * performing two requests per name lookup (one for IPv4, the other for IPv6) @@ -123,10 +133,16 @@ * most high-level websites use lots of media/ad servers with different names * but these are generally reused when browsing through the site. * - * As such, a valud of 64 should be relatively conformtable at the moment. + * As such, a value of 64 should be relatively comfortable at the moment. + * + * The system property ro.net.dns_cache_size can be used to override the default + * value with a custom value */ #define CONFIG_MAX_ENTRIES 64 +/* name of the system property that can be used to set the cache size */ +#define DNS_CACHE_SIZE_PROP_NAME "ro.net.dns_cache_size" + /****************************************************************************/ /****************************************************************************/ /***** *****/ @@ -141,6 +157,7 @@ /* set to 1 to debug query data */ #define DEBUG_DATA 0 +#undef XLOG #if DEBUG # include <logd.h> # define XLOG(...) \ @@ -987,10 +1004,50 @@ typedef struct Entry { int querylen; const uint8_t* answer; int answerlen; - time_t when; /* time_t when entry was added to table */ - int id; /* for debugging purpose */ + time_t expires; /* time_t when the entry isn't valid any more */ + int id; /* for debugging purpose */ } Entry; +/** + * Parse the answer records and find the smallest + * TTL among the answer records. + * + * The returned TTL is the number of seconds to + * keep the answer in the cache. + * + * In case of parse error zero (0) is returned which + * indicates that the answer shall not be cached. + */ +static u_long +answer_getTTL(const void* answer, int answerlen) +{ + ns_msg handle; + int ancount, n; + u_long result, ttl; + ns_rr rr; + + result = 0; + if (ns_initparse(answer, answerlen, &handle) >= 0) { + // get number of answer records + ancount = ns_msg_count(handle, ns_s_an); + for (n = 0; n < ancount; n++) { + if (ns_parserr(&handle, ns_s_an, n, &rr) == 0) { + ttl = ns_rr_ttl(rr); + if (n == 0 || ttl < result) { + result = ttl; + } + } else { + XLOG("ns_parserr failed ancount no = %d. errno = %s\n", n, strerror(errno)); + } + } + } else { + XLOG("ns_parserr failed. %s\n", strerror(errno)); + } + + XLOG("TTL = %d\n", result); + + return result; +} static void entry_free( Entry* e ) @@ -1072,8 +1129,6 @@ entry_alloc( const Entry* init, const void* answer, int answerlen ) memcpy( (char*)e->answer, answer, e->answerlen ); - e->when = _time_now(); - return e; } @@ -1103,17 +1158,25 @@ entry_equals( const Entry* e1, const Entry* e2 ) * for simplicity, the hash-table fields 'hash' and 'hlink' are * inlined in the Entry structure. */ -#define MAX_HASH_ENTRIES (2*CONFIG_MAX_ENTRIES) typedef struct resolv_cache { + int max_entries; int num_entries; Entry mru_list; pthread_mutex_t lock; unsigned generation; int last_id; - Entry* entries[ MAX_HASH_ENTRIES ]; + Entry* entries; } Cache; +typedef struct resolv_cache_info { + char ifname[IF_NAMESIZE + 1]; + struct in_addr ifaddr; + Cache* cache; + struct resolv_cache_info* next; + char* nameservers[MAXNS +1]; + struct addrinfo* nsaddrinfo[MAXNS + 1]; +} CacheInfo; #define HTABLE_VALID(x) ((x) != NULL && (x) != HTABLE_DELETED) @@ -1123,9 +1186,9 @@ _cache_flush_locked( Cache* cache ) int nn; time_t now = _time_now(); - for (nn = 0; nn < MAX_HASH_ENTRIES; nn++) + for (nn = 0; nn < cache->max_entries; nn++) { - Entry** pnode = &cache->entries[nn]; + Entry** pnode = (Entry**) &cache->entries[nn]; while (*pnode != NULL) { Entry* node = *pnode; @@ -1143,17 +1206,48 @@ _cache_flush_locked( Cache* cache ) "*************************"); } -struct resolv_cache* +/* Return max number of entries allowed in the cache, + * i.e. cache size. The cache size is either defined + * by system property ro.net.dns_cache_size or by + * CONFIG_MAX_ENTRIES if system property not set + * or set to invalid value. */ +static int +_res_cache_get_max_entries( void ) +{ + int result = -1; + char cache_size[PROP_VALUE_MAX]; + + if (__system_property_get(DNS_CACHE_SIZE_PROP_NAME, cache_size) > 0) { + result = atoi(cache_size); + } + + // ro.net.dns_cache_size not set or set to negative value + if (result <= 0) { + result = CONFIG_MAX_ENTRIES; + } + + XLOG("cache size: %d", result); + return result; +} + +static struct resolv_cache* _resolv_cache_create( void ) { struct resolv_cache* cache; cache = calloc(sizeof(*cache), 1); if (cache) { - cache->generation = ~0U; - pthread_mutex_init( &cache->lock, NULL ); - cache->mru_list.mru_prev = cache->mru_list.mru_next = &cache->mru_list; - XLOG("%s: cache created\n", __FUNCTION__); + cache->max_entries = _res_cache_get_max_entries(); + cache->entries = calloc(sizeof(*cache->entries), cache->max_entries); + if (cache->entries) { + cache->generation = ~0U; + pthread_mutex_init( &cache->lock, NULL ); + cache->mru_list.mru_prev = cache->mru_list.mru_next = &cache->mru_list; + XLOG("%s: cache created\n", __FUNCTION__); + } else { + free(cache); + cache = NULL; + } } return cache; } @@ -1183,12 +1277,47 @@ _cache_dump_mru( Cache* cache ) XLOG("%s", temp); } + +static void +_dump_answer(const void* answer, int answerlen) +{ + res_state statep; + FILE* fp; + char* buf; + int fileLen; + + fp = fopen("/data/reslog.txt", "w+"); + if (fp != NULL) { + statep = __res_get_state(); + + res_pquery(statep, answer, answerlen, fp); + + //Get file length + fseek(fp, 0, SEEK_END); + fileLen=ftell(fp); + fseek(fp, 0, SEEK_SET); + buf = (char *)malloc(fileLen+1); + if (buf != NULL) { + //Read file contents into buffer + fread(buf, fileLen, 1, fp); + XLOG("%s\n", buf); + free(buf); + } + fclose(fp); + remove("/data/reslog.txt"); + } + else { + XLOG("_dump_answer: can't open file\n"); + } +} #endif #if DEBUG # define XLOG_QUERY(q,len) _dump_query((q), (len)) +# define XLOG_ANSWER(a, len) _dump_answer((a), (len)) #else # define XLOG_QUERY(q,len) ((void)0) +# define XLOG_ANSWER(a,len) ((void)0) #endif /* This function tries to find a key within the hash table @@ -1209,8 +1338,8 @@ static Entry** _cache_lookup_p( Cache* cache, Entry* key ) { - int index = key->hash % MAX_HASH_ENTRIES; - Entry** pnode = &cache->entries[ key->hash % MAX_HASH_ENTRIES ]; + int index = key->hash % cache->max_entries; + Entry** pnode = (Entry**) &cache->entries[ index ]; while (*pnode != NULL) { Entry* node = *pnode; @@ -1322,7 +1451,7 @@ _resolv_cache_lookup( struct resolv_cache* cache, now = _time_now(); /* remove stale entries here */ - if ( (unsigned)(now - e->when) >= CONFIG_SECONDS ) { + if (now >= e->expires) { XLOG( " NOT IN CACHE (STALE ENTRY %p DISCARDED)", *lookup ); _cache_remove_p(cache, lookup); goto Exit; @@ -1363,6 +1492,7 @@ _resolv_cache_add( struct resolv_cache* cache, Entry key[1]; Entry* e; Entry** lookup; + u_long ttl; /* don't assume that the query has already been cached */ @@ -1375,6 +1505,7 @@ _resolv_cache_add( struct resolv_cache* cache, XLOG( "%s: query:", __FUNCTION__ ); XLOG_QUERY(query,querylen); + XLOG_ANSWER(answer, answerlen); #if DEBUG_DATA XLOG( "answer:"); XLOG_BYTES(answer,answerlen); @@ -1389,7 +1520,7 @@ _resolv_cache_add( struct resolv_cache* cache, goto Exit; } - if (cache->num_entries >= CONFIG_MAX_ENTRIES) { + if (cache->num_entries >= cache->max_entries) { _cache_remove_oldest(cache); /* need to lookup again */ lookup = _cache_lookup_p(cache, key); @@ -1401,9 +1532,13 @@ _resolv_cache_add( struct resolv_cache* cache, } } - e = entry_alloc( key, answer, answerlen ); - if (e != NULL) { - _cache_add_p(cache, lookup, e); + ttl = answer_getTTL(answer, answerlen); + if (ttl > 0) { + e = entry_alloc(key, answer, answerlen); + if (e != NULL) { + e->expires = ttl + _time_now(); + _cache_add_p(cache, lookup, e); + } } #if DEBUG _cache_dump_mru(cache); @@ -1420,11 +1555,47 @@ Exit: /****************************************************************************/ /****************************************************************************/ -static struct resolv_cache* _res_cache; static pthread_once_t _res_cache_once; +// Head of the list of caches. Protected by _res_cache_list_lock. +static struct resolv_cache_info _res_cache_list; + +// name of the current default inteface +static char _res_default_ifname[IF_NAMESIZE + 1]; + +// lock protecting everything in the _resolve_cache_info structs (next ptr, etc) +static pthread_mutex_t _res_cache_list_lock; + + +/* lookup the default interface name */ +static char *_get_default_iface_locked(); +/* insert resolv_cache_info into the list of resolv_cache_infos */ +static void _insert_cache_info_locked(struct resolv_cache_info* cache_info); +/* creates a resolv_cache_info */ +static struct resolv_cache_info* _create_cache_info( void ); +/* gets cache associated with an interface name, or NULL if none exists */ +static struct resolv_cache* _find_named_cache_locked(const char* ifname); +/* gets a resolv_cache_info associated with an interface name, or NULL if not found */ +static struct resolv_cache_info* _find_cache_info_locked(const char* ifname); +/* free dns name server list of a resolv_cache_info structure */ +static void _free_nameservers(struct resolv_cache_info* cache_info); +/* look up the named cache, and creates one if needed */ +static struct resolv_cache* _get_res_cache_for_iface_locked(const char* ifname); +/* empty the named cache */ +static void _flush_cache_for_iface_locked(const char* ifname); +/* empty the nameservers set for the named cache */ +static void _free_nameservers_locked(struct resolv_cache_info* cache_info); +/* lookup the namserver for the name interface */ +static int _get_nameserver_locked(const char* ifname, int n, char* addr, int addrLen); +/* lookup the addr of the nameserver for the named interface */ +static struct addrinfo* _get_nameserver_addr_locked(const char* ifname, int n); +/* lookup the inteface's address */ +static struct in_addr* _get_addr_locked(const char * ifname); + + + static void -_res_cache_init( void ) +_res_cache_init(void) { const char* env = getenv(CONFIG_ENV); @@ -1433,29 +1604,394 @@ _res_cache_init( void ) return; } - _res_cache = _resolv_cache_create(); + memset(&_res_default_ifname, 0, sizeof(_res_default_ifname)); + memset(&_res_cache_list, 0, sizeof(_res_cache_list)); + pthread_mutex_init(&_res_cache_list_lock, NULL); } - struct resolv_cache* -__get_res_cache( void ) +__get_res_cache(void) +{ + struct resolv_cache *cache; + + pthread_once(&_res_cache_once, _res_cache_init); + + pthread_mutex_lock(&_res_cache_list_lock); + + char* ifname = _get_default_iface_locked(); + + // if default interface not set then use the first cache + // associated with an interface as the default one. + if (ifname[0] == '\0') { + struct resolv_cache_info* cache_info = _res_cache_list.next; + while (cache_info) { + if (cache_info->ifname[0] != '\0') { + ifname = cache_info->ifname; + } + + cache_info = cache_info->next; + } + } + cache = _get_res_cache_for_iface_locked(ifname); + + pthread_mutex_unlock(&_res_cache_list_lock); + XLOG("_get_res_cache. default_ifname = %s\n", ifname); + return cache; +} + +static struct resolv_cache* +_get_res_cache_for_iface_locked(const char* ifname) { - pthread_once( &_res_cache_once, _res_cache_init ); - return _res_cache; + if (ifname == NULL) + return NULL; + + struct resolv_cache* cache = _find_named_cache_locked(ifname); + if (!cache) { + struct resolv_cache_info* cache_info = _create_cache_info(); + if (cache_info) { + cache = _resolv_cache_create(); + if (cache) { + int len = sizeof(cache_info->ifname); + cache_info->cache = cache; + strncpy(cache_info->ifname, ifname, len - 1); + cache_info->ifname[len - 1] = '\0'; + + _insert_cache_info_locked(cache_info); + } else { + free(cache_info); + } + } + } + return cache; } void -_resolv_cache_reset( unsigned generation ) +_resolv_cache_reset(unsigned generation) { XLOG("%s: generation=%d", __FUNCTION__, generation); - if (_res_cache == NULL) + pthread_once(&_res_cache_once, _res_cache_init); + pthread_mutex_lock(&_res_cache_list_lock); + + char* ifname = _get_default_iface_locked(); + // if default interface not set then use the first cache + // associated with an interface as the default one. + // Note: Copied the code from __get_res_cache since this + // method will be deleted/obsolete when cache per interface + // implemented all over + if (ifname[0] == '\0') { + struct resolv_cache_info* cache_info = _res_cache_list.next; + while (cache_info) { + if (cache_info->ifname[0] != '\0') { + ifname = cache_info->ifname; + } + + cache_info = cache_info->next; + } + } + struct resolv_cache* cache = _get_res_cache_for_iface_locked(ifname); + + if (cache == NULL) { + pthread_mutex_unlock(&_res_cache_list_lock); return; + } + + pthread_mutex_lock( &cache->lock ); + if (cache->generation != generation) { + _cache_flush_locked(cache); + cache->generation = generation; + } + pthread_mutex_unlock( &cache->lock ); + + pthread_mutex_unlock(&_res_cache_list_lock); +} + +void +_resolv_flush_cache_for_default_iface(void) +{ + char* ifname; + + pthread_once(&_res_cache_once, _res_cache_init); + pthread_mutex_lock(&_res_cache_list_lock); + + ifname = _get_default_iface_locked(); + _flush_cache_for_iface_locked(ifname); + + pthread_mutex_unlock(&_res_cache_list_lock); +} + +void +_resolv_flush_cache_for_iface(const char* ifname) +{ + pthread_once(&_res_cache_once, _res_cache_init); + pthread_mutex_lock(&_res_cache_list_lock); + + _flush_cache_for_iface_locked(ifname); + + pthread_mutex_unlock(&_res_cache_list_lock); +} + +static void +_flush_cache_for_iface_locked(const char* ifname) +{ + struct resolv_cache* cache = _find_named_cache_locked(ifname); + if (cache) { + pthread_mutex_lock(&cache->lock); + _cache_flush_locked(cache); + pthread_mutex_unlock(&cache->lock); + } +} + +static struct resolv_cache_info* +_create_cache_info(void) +{ + struct resolv_cache_info* cache_info; + + cache_info = calloc(sizeof(*cache_info), 1); + return cache_info; +} + +static void +_insert_cache_info_locked(struct resolv_cache_info* cache_info) +{ + struct resolv_cache_info* last; + + for (last = &_res_cache_list; last->next; last = last->next); + + last->next = cache_info; + +} + +static struct resolv_cache* +_find_named_cache_locked(const char* ifname) { + + struct resolv_cache_info* info = _find_cache_info_locked(ifname); + + if (info != NULL) return info->cache; + + return NULL; +} + +static struct resolv_cache_info* +_find_cache_info_locked(const char* ifname) +{ + if (ifname == NULL) + return NULL; + + struct resolv_cache_info* cache_info = _res_cache_list.next; + + while (cache_info) { + if (strcmp(cache_info->ifname, ifname) == 0) { + break; + } + + cache_info = cache_info->next; + } + return cache_info; +} + +static char* +_get_default_iface_locked(void) +{ + char* iface = _res_default_ifname; + + return iface; +} + +void +_resolv_set_default_iface(const char* ifname) +{ + XLOG("_resolv_set_default_if ifname %s\n",ifname); + + pthread_once(&_res_cache_once, _res_cache_init); + pthread_mutex_lock(&_res_cache_list_lock); + + int size = sizeof(_res_default_ifname); + memset(_res_default_ifname, 0, size); + strncpy(_res_default_ifname, ifname, size - 1); + _res_default_ifname[size - 1] = '\0'; + + pthread_mutex_unlock(&_res_cache_list_lock); +} + +void +_resolv_set_nameservers_for_iface(const char* ifname, char** servers, int numservers) +{ + int i, rt, index; + struct addrinfo hints; + char sbuf[NI_MAXSERV]; + + pthread_once(&_res_cache_once, _res_cache_init); + + pthread_mutex_lock(&_res_cache_list_lock); + // creates the cache if not created + _get_res_cache_for_iface_locked(ifname); + + struct resolv_cache_info* cache_info = _find_cache_info_locked(ifname); + + if (cache_info != NULL) { + // free current before adding new + _free_nameservers_locked(cache_info); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + hints.ai_flags = AI_NUMERICHOST; + sprintf(sbuf, "%u", NAMESERVER_PORT); + + index = 0; + for (i = 0; i < numservers && i < MAXNS; i++) { + rt = getaddrinfo(servers[i], sbuf, &hints, &cache_info->nsaddrinfo[index]); + if (rt == 0) { + cache_info->nameservers[index] = strdup(servers[i]); + index++; + } else { + cache_info->nsaddrinfo[index] = NULL; + } + } + } + pthread_mutex_unlock(&_res_cache_list_lock); +} + +static void +_free_nameservers_locked(struct resolv_cache_info* cache_info) +{ + int i; + for (i = 0; i <= MAXNS; i++) { + free(cache_info->nameservers[i]); + cache_info->nameservers[i] = NULL; + if (cache_info->nsaddrinfo[i] != NULL) { + freeaddrinfo(cache_info->nsaddrinfo[i]); + cache_info->nsaddrinfo[i] = NULL; + } + } +} + +int +_resolv_cache_get_nameserver(int n, char* addr, int addrLen) +{ + char *ifname; + int result = 0; + + pthread_once(&_res_cache_once, _res_cache_init); + pthread_mutex_lock(&_res_cache_list_lock); + + ifname = _get_default_iface_locked(); + result = _get_nameserver_locked(ifname, n, addr, addrLen); + + pthread_mutex_unlock(&_res_cache_list_lock); + return result; +} + +static int +_get_nameserver_locked(const char* ifname, int n, char* addr, int addrLen) +{ + int len = 0; + char* ns; + struct resolv_cache_info* cache_info; + + if (n < 1 || n > MAXNS || !addr) + return 0; + + cache_info = _find_cache_info_locked(ifname); + if (cache_info) { + ns = cache_info->nameservers[n - 1]; + if (ns) { + len = strlen(ns); + if (len < addrLen) { + strncpy(addr, ns, len); + addr[len] = '\0'; + } else { + len = 0; + } + } + } + + return len; +} + +struct addrinfo* +_cache_get_nameserver_addr(int n) +{ + struct addrinfo *result; + char* ifname; + + pthread_once(&_res_cache_once, _res_cache_init); + pthread_mutex_lock(&_res_cache_list_lock); + + ifname = _get_default_iface_locked(); + + result = _get_nameserver_addr_locked(ifname, n); + pthread_mutex_unlock(&_res_cache_list_lock); + return result; +} - pthread_mutex_lock( &_res_cache->lock ); - if (_res_cache->generation != generation) { - _cache_flush_locked(_res_cache); - _res_cache->generation = generation; +static struct addrinfo* +_get_nameserver_addr_locked(const char* ifname, int n) +{ + struct addrinfo* ai = NULL; + struct resolv_cache_info* cache_info; + + if (n < 1 || n > MAXNS) + return NULL; + + cache_info = _find_cache_info_locked(ifname); + if (cache_info) { + ai = cache_info->nsaddrinfo[n - 1]; + } + return ai; +} + +void +_resolv_set_addr_of_iface(const char* ifname, struct in_addr* addr) +{ + pthread_once(&_res_cache_once, _res_cache_init); + pthread_mutex_lock(&_res_cache_list_lock); + struct resolv_cache_info* cache_info = _find_cache_info_locked(ifname); + if (cache_info) { + memcpy(&cache_info->ifaddr, addr, sizeof(*addr)); + + if (DEBUG) { + char* addr_s = inet_ntoa(cache_info->ifaddr); + XLOG("address of interface %s is %s\n", ifname, addr_s); + } + } + pthread_mutex_unlock(&_res_cache_list_lock); +} + +struct in_addr* +_resolv_get_addr_of_default_iface(void) +{ + struct in_addr* ai = NULL; + char* ifname; + + pthread_once(&_res_cache_once, _res_cache_init); + pthread_mutex_lock(&_res_cache_list_lock); + ifname = _get_default_iface_locked(); + ai = _get_addr_locked(ifname); + pthread_mutex_unlock(&_res_cache_list_lock); + + return ai; +} + +struct in_addr* +_resolv_get_addr_of_iface(const char* ifname) +{ + struct in_addr* ai = NULL; + + pthread_once(&_res_cache_once, _res_cache_init); + pthread_mutex_lock(&_res_cache_list_lock); + ai =_get_addr_locked(ifname); + pthread_mutex_unlock(&_res_cache_list_lock); + return ai; +} + +static struct in_addr* +_get_addr_locked(const char * ifname) +{ + struct resolv_cache_info* cache_info = _find_cache_info_locked(ifname); + if (cache_info) { + return &cache_info->ifaddr; } - pthread_mutex_unlock( &_res_cache->lock ); + return NULL; } diff --git a/libc/netbsd/resolv/res_init.c b/libc/netbsd/resolv/res_init.c index 81e570f77..1cdfc534a 100644 --- a/libc/netbsd/resolv/res_init.c +++ b/libc/netbsd/resolv/res_init.c @@ -225,6 +225,9 @@ __res_vinit(res_state statp, int preinit) { char dnsProperty[PROP_VALUE_MAX]; #endif + if ((statp->options & RES_INIT) != 0U) + res_ndestroy(statp); + if (!preinit) { statp->retrans = RES_TIMEOUT; statp->retry = RES_DFLRETRY; @@ -232,9 +235,6 @@ __res_vinit(res_state statp, int preinit) { statp->id = res_randomid(); } - if ((statp->options & RES_INIT) != 0U) - res_ndestroy(statp); - memset(u, 0, sizeof(u)); #ifdef USELOOPBACK u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); diff --git a/libc/netbsd/resolv/res_send.c b/libc/netbsd/resolv/res_send.c index 696f8cfeb..94ba9693f 100644 --- a/libc/netbsd/resolv/res_send.c +++ b/libc/netbsd/resolv/res_send.c @@ -413,7 +413,7 @@ res_nsend(res_state statp, if (EXT(statp).nssocks[ns] == -1) continue; peerlen = sizeof(peer); - if (getsockname(EXT(statp).nssocks[ns], + if (getpeername(EXT(statp).nssocks[ns], (struct sockaddr *)(void *)&peer, &peerlen) < 0) { needclose++; break; diff --git a/libc/netbsd/resolv/res_state.c b/libc/netbsd/resolv/res_state.c index 3a2301d2e..94c62bfc9 100644 --- a/libc/netbsd/resolv/res_state.c +++ b/libc/netbsd/resolv/res_state.c @@ -38,21 +38,32 @@ #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include <sys/_system_properties.h> +/* Set to 1 to enable debug traces */ +#define DEBUG 0 + +#if DEBUG +# include <logd.h> +# include <unistd.h> /* for gettid() */ +# define D(...) __libc_android_log_print(ANDROID_LOG_DEBUG,"libc", __VA_ARGS__) +#else +# define D(...) do{}while(0) +#endif + static pthread_key_t _res_key; static pthread_once_t _res_once; typedef struct { - int _h_errno; - struct __res_state _nres[1]; - unsigned _serial; - struct prop_info* _pi; - struct res_static _rstatic[1]; + int _h_errno; + struct __res_state _nres[1]; + unsigned _serial; + struct prop_info* _pi; + struct res_static _rstatic[1]; } _res_thread; static _res_thread* _res_thread_alloc(void) { - _res_thread* rt = malloc(sizeof(*rt)); + _res_thread* rt = calloc(1, sizeof(*rt)); if (rt) { rt->_h_errno = 0; @@ -62,12 +73,7 @@ _res_thread_alloc(void) if (rt->_pi) { rt->_serial = rt->_pi->serial; } - if ( res_ninit( rt->_nres ) < 0 ) { - free(rt); - rt = NULL; - } else { - memset(rt->_rstatic, 0, sizeof rt->_rstatic); - } + memset(rt->_rstatic, 0, sizeof rt->_rstatic); } return rt; } @@ -91,6 +97,8 @@ _res_thread_free( void* _rt ) { _res_thread* rt = _rt; + D("%s: rt=%p for thread=%d", __FUNCTION__, rt, gettid()); + _res_static_done(rt->_rstatic); res_ndestroy(rt->_nres); free(rt); @@ -108,29 +116,60 @@ _res_thread_get(void) _res_thread* rt; pthread_once( &_res_once, _res_init_key ); rt = pthread_getspecific( _res_key ); - if (rt == NULL) { - if ((rt = _res_thread_alloc()) == NULL) { - return NULL; + + if (rt != NULL) { + /* We already have one thread-specific DNS state object. + * Check the serial value for any changes to net.* properties */ + D("%s: Called for tid=%d rt=%p rt->pi=%p rt->serial=%d", + __FUNCTION__, gettid(), rt, rt->_pi, rt->_serial); + if (rt->_pi == NULL) { + /* The property wasn't created when _res_thread_get() was + * called the last time. This should only happen very + * early during the boot sequence. First, let's try to see if it + * is here now. */ + rt->_pi = (struct prop_info*) __system_property_find("net.change"); + if (rt->_pi == NULL) { + /* Still nothing, return current state */ + D("%s: exiting for tid=%d rt=%d since system property not found", + __FUNCTION__, gettid(), rt); + return rt; + } } - rt->_h_errno = 0; - rt->_serial = 0; - pthread_setspecific( _res_key, rt ); - } - /* Check the serial value for any chanes to net.* properties. */ - if (rt->_pi == NULL) { - rt->_pi = (struct prop_info*) __system_property_find("net.change"); + if (rt->_serial == rt->_pi->serial) { + /* Nothing changed, so return the current state */ + D("%s: tid=%d rt=%p nothing changed, returning", + __FUNCTION__, gettid(), rt); + return rt; + } + /* Update the recorded serial number, and go reset the state */ + rt->_serial = rt->_pi->serial; + goto RESET_STATE; } - if (rt->_pi == NULL || rt->_serial == rt->_pi->serial) { - return rt; + + /* It is the first time this function is called in this thread, + * we need to create a new thread-specific DNS resolver state. */ + rt = _res_thread_alloc(); + if (rt == NULL) { + return NULL; } - rt->_serial = rt->_pi->serial; - /* Reload from system properties. */ + pthread_setspecific( _res_key, rt ); + D("%s: tid=%d Created new DNS state rt=%p", + __FUNCTION__, gettid(), rt); + +RESET_STATE: + /* Reset the state, note that res_ninit() can now properly reset + * an existing state without leaking memory. + */ + D("%s: tid=%d, rt=%p, resetting DNS state (options RES_INIT=%d)", + __FUNCTION__, gettid(), rt, (rt->_nres->options & RES_INIT) != 0); if ( res_ninit( rt->_nres ) < 0 ) { - free(rt); - rt = NULL; - pthread_setspecific( _res_key, rt ); + /* This should not happen */ + D("%s: tid=%d rt=%p, woot, res_ninit() returned < 0", + __FUNCTION__, gettid(), rt); + _res_thread_free(rt); + pthread_setspecific( _res_key, NULL ); + return NULL; } - _resolv_cache_reset(rt->_serial); return rt; } diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h index 008fd2ff7..94a81cd51 100644 --- a/libc/private/bionic_tls.h +++ b/libc/private/bionic_tls.h @@ -111,6 +111,12 @@ extern int __set_tls(void *ptr); * Note that HAVE_ARM_TLS_REGISTER is build-specific * (it must match your kernel configuration) */ +# ifdef HAVE_TEGRA_ERRATA_657451 +# define __munge_tls(_v) ( ((_v)&~((1ul<<20)|1ul)) | (((_v)&0x1)<<20) ) +# else +# define __munge_tls(_v) (_v) +#endif + # ifdef HAVE_ARM_TLS_REGISTER /* We can read the address directly from a coprocessor * register, which avoids touching the data cache @@ -119,6 +125,7 @@ extern int __set_tls(void *ptr); # define __get_tls() \ ({ register unsigned int __val asm("r0"); \ asm ("mrc p15, 0, r0, c13, c0, 3" : "=r"(__val) ); \ + __val = __munge_tls(__val); \ (volatile void*)__val; }) # else /* !HAVE_ARM_TLS_REGISTER */ /* The kernel provides the address of the TLS at a fixed diff --git a/libc/private/resolv_cache.h b/libc/private/resolv_cache.h index cd876fb28..2a5445355 100644 --- a/libc/private/resolv_cache.h +++ b/libc/private/resolv_cache.h @@ -30,13 +30,45 @@ struct resolv_cache; /* forward */ -/* get cache instance, can be NULL if cache is disabled - * (e.g. through an environment variable) */ +/* gets the cache for the default interface. Might be NULL*/ extern struct resolv_cache* __get_res_cache(void); +/* get the cache for a specified interface. Can be NULL*/ +extern struct resolv_cache* __get_res_cache_for_iface(const char* ifname); + /* this gets called everytime we detect some changes in the DNS configuration * and will flush the cache */ -extern void _resolv_cache_reset( unsigned generation ); +extern void _resolv_cache_reset( unsigned generation ); + +/* Gets the address of the n:th name server for the default interface + * Return length of address on success else 0. + * Note: The first name server is at n = 1 */ +extern int _resolv_cache_get_nameserver(int n, char* addr, int addrLen); + +/* Gets the address of the n:th name server for a certain interface + * Return length of address on success else 0. + * Note: The first name server is at n = 1 */ +extern int _resolv_cache_get_nameserver_for_iface(const char* ifname, int n, + char* addr, int addrLen); + +/* Gets addrinfo of the n:th name server associated with an interface. + * NULL is returned if no address if found. + * Note: The first name server is at n = 1. */ +extern struct addrinfo* _resolv_cache_get_nameserver_addr_for_iface(const char* ifname, int n); + +/* Gets addrinfo of the n:th name server associated with the default interface + * NULL is returned if no address if found. + * Note: The first name server is at n = 1. */ +extern struct addrinfo* _resolv_cache_get_nameserver_addr(int n); + +/* gets the address associated with the default interface */ +extern struct in_addr* _resolv_get_addr_of_default_iface(); + +/* gets the address associated with the specified interface */ +extern struct in_addr* _resolv_get_addr_of_iface(const char* ifname); + +/* Get name of default interface */ +extern char* _resolv_get_default_iface(); typedef enum { RESOLV_CACHE_UNSUPPORTED, /* the cache can't handle that kind of queries */ diff --git a/libc/stdio/wcio.h b/libc/stdio/wcio.h index f8ac1b21e..dd6db21a0 100644 --- a/libc/stdio/wcio.h +++ b/libc/stdio/wcio.h @@ -41,7 +41,7 @@ struct wchar_io_data { /* BIONIC: disable wchar support */ #define WCIO_GET(fp) \ - ((struct whcar_io_data*) 0) + ((struct wchar_io_data*) 0) #define _SET_ORIENTATION(fp, mode) ((void)0) diff --git a/libc/string/memmove.c b/libc/string/memmove.c index 98ecfc90b..072104b6c 100644 --- a/libc/string/memmove.c +++ b/libc/string/memmove.c @@ -26,6 +26,7 @@ * SUCH DAMAGE. */ #include <string.h> +#include <strings.h> void *memmove(void *dst, const void *src, size_t n) { @@ -37,39 +38,7 @@ void *memmove(void *dst, const void *src, size_t n) if (__builtin_expect((q < p) || ((size_t)(q - p) >= n), 1)) { return memcpy(dst, src, n); } else { -#define PRELOAD_DISTANCE 64 - /* a semi-optimized memmove(). we're preloading the src and dst buffers - * as we go */ - size_t c0, c1, i; - p += n; - q += n; - /* note: we preload the destination as well, because the 1-byte at a time - * copy below doesn't take advantage of the write-buffer, we need - * to use the cache instead as a poor man's write-combiner */ - __builtin_prefetch(p-1); - __builtin_prefetch(q-1); - if (PRELOAD_DISTANCE > 32) { - __builtin_prefetch(p-(32+1)); - __builtin_prefetch(q-(32+1)); - } - /* do the prefetech as soon as possible, prevent the compiler to - * reorder the instructions above the prefetch */ - asm volatile("":::"memory"); - c0 = n & 0x1F; /* cache-line is 32 bytes */ - c1 = n >> 5; - while ( c1-- ) { - /* ARMv6 can have up to 3 memory access outstanding */ - __builtin_prefetch(p - (PRELOAD_DISTANCE+1)); - __builtin_prefetch(q - (PRELOAD_DISTANCE+1)); - asm volatile("":::"memory"); - for (i=0 ; i<32 ; i++) { - *--q = *--p; - } - } - while ( c0-- ) { - *--q = *--p; - } + bcopy(src, dst, n); + return dst; } - - return dst; } diff --git a/libc/tools/checksyscalls.py b/libc/tools/checksyscalls.py index 9edb39044..f6182f368 100755 --- a/libc/tools/checksyscalls.py +++ b/libc/tools/checksyscalls.py @@ -132,10 +132,10 @@ if not os.path.exists(arm_unistd): # with two distinct unistd_32.h and unistd_64.h definition files. # take care of this here # -x86_unistd = linux_root + "/include/asm-i386/unistd.h" +x86_unistd = linux_root + "/include/asm-i386/unistd_32.h" if not os.path.exists(x86_unistd): x86_unistd1 = x86_unistd - x86_unistd = linux_root + "/include/asm-x86/unistd_32.h" + x86_unistd = linux_root + "/include/asm-x86/unistd.h" if not os.path.exists(x86_unistd): print "WEIRD: could not locate the i386/x86 unistd.h header file" print "tried searching in '%s' and '%s'" % (x86_unistd1, x86_unistd) diff --git a/libc/unistd/exec.c b/libc/unistd/exec.c index cbb98b366..89396ac31 100644 --- a/libc/unistd/exec.c +++ b/libc/unistd/exec.c @@ -194,9 +194,9 @@ execvp(const char *name, char * const *argv) (void)writev(STDERR_FILENO, iov, 3); continue; } - bcopy(p, buf, lp); + memcpy(buf, p, lp); buf[lp] = '/'; - bcopy(name, buf + lp + 1, ln); + memcpy(buf + lp + 1, name, ln); buf[lp + ln + 1] = '\0'; retry: (void)execve(bp, argv, environ); @@ -216,7 +216,7 @@ retry: (void)execve(bp, argv, environ); goto done; memp[0] = "sh"; memp[1] = bp; - bcopy(argv + 1, memp + 2, cnt * sizeof(char *)); + memcpy(memp + 2, argv + 1, cnt * sizeof(char *)); (void)execve(_PATH_BSHELL, memp, environ); goto done; case ENOMEM: diff --git a/libc/unistd/raise.c b/libc/unistd/raise.c index de099da25..d15bcdf96 100644 --- a/libc/unistd/raise.c +++ b/libc/unistd/raise.c @@ -27,8 +27,9 @@ */ #include <unistd.h> #include <signal.h> +#include <pthread.h> int raise(int signum) { - return kill(getpid(), signum); + return pthread_kill(pthread_self(), signum); } |