diff options
Diffstat (limited to 'semihosting/syscalls.c')
-rw-r--r-- | semihosting/syscalls.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/semihosting/syscalls.c b/semihosting/syscalls.c index d42a190746..5cb12d6adc 100644 --- a/semihosting/syscalls.c +++ b/semihosting/syscalls.c @@ -107,6 +107,13 @@ static void gdb_read(CPUState *cs, gdb_syscall_complete_cb complete, (target_ulong)gf->hostfd, buf, len); } +static void gdb_write(CPUState *cs, gdb_syscall_complete_cb complete, + GuestFD *gf, target_ulong buf, target_ulong len) +{ + gdb_do_syscall(complete, "write,%x,%x,%x", + (target_ulong)gf->hostfd, buf, len); +} + /* * Host semihosting syscall implementations. */ @@ -193,6 +200,22 @@ static void host_read(CPUState *cs, gdb_syscall_complete_cb complete, } } +static void host_write(CPUState *cs, gdb_syscall_complete_cb complete, + GuestFD *gf, target_ulong buf, target_ulong len) +{ + CPUArchState *env G_GNUC_UNUSED = cs->env_ptr; + void *ptr = lock_user(VERIFY_READ, buf, len, 1); + ssize_t ret; + + if (!ptr) { + complete(cs, -1, EFAULT); + return; + } + ret = write(gf->hostfd, ptr, len); + complete(cs, ret, ret == -1 ? errno : 0); + unlock_user(ptr, buf, 0); +} + /* * Static file semihosting syscall implementations. */ @@ -286,3 +309,34 @@ void semihost_sys_read(CPUState *cs, gdb_syscall_complete_cb complete, complete(cs, -1, EBADF); } } + +void semihost_sys_write_gf(CPUState *cs, gdb_syscall_complete_cb complete, + GuestFD *gf, target_ulong buf, target_ulong len) +{ + switch (gf->type) { + case GuestFDGDB: + gdb_write(cs, complete, gf, buf, len); + break; + case GuestFDHost: + host_write(cs, complete, gf, buf, len); + break; + case GuestFDStatic: + /* Static files are never open for writing: EBADF. */ + complete(cs, -1, EBADF); + break; + default: + g_assert_not_reached(); + } +} + +void semihost_sys_write(CPUState *cs, gdb_syscall_complete_cb complete, + int fd, target_ulong buf, target_ulong len) +{ + GuestFD *gf = get_guestfd(fd); + + if (gf) { + semihost_sys_write_gf(cs, complete, gf, buf, len); + } else { + complete(cs, -1, EBADF); + } +} |