aboutsummaryrefslogtreecommitdiff
path: root/semihosting
diff options
context:
space:
mode:
Diffstat (limited to 'semihosting')
-rw-r--r--semihosting/arm-compat-semi.c11
-rw-r--r--semihosting/console.c16
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)