diff options
author | Shih-wei Liao <sliao@google.com> | 2012-01-30 18:26:34 -0800 |
---|---|---|
committer | Shih-wei Liao <sliao@google.com> | 2012-01-30 22:14:58 -0800 |
commit | 9b34649af4b22a1bbc8658d58fbabcbc3ad73c39 (patch) | |
tree | 376814d8ddf7bc482c50c46fff9b8a75efe008e1 | |
parent | 0f8a40e4cfdc5f6cd47c22e81f69ed0446067c54 (diff) | |
download | gdk-9b34649af4b22a1bbc8658d58fbabcbc3ad73c39.tar.gz |
Add libportable that allows Quake to run with the same headers.
This SHIM layer allows the same APK to be downloaded to MIPS, ARM and
x86 and run.
Change-Id: I30fab6837cca57705e05cfb1a051515ee908653a
Author: Luse Cheng <luse.cheng@gmail.com>
-rw-r--r-- | libportable/Android.mk | 43 | ||||
-rw-r--r-- | libportable/arch-mips/mmap.c | 44 | ||||
-rw-r--r-- | libportable/arch-mips/open.c | 35 | ||||
-rw-r--r-- | libportable/arch-mips/socket.c | 20 | ||||
-rw-r--r-- | libportable/arch-mips/stat.c | 96 |
5 files changed, 238 insertions, 0 deletions
diff --git a/libportable/Android.mk b/libportable/Android.mk new file mode 100644 index 0000000..507b3df --- /dev/null +++ b/libportable/Android.mk @@ -0,0 +1,43 @@ +# +# Copyright (C) 2012 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(call my-dir) + +#===================================================================== +# Device Shared Library libportable +#===================================================================== + +include $(CLEAR_VARS) + +LOCAL_MODULE := libportable +LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_CLASS := SHARED_LIBRARIES + +LOCAL_CFLAGS := + +ifeq ($(TARGET_ARCH),mips) +libportable_arch_src_files += arch-mips/mmap.c \ + arch-mips/stat.c \ + arch-mips/open.c \ + arch-mips/socket.c +endif + +LOCAL_SRC_FILES := \ + $(libportable_common_src_files) \ + $(libportable_arch_src_files) + +include $(BUILD_SHARED_LIBRARY) + diff --git a/libportable/arch-mips/mmap.c b/libportable/arch-mips/mmap.c new file mode 100644 index 0000000..6b23549 --- /dev/null +++ b/libportable/arch-mips/mmap.c @@ -0,0 +1,44 @@ + +#include <unistd.h> +#include <stdio.h> +#include <errno.h> +#include <sys/mman.h> + +/* May integate into one header file */ +#define MAP_ANONYMOUS_PORTABLE 0x20 +#define PROT_SEM_PORTABLE 0x8 + +extern void* __mmap2(void*, size_t, int, int, int, size_t); + +static inline int mips_change_prot(int prot) +{ + if (prot & PROT_SEM_PORTABLE) { + prot &= ~PROT_SEM_PORTABLE; + prot |= PROT_SEM; + } + + return prot; +} + +static inline int mips_change_flags(int flags) +{ + if (flags & MAP_ANONYMOUS_PORTABLE) { + flags &= ~MAP_ANONYMOUS_PORTABLE; + flags |= MAP_ANONYMOUS; + } + + return flags; +} + +#define MMAP2_SHIFT 12 +void* mmap( void* addr, size_t size, int prot, int flags, int fd, long offset ) +{ + if ( offset & ((1UL << MMAP2_SHIFT)-1) ) { + errno = EINVAL; + return MAP_FAILED; + } + + prot = mips_change_prot(prot); + flags = mips_change_flags(flags); + return __mmap2(addr, size, prot, flags, fd, (size_t)offset >> MMAP2_SHIFT); +} diff --git a/libportable/arch-mips/open.c b/libportable/arch-mips/open.c new file mode 100644 index 0000000..50c4adc --- /dev/null +++ b/libportable/arch-mips/open.c @@ -0,0 +1,35 @@ + +#include <unistd.h> +#include <fcntl.h> +#include <stdarg.h> + +extern int __open(const char*, int, int); +#define O_CREAT_PORTABLE 00000100 + +static inline int mips_change_flags(int flags) +{ + if (flags & O_CREAT_PORTABLE) { + flags &= ~O_CREAT_PORTABLE; + flags |= O_CREAT; + } + return flags; +} + +int open(const char *pathname, int flags, ...) +{ + mode_t mode = 0; + flags = mips_change_flags(flags); + flags |= O_LARGEFILE; + + if (flags & O_CREAT) + { + va_list args; + + va_start(args, flags); + mode = (mode_t) va_arg(args, int); + va_end(args); + } + + return __open(pathname, flags, mode); +} + diff --git a/libportable/arch-mips/socket.c b/libportable/arch-mips/socket.c new file mode 100644 index 0000000..d7cb110 --- /dev/null +++ b/libportable/arch-mips/socket.c @@ -0,0 +1,20 @@ + +#include <unistd.h> +#include <sys/socket.h> +#include <sys/linux-syscalls.h> + +static inline int mips_change_type(int type) +{ + switch (type) { + case SOCK_DGRAM: return 2; + case SOCK_STREAM: return 1; + } + return type; +} + +extern int socket(int, int, int); +int socket_portable(int domain, int type, int protocol) +{ + return socket(domain,mips_change_type(type),protocol); +} + diff --git a/libportable/arch-mips/stat.c b/libportable/arch-mips/stat.c new file mode 100644 index 0000000..e214f67 --- /dev/null +++ b/libportable/arch-mips/stat.c @@ -0,0 +1,96 @@ +#include <sys/stat.h> + +/* It's easy to change kernel to support stat */ + +struct stat_portable { + unsigned long long st_dev; + unsigned char __pad0[4]; + + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + unsigned long long st_rdev; + unsigned char __pad3[4]; + + long long st_size; + unsigned long st_blksize; + unsigned long long st_blocks; + + unsigned long st_atime; + unsigned long st_atime_nsec; + + unsigned long st_mtime; + unsigned long st_mtime_nsec; + + unsigned long st_ctime; + unsigned long st_ctime_nsec; + + unsigned long long st_ino; +}; + +/* +The MIPS Version is +struct stat { + unsigned long st_dev; + unsigned long __pad0[3]; + + unsigned long long st_ino; + + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + unsigned long st_rdev; + unsigned long __pad1[3]; + + long long st_size; + + unsigned long st_atime; + unsigned long st_atime_nsec; + + unsigned long st_mtime; + unsigned long st_mtime_nsec; + + unsigned long st_ctime; + unsigned long st_ctime_nsec; + + unsigned long st_blksize; + unsigned long __pad2; + + unsigned long long st_blocks; +}; +*/ + +/* Real Stat Syscall */ +extern int stat(const char *, struct stat *); + +/* Note: The Portable Header will define stat to stat_portable */ +int stat_portable(const char *path, struct stat_portable *s) +{ + struct stat mips_stat; + int ret = stat(path,&mips_stat); + s->st_dev = mips_stat.st_dev; + s->__st_ino = mips_stat.st_ino; + s->st_mode = mips_stat.st_mode; + s->st_nlink = mips_stat.st_nlink; + s->st_uid = mips_stat.st_uid; + s->st_gid = mips_stat.st_gid; + s->st_rdev = mips_stat.st_rdev; + s->st_size = mips_stat.st_size; + s->st_blksize = mips_stat.st_blksize; + s->st_blocks = mips_stat.st_blocks; + s->st_atime = mips_stat.st_atime; + s->st_atime_nsec = mips_stat.st_atime_nsec; + s->st_mtime = mips_stat.st_mtime; + s->st_mtime_nsec = mips_stat.st_mtime_nsec; + s->st_ctime = mips_stat.st_ctime; + s->st_ctime_nsec = mips_stat.st_ctime_nsec; + s->st_ino = mips_stat.st_ino; + return ret; +} |