18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* 28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Arm "Angel" semihosting syscalls 38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2005, 2007 CodeSourcery. 58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Written by Paul Brook. 68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This program is free software; you can redistribute it and/or modify 88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * it under the terms of the GNU General Public License as published by 98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the Free Software Foundation; either version 2 of the License, or 108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (at your option) any later version. 118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This program is distributed in the hope that it will be useful, 138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of 148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * GNU General Public License for more details. 168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * You should have received a copy of the GNU General Public License 18dd9cb7929e2b98bf9f8017ebbd7e433d38541664David 'Digit' Turner * along with this program; if not, see <http://www.gnu.org/licenses/>. 198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */ 208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/types.h> 228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/stat.h> 238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <fcntl.h> 248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <unistd.h> 258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h> 268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdio.h> 278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <time.h> 288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "cpu.h" 308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_USER_ONLY 318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu.h" 328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024) 348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu-common.h" 36852088c7e08182c2de563872d558309815cbfa0dDavid 'Digit' Turner#include "exec/gdbstub.h" 3785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#include "hw/arm/arm.h" 388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 4085125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_OPEN 0x01 4185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_CLOSE 0x02 4285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_WRITEC 0x03 4385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_WRITE0 0x04 4485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_WRITE 0x05 4585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_READ 0x06 4685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_READC 0x07 4785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_ISTTY 0x09 4885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_SEEK 0x0a 4985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_FLEN 0x0c 5085125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_TMPNAM 0x0d 5185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_REMOVE 0x0e 5285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_RENAME 0x0f 5385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_CLOCK 0x10 5485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_TIME 0x11 5585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_SYSTEM 0x12 5685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_ERRNO 0x13 5785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_GET_CMDLINE 0x15 5885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_HEAPINFO 0x16 5985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define TARGET_SYS_EXIT 0x18 608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef O_BINARY 628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define O_BINARY 0 638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GDB_O_RDONLY 0x000 668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GDB_O_WRONLY 0x001 678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GDB_O_RDWR 0x002 688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GDB_O_APPEND 0x008 698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GDB_O_CREAT 0x200 708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GDB_O_TRUNC 0x400 718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define GDB_O_BINARY 0 728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int gdb_open_modeflags[12] = { 748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GDB_O_RDONLY, 758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GDB_O_RDONLY | GDB_O_BINARY, 768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GDB_O_RDWR, 778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GDB_O_RDWR | GDB_O_BINARY, 788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC, 798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY, 808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC, 818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY, 828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND, 838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY, 848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND, 858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY 868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int open_modeflags[12] = { 898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project O_RDONLY, 908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project O_RDONLY | O_BINARY, 918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project O_RDWR, 928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project O_RDWR | O_BINARY, 938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project O_WRONLY | O_CREAT | O_TRUNC, 948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project O_RDWR | O_CREAT | O_TRUNC, 968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project O_WRONLY | O_CREAT | O_APPEND, 988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project O_WRONLY | O_CREAT | O_APPEND | O_BINARY, 998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project O_RDWR | O_CREAT | O_APPEND, 1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project O_RDWR | O_CREAT | O_APPEND | O_BINARY 1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}; 1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_USER_ONLY 1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic inline uint32_t set_swi_errno(TaskState *ts, uint32_t code) 1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (code == (uint32_t)-1) 1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ts->swi_errno = errno; 1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return code; 1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 11185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turnerstatic inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code) 1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return code; 1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 116852088c7e08182c2de563872d558309815cbfa0dDavid 'Digit' Turner#include "exec/softmmu-semi.h" 1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic target_ulong arm_semi_syscall_len; 1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(CONFIG_USER_ONLY) 1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic target_ulong syscall_err; 1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1250b1a84571c04503c5fb1ac012483f03454e2b140David 'Digit' Turnerstatic void arm_semi_cb(CPUState *cpu, target_ulong ret, target_ulong err) 1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1270b1a84571c04503c5fb1ac012483f03454e2b140David 'Digit' Turner CPUARMState *env = cpu->env_ptr; 1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_USER_ONLY 1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TaskState *ts = env->opaque; 1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ret == (target_ulong)-1) { 1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_USER_ONLY 1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ts->swi_errno = err; 1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project syscall_err = err; 1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project env->regs[0] = ret; 1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Fixup syscalls that use nonstardard return conventions. */ 1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (env->regs[0]) { 14285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_WRITE: 14385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_READ: 1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project env->regs[0] = arm_semi_syscall_len - ret; 1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 14685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_SEEK: 1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project env->regs[0] = 0; 1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project env->regs[0] = ret; 1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1560b1a84571c04503c5fb1ac012483f03454e2b140David 'Digit' Turnerstatic void arm_semi_flen_cb(CPUState *cpu, target_ulong ret, target_ulong err) 1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* The size is always stored in big-endian order, extract 1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project the value. We assume the size always fit in 32 bits. */ 1600b1a84571c04503c5fb1ac012483f03454e2b140David 'Digit' Turner CPUARMState *env = cpu->env_ptr; 1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t size; 1620b1a84571c04503c5fb1ac012483f03454e2b140David 'Digit' Turner cpu_memory_rw_debug(cpu, env->regs[13]-64+32, (uint8_t *)&size, 4, 0); 1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project env->regs[0] = be32_to_cpu(size); 1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_USER_ONLY 1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ((TaskState *)env->opaque)->swi_errno = err; 1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project syscall_err = err; 1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 17185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner/* Read the input value from the argument block; fail the semihosting 17285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner * call if the memory read fails. 17385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner */ 17485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#define GET_ARG(n) do { \ 17585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (get_user_ual(arg ## n, args + (n) * 4)) { \ 17685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner return (uint32_t)-1; \ 17785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } \ 17885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner} while (0) 17985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner 1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SET_ARG(n, val) put_user_ual(val, args + (n) * 4) 18185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turneruint32_t do_arm_semihosting(CPUARMState *env) 1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{ 1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project target_ulong args; 18485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner target_ulong arg0, arg1, arg2, arg3; 1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char * s; 1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project int nr; 1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t ret; 1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t len; 1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_USER_ONLY 1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project TaskState *ts = env->opaque; 1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 19285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner CPUARMState *ts = env; 1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project nr = env->regs[0]; 1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project args = env->regs[1]; 1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project switch (nr) { 19885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_OPEN: 19985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(0); 20085125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(1); 20185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(2); 20285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner s = lock_user_string(arg0); 20385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (!s) { 2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FIXME - should this error code be -TARGET_EFAULT ? */ 2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (uint32_t)-1; 20685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } 20785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (arg1 >= 12) { 20885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner unlock_user(s, arg0, 0); 2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (uint32_t)-1; 21085125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } 2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (strcmp(s, ":tt") == 0) { 21285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner int result_fileno = arg1 < 4 ? STDIN_FILENO : STDOUT_FILENO; 21385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner unlock_user(s, arg0, 0); 21485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner return result_fileno; 2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (use_gdb_syscalls()) { 21785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", arg0, 21885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner (int)arg2+1, gdb_open_modeflags[arg1]); 21985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner ret = env->regs[0]; 2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 22185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner ret = set_swi_errno(ts, open(s, open_modeflags[arg1], 0644)); 2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 22385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner unlock_user(s, arg0, 0); 2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ret; 22585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_CLOSE: 22685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(0); 2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (use_gdb_syscalls()) { 22885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner gdb_do_syscall(arm_semi_cb, "close,%x", arg0); 2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return env->regs[0]; 2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 23185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner return set_swi_errno(ts, close(arg0)); 2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 23385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_WRITEC: 2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char c; 2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (get_user_u8(c, args)) 2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FIXME - should this error code be -TARGET_EFAULT ? */ 2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (uint32_t)-1; 2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Write to debug console. stderr is near enough. */ 2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (use_gdb_syscalls()) { 2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gdb_do_syscall(arm_semi_cb, "write,2,%x,1", args); 2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return env->regs[0]; 2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return write(STDERR_FILENO, &c, 1); 2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 24885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_WRITE0: 2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!(s = lock_user_string(args))) 2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FIXME - should this error code be -TARGET_EFAULT ? */ 2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (uint32_t)-1; 2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project len = strlen(s); 2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (use_gdb_syscalls()) { 2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len); 2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = env->regs[0]; 2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = write(STDERR_FILENO, s, len); 2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project unlock_user(s, args, 0); 2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ret; 26185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_WRITE: 26285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(0); 26385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(1); 26485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(2); 26585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner len = arg2; 2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (use_gdb_syscalls()) { 2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project arm_semi_syscall_len = len; 26885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", arg0, arg1, len); 2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return env->regs[0]; 2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 27185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner s = lock_user(VERIFY_READ, arg1, len, 1); 27285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (!s) { 2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FIXME - should this error code be -TARGET_EFAULT ? */ 2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (uint32_t)-1; 27585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } 27685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner ret = set_swi_errno(ts, write(arg0, s, len)); 27785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner unlock_user(s, arg1, 0); 2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ret == (uint32_t)-1) 2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return len - ret; 2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 28285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_READ: 28385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(0); 28485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(1); 28585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(2); 28685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner len = arg2; 2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (use_gdb_syscalls()) { 2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project arm_semi_syscall_len = len; 28985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", arg0, arg1, len); 2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return env->regs[0]; 2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 29285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner s = lock_user(VERIFY_WRITE, arg1, len, 0); 29385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (!s) { 2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FIXME - should this error code be -TARGET_EFAULT ? */ 2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (uint32_t)-1; 29685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } 29785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner do { 29885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner ret = set_swi_errno(ts, read(arg0, s, len)); 29985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } while (ret == -1 && errno == EINTR); 30085125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner unlock_user(s, arg1, len); 3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ret == (uint32_t)-1) 3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return len - ret; 3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 30585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_READC: 30685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner /* XXX: Read from debug console. Not implemented. */ 3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 30885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_ISTTY: 30985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(0); 3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (use_gdb_syscalls()) { 31185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner gdb_do_syscall(arm_semi_cb, "isatty,%x", arg0); 3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return env->regs[0]; 3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 31485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner return isatty(arg0); 3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 31685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_SEEK: 31785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(0); 31885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(1); 3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (use_gdb_syscalls()) { 32085125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner gdb_do_syscall(arm_semi_cb, "lseek,%x,%x,0", arg0, arg1); 3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return env->regs[0]; 3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 32385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner ret = set_swi_errno(ts, lseek(arg0, arg1, SEEK_SET)); 3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ret == (uint32_t)-1) 3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 32885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_FLEN: 32985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(0); 3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (use_gdb_syscalls()) { 3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gdb_do_syscall(arm_semi_flen_cb, "fstat,%x,%x", 33285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner arg0, env->regs[13]-64); 3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return env->regs[0]; 3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project struct stat buf; 33685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner ret = set_swi_errno(ts, fstat(arg0, &buf)); 3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (ret == (uint32_t)-1) 3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return buf.st_size; 3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 34185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_TMPNAM: 3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* XXX: Not implemented. */ 3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return -1; 34485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_REMOVE: 34585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(0); 34685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(1); 3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (use_gdb_syscalls()) { 34885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner gdb_do_syscall(arm_semi_cb, "unlink,%s", arg0, (int)arg1+1); 3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = env->regs[0]; 3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 35185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner s = lock_user_string(arg0); 35285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (!s) { 3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FIXME - should this error code be -TARGET_EFAULT ? */ 3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (uint32_t)-1; 35585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } 3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = set_swi_errno(ts, remove(s)); 35785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner unlock_user(s, arg0, 0); 3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ret; 36085125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_RENAME: 36185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(0); 36285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(1); 36385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(2); 36485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(3); 3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (use_gdb_syscalls()) { 3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project gdb_do_syscall(arm_semi_cb, "rename,%s,%s", 36785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner arg0, (int)arg1+1, arg2, (int)arg3+1); 3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return env->regs[0]; 3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project char *s2; 37185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner s = lock_user_string(arg0); 37285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner s2 = lock_user_string(arg2); 3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!s || !s2) 3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FIXME - should this error code be -TARGET_EFAULT ? */ 3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = (uint32_t)-1; 3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project else 3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = set_swi_errno(ts, rename(s, s2)); 3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s2) 37985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner unlock_user(s2, arg2, 0); 3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (s) 38185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner unlock_user(s, arg0, 0); 3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ret; 3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 38485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_CLOCK: 3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return clock() / (CLOCKS_PER_SEC / 100); 38685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_TIME: 3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return set_swi_errno(ts, time(NULL)); 38885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_SYSTEM: 38985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(0); 39085125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(1); 3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (use_gdb_syscalls()) { 39285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner gdb_do_syscall(arm_semi_cb, "system,%s", arg0, (int)arg1+1); 3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return env->regs[0]; 3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } else { 39585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner s = lock_user_string(arg0); 39685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (!s) { 3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FIXME - should this error code be -TARGET_EFAULT ? */ 3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (uint32_t)-1; 39985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } 4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = set_swi_errno(ts, system(s)); 40185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner unlock_user(s, arg0, 0); 4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ret; 4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 40485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_ERRNO: 4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_USER_ONLY 4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return ts->swi_errno; 4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return syscall_err; 4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 41085125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_GET_CMDLINE: 4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 41285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner /* Build a command-line from the original argv. 41385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner * 41485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner * The inputs are: 41585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner * * arg0, pointer to a buffer of at least the size 41685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner * specified in arg1. 41785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner * * arg1, size of the buffer pointed to by arg0 in 41885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner * bytes. 41985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner * 42085125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner * The outputs are: 42185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner * * arg0, pointer to null-terminated string of the 42285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner * command line. 42385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner * * arg1, length of the string pointed to by arg0. 42485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner */ 4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 42685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner char *output_buffer; 42785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner size_t input_size; 42885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner size_t output_size; 42985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner int status = 0; 43085125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(0); 43185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(1); 43285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner input_size = arg1; 43385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner /* Compute the size of the output string. */ 43485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#if !defined(CONFIG_USER_ONLY) 43585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner output_size = strlen(ts->boot_info->kernel_filename) 43685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner + 1 /* Separating space. */ 43785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner + strlen(ts->boot_info->kernel_cmdline) 43885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner + 1; /* Terminating null byte. */ 43985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#else 44039373b13009fd2c2d13b6804c3e2d146d1e11afaDavid 'Digit' Turner unsigned int i; 44139373b13009fd2c2d13b6804c3e2d146d1e11afaDavid 'Digit' Turner 44285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner output_size = ts->info->arg_end - ts->info->arg_start; 44385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (!output_size) { 44439373b13009fd2c2d13b6804c3e2d146d1e11afaDavid 'Digit' Turner /* We special-case the "empty command line" case (argc==0). 44539373b13009fd2c2d13b6804c3e2d146d1e11afaDavid 'Digit' Turner Just provide the terminating 0. */ 44685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner output_size = 1; 44785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } 44885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#endif 4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 45085125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (output_size > input_size) { 45185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner /* Not enough space to store command-line arguments. */ 45285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner return -1; 4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 45585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner /* Adjust the command-line length. */ 45685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (SET_ARG(1, output_size - 1)) { 45785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner /* Couldn't write back to argument block */ 45885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner return -1; 45985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } 4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 46185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner /* Lock the buffer on the ARM side. */ 46285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner output_buffer = lock_user(VERIFY_WRITE, arg0, output_size, 0); 46385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (!output_buffer) { 46485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner return -1; 46585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } 4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 46785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner /* Copy the command-line arguments. */ 46885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#if !defined(CONFIG_USER_ONLY) 46985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner pstrcpy(output_buffer, output_size, ts->boot_info->kernel_filename); 47085125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner pstrcat(output_buffer, output_size, " "); 47185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner pstrcat(output_buffer, output_size, ts->boot_info->kernel_cmdline); 47285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#else 47385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (output_size == 1) { 47485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner /* Empty command-line. */ 47585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner output_buffer[0] = '\0'; 47685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner goto out; 47785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } 47839373b13009fd2c2d13b6804c3e2d146d1e11afaDavid 'Digit' Turner 47985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (copy_from_user(output_buffer, ts->info->arg_start, 48085125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner output_size)) { 48185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner status = -1; 48285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner goto out; 48339373b13009fd2c2d13b6804c3e2d146d1e11afaDavid 'Digit' Turner } 48439373b13009fd2c2d13b6804c3e2d146d1e11afaDavid 'Digit' Turner 48585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner /* Separate arguments by white spaces. */ 48685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner for (i = 0; i < output_size - 1; i++) { 48785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (output_buffer[i] == 0) { 48885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner output_buffer[i] = ' '; 48985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } 49085125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } 49185125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner out: 49285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner#endif 49385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner /* Unlock the buffer on the ARM side. */ 49485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner unlock_user(output_buffer, arg0, output_size); 49539373b13009fd2c2d13b6804c3e2d146d1e11afaDavid 'Digit' Turner 49685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner return status; 4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 49885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_HEAPINFO: 4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project { 5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t *ptr; 5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project uint32_t limit; 50285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner GET_ARG(0); 5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef CONFIG_USER_ONLY 5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Some C libraries assume the heap immediately follows .bss, so 5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project allocate it using sbrk. */ 5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project if (!ts->heap_limit) { 50885125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner abi_ulong ret; 5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ts->heap_base = do_brk(0); 5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE; 5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* Try a big heap, and reduce the size if that fails. */ 5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project for (;;) { 5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ret = do_brk(limit); 51585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (ret >= limit) { 5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project break; 51785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } 5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project limit = (ts->heap_base >> 1) + (limit >> 1); 5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ts->heap_limit = limit; 5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 52385125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner ptr = lock_user(VERIFY_WRITE, arg0, 16, 0); 52485125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (!ptr) { 5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FIXME - should this error code be -TARGET_EFAULT ? */ 5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (uint32_t)-1; 52785125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } 5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ptr[0] = tswap32(ts->heap_base); 5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ptr[1] = tswap32(ts->heap_limit); 5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ptr[2] = tswap32(ts->stack_base); 5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ptr[3] = tswap32(0); /* Stack limit. */ 53285125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner unlock_user(ptr, arg0, 16); 5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else 5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project limit = ram_size; 53585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner ptr = lock_user(VERIFY_WRITE, arg0, 16, 0); 53685125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner if (!ptr) { 5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* FIXME - should this error code be -TARGET_EFAULT ? */ 5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return (uint32_t)-1; 53985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner } 5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project /* TODO: Make this use the limit of the loaded application. */ 5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ptr[0] = tswap32(limit / 2); 5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ptr[1] = tswap32(limit); 5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ptr[2] = tswap32(limit); /* Stack base */ 5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project ptr[3] = tswap32(0); /* Stack limit. */ 54585125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner unlock_user(ptr, arg0, 16); 5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif 5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project return 0; 5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 54985125480c07e11d5dd98f69b71bded86ee903075David 'Digit' Turner case TARGET_SYS_EXIT: 5503b290c31efd96e5474f2b55b7fe1ca0250a5bb47David Turner //gdb_exit(env, 0); 5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project exit(0); 5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project default: 5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr); 554bf7a22f3a6c38d359d2e933dec4706d1c7375f0aDavid 'Digit' Turner cpu_dump_state(ENV_GET_CPU(env), stderr, fprintf, 0); 5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project abort(); 5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project } 5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} 558