summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShih-wei Liao <sliao@google.com>2012-01-30 18:26:34 -0800
committerShih-wei Liao <sliao@google.com>2012-01-30 22:14:58 -0800
commit9b34649af4b22a1bbc8658d58fbabcbc3ad73c39 (patch)
tree376814d8ddf7bc482c50c46fff9b8a75efe008e1
parent0f8a40e4cfdc5f6cd47c22e81f69ed0446067c54 (diff)
downloadgdk-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.mk43
-rw-r--r--libportable/arch-mips/mmap.c44
-rw-r--r--libportable/arch-mips/open.c35
-rw-r--r--libportable/arch-mips/socket.c20
-rw-r--r--libportable/arch-mips/stat.c96
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;
+}