diff options
Diffstat (limited to 'linux-user/arm-semi.c')
-rw-r--r-- | linux-user/arm-semi.c | 41 |
1 files changed, 24 insertions, 17 deletions
diff --git a/linux-user/arm-semi.c b/linux-user/arm-semi.c index 472361a478..250d5b75cc 100644 --- a/linux-user/arm-semi.c +++ b/linux-user/arm-semi.c @@ -77,20 +77,20 @@ static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code) return code; } -#define ARG(x) tswap32(args[x]) +#define ARG(n) tget32(args + n * 4) uint32_t do_arm_semihosting(CPUState *env) { - uint32_t *args; + target_ulong args; char * s; int nr; uint32_t ret; TaskState *ts = env->opaque; nr = env->regs[0]; - args = (uint32_t *)env->regs[1]; + args = env->regs[1]; switch (nr) { case SYS_OPEN: - s = (char *)ARG(0); + s = (char *)g2h(ARG(0)); if (ARG(1) >= 12) return (uint32_t)-1; if (strcmp(s, ":tt") == 0) { @@ -103,18 +103,23 @@ uint32_t do_arm_semihosting(CPUState *env) case SYS_CLOSE: return set_swi_errno(ts, close(ARG(0))); case SYS_WRITEC: - /* Write to debug console. stderr is near enough. */ - return write(STDERR_FILENO, args, 1); + { + char c = tget8(args); + /* Write to debug console. stderr is near enough. */ + return write(STDERR_FILENO, &c, 1); + } case SYS_WRITE0: - s = (char *)args; - return write(STDERR_FILENO, s, strlen(s)); + s = lock_user_string(args); + ret = write(STDERR_FILENO, s, strlen(s)); + unlock_user(s, args, 0); + return ret; case SYS_WRITE: - ret = set_swi_errno(ts, write(ARG(0), (void *)ARG(1), ARG(2))); + ret = set_swi_errno(ts, write(ARG(0), g2h(ARG(1)), ARG(2))); if (ret == (uint32_t)-1) return -1; return ARG(2) - ret; case SYS_READ: - ret = set_swi_errno(ts, read(ARG(0), (void *)ARG(1), ARG(2))); + ret = set_swi_errno(ts, read(ARG(0), g2h(ARG(1)), ARG(2))); if (ret == (uint32_t)-1) return -1; return ARG(2) - ret; @@ -140,20 +145,21 @@ uint32_t do_arm_semihosting(CPUState *env) /* XXX: Not implemented. */ return -1; case SYS_REMOVE: - return set_swi_errno(ts, remove((char *)ARG(0))); + return set_swi_errno(ts, remove((char *)g2h(ARG(0)))); case SYS_RENAME: - return set_swi_errno(ts, rename((char *)ARG(0), (char *)ARG(2))); + return set_swi_errno(ts, rename((char *)g2h(ARG(0)), + (char *)g2h(ARG(2)))); case SYS_CLOCK: return clock() / (CLOCKS_PER_SEC / 100); case SYS_TIME: return set_swi_errno(ts, time(NULL)); case SYS_SYSTEM: - return set_swi_errno(ts, system((char *)ARG(0))); + return set_swi_errno(ts, system((char *)g2h(ARG(0)))); case SYS_ERRNO: return ts->swi_errno; case SYS_GET_CMDLINE: /* XXX: Not implemented. */ - s = (char *)ARG(0); + s = (char *)g2h(ARG(0)); *s = 0; return -1; case SYS_HEAPINFO: @@ -166,11 +172,11 @@ uint32_t do_arm_semihosting(CPUState *env) if (!ts->heap_limit) { long ret; - ts->heap_base = do_brk(NULL); + ts->heap_base = do_brk(0); limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE; /* Try a big heap, and reduce the size if that fails. */ for (;;) { - ret = do_brk((char *)limit); + ret = do_brk(limit); if (ret != -1) break; limit = (ts->heap_base >> 1) + (limit >> 1); @@ -178,7 +184,8 @@ uint32_t do_arm_semihosting(CPUState *env) ts->heap_limit = limit; } - ptr = (uint32_t *)ARG(0); + page_unprotect_range (ARG(0), 32); + ptr = (uint32_t *)g2h(ARG(0)); ptr[0] = tswap32(ts->heap_base); ptr[1] = tswap32(ts->heap_limit); ptr[2] = tswap32(ts->stack_base); |