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