From f721e3ac031f892af46f255a47d7f54a91317b30 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 3 Mar 2009 18:28:35 -0800 Subject: auto import from //depot/cupcake/@135843 --- arm-semi.c | 469 ------------------------------------------------------------- 1 file changed, 469 deletions(-) delete mode 100644 arm-semi.c (limited to 'arm-semi.c') diff --git a/arm-semi.c b/arm-semi.c deleted file mode 100644 index cd77d1d..0000000 --- a/arm-semi.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Arm "Angel" semihosting syscalls - * - * Copyright (c) 2005, 2007 CodeSourcery. - * Written by Paul Brook. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "cpu.h" -#ifdef CONFIG_USER_ONLY -#include "qemu.h" - -#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024) -#else -#include "qemu-common.h" -#include "sysemu.h" -#include "gdbstub.h" -#endif - -#define SYS_OPEN 0x01 -#define SYS_CLOSE 0x02 -#define SYS_WRITEC 0x03 -#define SYS_WRITE0 0x04 -#define SYS_WRITE 0x05 -#define SYS_READ 0x06 -#define SYS_READC 0x07 -#define SYS_ISTTY 0x09 -#define SYS_SEEK 0x0a -#define SYS_FLEN 0x0c -#define SYS_TMPNAM 0x0d -#define SYS_REMOVE 0x0e -#define SYS_RENAME 0x0f -#define SYS_CLOCK 0x10 -#define SYS_TIME 0x11 -#define SYS_SYSTEM 0x12 -#define SYS_ERRNO 0x13 -#define SYS_GET_CMDLINE 0x15 -#define SYS_HEAPINFO 0x16 -#define SYS_EXIT 0x18 - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -#define GDB_O_RDONLY 0x000 -#define GDB_O_WRONLY 0x001 -#define GDB_O_RDWR 0x002 -#define GDB_O_APPEND 0x008 -#define GDB_O_CREAT 0x200 -#define GDB_O_TRUNC 0x400 -#define GDB_O_BINARY 0 - -static int gdb_open_modeflags[12] = { - GDB_O_RDONLY, - GDB_O_RDONLY | GDB_O_BINARY, - GDB_O_RDWR, - GDB_O_RDWR | GDB_O_BINARY, - GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC, - GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY, - GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC, - GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY, - GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND, - GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY, - GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND, - GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY -}; - -static int open_modeflags[12] = { - O_RDONLY, - O_RDONLY | O_BINARY, - O_RDWR, - O_RDWR | O_BINARY, - O_WRONLY | O_CREAT | O_TRUNC, - O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, - O_RDWR | O_CREAT | O_TRUNC, - O_RDWR | O_CREAT | O_TRUNC | O_BINARY, - O_WRONLY | O_CREAT | O_APPEND, - O_WRONLY | O_CREAT | O_APPEND | O_BINARY, - O_RDWR | O_CREAT | O_APPEND, - O_RDWR | O_CREAT | O_APPEND | O_BINARY -}; - -#ifdef CONFIG_USER_ONLY -static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code) -{ - if (code == (uint32_t)-1) - ts->swi_errno = errno; - return code; -} -#else -static inline uint32_t set_swi_errno(CPUState *env, uint32_t code) -{ - return code; -} - -#include "softmmu-semi.h" -#endif - -static target_ulong arm_semi_syscall_len; - -#if !defined(CONFIG_USER_ONLY) -static target_ulong syscall_err; -#endif - -static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err) -{ -#ifdef CONFIG_USER_ONLY - TaskState *ts = env->opaque; -#endif - - if (ret == (target_ulong)-1) { -#ifdef CONFIG_USER_ONLY - ts->swi_errno = err; -#else - syscall_err = err; -#endif - env->regs[0] = ret; - } else { - /* Fixup syscalls that use nonstardard return conventions. */ - switch (env->regs[0]) { - case SYS_WRITE: - case SYS_READ: - env->regs[0] = arm_semi_syscall_len - ret; - break; - case SYS_SEEK: - env->regs[0] = 0; - break; - default: - env->regs[0] = ret; - break; - } - } -} - -static void arm_semi_flen_cb(CPUState *env, target_ulong ret, target_ulong err) -{ - /* The size is always stored in big-endian order, extract - the value. We assume the size always fit in 32 bits. */ - uint32_t size; - cpu_memory_rw_debug(env, env->regs[13]-64+32, (uint8_t *)&size, 4, 0); - env->regs[0] = be32_to_cpu(size); -#ifdef CONFIG_USER_ONLY - ((TaskState *)env->opaque)->swi_errno = err; -#else - syscall_err = err; -#endif -} - -#define ARG(n) \ -({ \ - target_ulong __arg; \ - /* FIXME - handle get_user() failure */ \ - get_user_ual(__arg, args + (n) * 4); \ - __arg; \ -}) -#define SET_ARG(n, val) put_user_ual(val, args + (n) * 4) -uint32_t do_arm_semihosting(CPUState *env) -{ - target_ulong args; - char * s; - int nr; - uint32_t ret; - uint32_t len; -#ifdef CONFIG_USER_ONLY - TaskState *ts = env->opaque; -#else - CPUState *ts = env; -#endif - - nr = env->regs[0]; - args = env->regs[1]; - switch (nr) { - case SYS_OPEN: - if (!(s = lock_user_string(ARG(0)))) - /* FIXME - should this error code be -TARGET_EFAULT ? */ - return (uint32_t)-1; - if (ARG(1) >= 12) - return (uint32_t)-1; - if (strcmp(s, ":tt") == 0) { - if (ARG(1) < 4) - return STDIN_FILENO; - else - return STDOUT_FILENO; - } - if (use_gdb_syscalls()) { - gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0), - (int)ARG(2)+1, gdb_open_modeflags[ARG(1)]); - return env->regs[0]; - } else { - ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644)); - } - unlock_user(s, ARG(0), 0); - return ret; - case SYS_CLOSE: - if (use_gdb_syscalls()) { - gdb_do_syscall(arm_semi_cb, "close,%x", ARG(0)); - return env->regs[0]; - } else { - return set_swi_errno(ts, close(ARG(0))); - } - case SYS_WRITEC: - { - char c; - - if (get_user_u8(c, args)) - /* FIXME - should this error code be -TARGET_EFAULT ? */ - return (uint32_t)-1; - /* Write to debug console. stderr is near enough. */ - if (use_gdb_syscalls()) { - gdb_do_syscall(arm_semi_cb, "write,2,%x,1", args); - return env->regs[0]; - } else { - return write(STDERR_FILENO, &c, 1); - } - } - case SYS_WRITE0: - if (!(s = lock_user_string(args))) - /* FIXME - should this error code be -TARGET_EFAULT ? */ - return (uint32_t)-1; - len = strlen(s); - if (use_gdb_syscalls()) { - gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len); - ret = env->regs[0]; - } else { - ret = write(STDERR_FILENO, s, len); - } - unlock_user(s, args, 0); - return ret; - case SYS_WRITE: - len = ARG(2); - if (use_gdb_syscalls()) { - arm_semi_syscall_len = len; - gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", ARG(0), ARG(1), len); - return env->regs[0]; - } else { - if (!(s = lock_user(VERIFY_READ, ARG(1), len, 1))) - /* FIXME - should this error code be -TARGET_EFAULT ? */ - return (uint32_t)-1; - ret = set_swi_errno(ts, write(ARG(0), s, len)); - unlock_user(s, ARG(1), 0); - if (ret == (uint32_t)-1) - return -1; - return len - ret; - } - case SYS_READ: - len = ARG(2); - if (use_gdb_syscalls()) { - arm_semi_syscall_len = len; - gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", ARG(0), ARG(1), len); - return env->regs[0]; - } else { - if (!(s = lock_user(VERIFY_WRITE, ARG(1), len, 0))) - /* FIXME - should this error code be -TARGET_EFAULT ? */ - return (uint32_t)-1; - do - ret = set_swi_errno(ts, read(ARG(0), s, len)); - while (ret == -1 && errno == EINTR); - unlock_user(s, ARG(1), len); - if (ret == (uint32_t)-1) - return -1; - return len - ret; - } - case SYS_READC: - /* XXX: Read from debug cosole. Not implemented. */ - return 0; - case SYS_ISTTY: - if (use_gdb_syscalls()) { - gdb_do_syscall(arm_semi_cb, "isatty,%x", ARG(0)); - return env->regs[0]; - } else { - return isatty(ARG(0)); - } - case SYS_SEEK: - if (use_gdb_syscalls()) { - gdb_do_syscall(arm_semi_cb, "lseek,%x,%x,0", ARG(0), ARG(1)); - return env->regs[0]; - } else { - ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET)); - if (ret == (uint32_t)-1) - return -1; - return 0; - } - case SYS_FLEN: - if (use_gdb_syscalls()) { - gdb_do_syscall(arm_semi_flen_cb, "fstat,%x,%x", - ARG(0), env->regs[13]-64); - return env->regs[0]; - } else { - struct stat buf; - ret = set_swi_errno(ts, fstat(ARG(0), &buf)); - if (ret == (uint32_t)-1) - return -1; - return buf.st_size; - } - case SYS_TMPNAM: - /* XXX: Not implemented. */ - return -1; - case SYS_REMOVE: - if (use_gdb_syscalls()) { - gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1)+1); - ret = env->regs[0]; - } else { - if (!(s = lock_user_string(ARG(0)))) - /* FIXME - should this error code be -TARGET_EFAULT ? */ - return (uint32_t)-1; - ret = set_swi_errno(ts, remove(s)); - unlock_user(s, ARG(0), 0); - } - return ret; - case SYS_RENAME: - if (use_gdb_syscalls()) { - gdb_do_syscall(arm_semi_cb, "rename,%s,%s", - ARG(0), (int)ARG(1)+1, ARG(2), (int)ARG(3)+1); - return env->regs[0]; - } else { - char *s2; - s = lock_user_string(ARG(0)); - s2 = lock_user_string(ARG(2)); - if (!s || !s2) - /* FIXME - should this error code be -TARGET_EFAULT ? */ - ret = (uint32_t)-1; - else - ret = set_swi_errno(ts, rename(s, s2)); - if (s2) - unlock_user(s2, ARG(2), 0); - if (s) - unlock_user(s, ARG(0), 0); - return ret; - } - case SYS_CLOCK: - return clock() / (CLOCKS_PER_SEC / 100); - case SYS_TIME: - return set_swi_errno(ts, time(NULL)); - case SYS_SYSTEM: - if (use_gdb_syscalls()) { - gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1)+1); - return env->regs[0]; - } else { - if (!(s = lock_user_string(ARG(0)))) - /* FIXME - should this error code be -TARGET_EFAULT ? */ - return (uint32_t)-1; - ret = set_swi_errno(ts, system(s)); - unlock_user(s, ARG(0), 0); - return ret; - } - case SYS_ERRNO: -#ifdef CONFIG_USER_ONLY - return ts->swi_errno; -#else - return syscall_err; -#endif - case SYS_GET_CMDLINE: -#ifdef CONFIG_USER_ONLY - /* Build a commandline from the original argv. */ - { - char **arg = ts->info->host_argv; - int len = ARG(1); - /* lock the buffer on the ARM side */ - char *cmdline_buffer = (char*)lock_user(VERIFY_WRITE, ARG(0), len, 0); - - if (!cmdline_buffer) - /* FIXME - should this error code be -TARGET_EFAULT ? */ - return (uint32_t)-1; - - s = cmdline_buffer; - while (*arg && len > 2) { - int n = strlen(*arg); - - if (s != cmdline_buffer) { - *(s++) = ' '; - len--; - } - if (n >= len) - n = len - 1; - memcpy(s, *arg, n); - s += n; - len -= n; - arg++; - } - /* Null terminate the string. */ - *s = 0; - len = s - cmdline_buffer; - - /* Unlock the buffer on the ARM side. */ - unlock_user(cmdline_buffer, ARG(0), len); - - /* Adjust the commandline length argument. */ - SET_ARG(1, len); - - /* Return success if commandline fit into buffer. */ - return *arg ? -1 : 0; - } -#else - return -1; -#endif - case SYS_HEAPINFO: - { - uint32_t *ptr; - uint32_t limit; - -#ifdef CONFIG_USER_ONLY - /* Some C libraries assume the heap immediately follows .bss, so - allocate it using sbrk. */ - if (!ts->heap_limit) { - long ret; - - ts->heap_base = do_brk(0); - limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE; - /* Try a big heap, and reduce the size if that fails. */ - for (;;) { - ret = do_brk(limit); - if (ret != -1) - break; - limit = (ts->heap_base >> 1) + (limit >> 1); - } - ts->heap_limit = limit; - } - - if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0))) - /* FIXME - should this error code be -TARGET_EFAULT ? */ - return (uint32_t)-1; - ptr[0] = tswap32(ts->heap_base); - ptr[1] = tswap32(ts->heap_limit); - ptr[2] = tswap32(ts->stack_base); - ptr[3] = tswap32(0); /* Stack limit. */ - unlock_user(ptr, ARG(0), 16); -#else - limit = ram_size; - if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0))) - /* FIXME - should this error code be -TARGET_EFAULT ? */ - return (uint32_t)-1; - /* TODO: Make this use the limit of the loaded application. */ - ptr[0] = tswap32(limit / 2); - ptr[1] = tswap32(limit); - ptr[2] = tswap32(limit); /* Stack base */ - ptr[3] = tswap32(0); /* Stack limit. */ - unlock_user(ptr, ARG(0), 16); -#endif - return 0; - } - case SYS_EXIT: - exit(0); - default: - fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr); - cpu_dump_state(env, stderr, fprintf, 0); - abort(); - } -} -- cgit v1.1