On 13:45 Tue 07 Jun , Richard Henderson wrote: > Allow more than one character to be read at one time. > Will be used by m68k and nios2 semihosting for stdio. > > Signed-off-by: Richard Henderson <richard.hender...@linaro.org>
Reviewed-by: Luc Michel <lmic...@kalray.eu> > --- > include/semihosting/console.h | 12 +++++++----- > linux-user/semihost.c | 10 ++++++---- > semihosting/arm-compat-semi.c | 11 +++++++++-- > semihosting/console.c | 16 ++++++++++++---- > 4 files changed, 34 insertions(+), 15 deletions(-) > > diff --git a/include/semihosting/console.h b/include/semihosting/console.h > index 27f8e9ae2e..39dbf1b062 100644 > --- a/include/semihosting/console.h > +++ b/include/semihosting/console.h > @@ -38,19 +38,21 @@ int qemu_semihosting_console_outs(CPUArchState *env, > target_ulong s); > void qemu_semihosting_console_outc(CPUArchState *env, target_ulong c); > > /** > - * qemu_semihosting_console_inc: > + * qemu_semihosting_console_read: > * @cs: CPUState > + * @buf: host buffer > + * @len: buffer size > * > - * Receive single character from debug console. As this call may block > - * if no data is available we suspend the CPU and will re-execute the > + * Receive at least one character from debug console. As this call may > + * block if no data is available we suspend the CPU and will re-execute the > * instruction when data is there. Therefore two conditions must be met: > * > * - CPUState is synchronized before calling this function > * - pc is only updated once the character is successfully returned > * > - * Returns: character read OR cpu_loop_exit! > + * Returns: number of characters read, OR cpu_loop_exit! > */ > -target_ulong qemu_semihosting_console_inc(CPUState *cs); > +int qemu_semihosting_console_read(CPUState *cs, void *buf, int len); > > /** > * qemu_semihosting_log_out: > diff --git a/linux-user/semihost.c b/linux-user/semihost.c > index f14c6ae21d..2029fb674c 100644 > --- a/linux-user/semihost.c > +++ b/linux-user/semihost.c > @@ -56,21 +56,23 @@ void qemu_semihosting_console_outc(CPUArchState *env, > target_ulong addr) > * program is expecting more normal behaviour. This is slow but > * nothing using semihosting console reading is expecting to be fast. > */ > -target_ulong qemu_semihosting_console_inc(CPUState *cs) > +int qemu_semihosting_console_read(CPUState *cs, void *buf, int len) > { > - uint8_t c; > + int ret; > struct termios old_tio, new_tio; > > /* Disable line-buffering and echo */ > tcgetattr(STDIN_FILENO, &old_tio); > new_tio = old_tio; > new_tio.c_lflag &= (~ICANON & ~ECHO); > + new_tio.c_cc[VMIN] = 1; > + new_tio.c_cc[VTIME] = 0; > tcsetattr(STDIN_FILENO, TCSANOW, &new_tio); > > - c = getchar(); > + ret = fread(buf, 1, len, stdin); > > /* restore config */ > tcsetattr(STDIN_FILENO, TCSANOW, &old_tio); > > - return (target_ulong) c; > + return ret; > } > diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c > index e7de52d042..20e99cdcc0 100644 > --- a/semihosting/arm-compat-semi.c > +++ b/semihosting/arm-compat-semi.c > @@ -427,8 +427,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 7b896fe43b..df618a28a4 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) > -- > 2.34.1 > > > > > To declare a filtering error, please use the following link : > https://www.security-mail.net/reporter.php?mid=17c01.629fd5ab.99e5d.0&r=lmichel%40kalrayinc.com&s=qemu-devel-bounces%2Blmichel%3Dkalrayinc.com%40nongnu.org&o=%5BPATCH+v4+43%2F53%5D+semihosting%3A+Expand+qemu_semihosting_console_inc+to+read&verdict=C&c=e9da6e5078994ded7c137213d7c4d1e10afac866 > --