diff options
Diffstat (limited to 'semihosting')
-rw-r--r-- | semihosting/arm-compat-semi.c | 11 | ||||
-rw-r--r-- | semihosting/console.c | 16 |
2 files changed, 21 insertions, 6 deletions
diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c index 40f3730778..fdb143ace8 100644 --- a/semihosting/arm-compat-semi.c +++ b/semihosting/arm-compat-semi.c @@ -428,8 +428,15 @@ void do_common_semihosting(CPUState *cs) break; case TARGET_SYS_READC: - ret = qemu_semihosting_console_inc(cs); - common_semi_set_ret(cs, ret); + { + uint8_t ch; + int ret = qemu_semihosting_console_read(cs, &ch, 1); + if (ret == 1) { + common_semi_cb(cs, ch, 0); + } else { + common_semi_cb(cs, -1, EIO); + } + } break; case TARGET_SYS_ISERROR: diff --git a/semihosting/console.c b/semihosting/console.c index 17ece6bdca..e5ac3f20ba 100644 --- a/semihosting/console.c +++ b/semihosting/console.c @@ -144,12 +144,14 @@ static void console_read(void *opaque, const uint8_t *buf, int size) c->sleeping_cpus = NULL; } -target_ulong qemu_semihosting_console_inc(CPUState *cs) +int qemu_semihosting_console_read(CPUState *cs, void *buf, int len) { - uint8_t ch; SemihostingConsole *c = &console; + int ret = 0; g_assert(qemu_mutex_iothread_locked()); + + /* Block if the fifo is completely empty. */ if (fifo8_is_empty(&c->fifo)) { c->sleeping_cpus = g_slist_prepend(c->sleeping_cpus, cs); cs->halted = 1; @@ -157,8 +159,14 @@ target_ulong qemu_semihosting_console_inc(CPUState *cs) cpu_loop_exit(cs); /* never returns */ } - ch = fifo8_pop(&c->fifo); - return (target_ulong) ch; + + /* Read until buffer full or fifo exhausted. */ + do { + *(char *)(buf + ret) = fifo8_pop(&c->fifo); + ret++; + } while (ret < len && !fifo8_is_empty(&c->fifo)); + + return ret; } void qemu_semihosting_console_init(void) |