From 62af3cbd656c7cce57756896f3be18497639c1e1 Mon Sep 17 00:00:00 2001 From: Sparchatus Date: Thu, 31 Mar 2022 20:29:43 +0000 Subject: [PATCH] Bugfixes for serial read rpc. Using kernel sys_getchar for dummy terminal read. Added silly shell to hello.c --- include/aos/aos_rpc.h | 30 ++++++++++++++++++++++++++++++ lib/aos/aos_rpc.c | 8 ++++++-- lib/aos/init.c | 40 +++++++++++++++++++--------------------- lib/spawn/rpc_server.c | 14 +++----------- usr/hello/hello.c | 33 ++++++++++++++++++++++++++++++++- 5 files changed, 90 insertions(+), 35 deletions(-) diff --git a/include/aos/aos_rpc.h b/include/aos/aos_rpc.h index ec74ca4..85cebd3 100644 --- a/include/aos/aos_rpc.h +++ b/include/aos/aos_rpc.h @@ -145,4 +145,34 @@ struct aos_rpc *aos_rpc_get_process_channel(void); */ struct aos_rpc *aos_rpc_get_serial_channel(void); +// MARKER SHELL: remove these temprorary functions +static inline size_t dummy_terminal_write(const char *buf, size_t len) +{ + errval_t err; + + if (len > 0) { + err = sys_print(buf, len); + if (err_is_fail(err)) { + return 0; + } + } + + return len; +} +static inline size_t dummy_terminal_read(char *buf, size_t len) +{ + errval_t err; + + // we need this for now cause sys_getchar is blocking and not even allowing other processes to run + if(len > 1) len = 1; + + for(size_t i = 0; i < len; ++i) { + err = sys_getchar(&buf[i]); + if (err_is_fail(err)) { + return i; + } + } + return len; +} + #endif // _LIB_BARRELFISH_AOS_MESSAGES_H diff --git a/lib/aos/aos_rpc.c b/lib/aos/aos_rpc.c index 7c3d9cf..90e0a71 100644 --- a/lib/aos/aos_rpc.c +++ b/lib/aos/aos_rpc.c @@ -146,8 +146,10 @@ aos_rpc_serial_write(struct aos_rpc *rpc, const char *buf, size_t buf_len) { NULL, NULL, &written_bytes, NULL ); if (err_is_fail(err)) { + DEBUG_ERR(err, "Failed to write the full buffer"); return total_bytes; } + assert(written_bytes <= chunk_len); total_bytes += written_bytes; @@ -176,13 +178,15 @@ aos_rpc_serial_read(struct aos_rpc *rpc, char *buf, size_t buf_len) { size_t read_bytes; err = do_aos_rpc( - rpc, RPC_MTYPE_SERIAL_WRITE, + rpc, RPC_MTYPE_SERIAL_READ, NULL_CAP, 0, chunk_len, 0, - NULL, NULL, &read_bytes, NULL + NULL, &read_bytes, NULL, NULL ); if (err_is_fail(err)) { + DEBUG_ERR(err, "Failed to read the full buffer"); return total_bytes; } + assert(read_bytes <= chunk_len); memcpy(buf, rpc->shared_mem, read_bytes); total_bytes += read_bytes; diff --git a/lib/aos/init.c b/lib/aos/init.c index fe6b17a..6649dc4 100644 --- a/lib/aos/init.c +++ b/lib/aos/init.c @@ -64,24 +64,24 @@ static void libc_assert(const char *expression, const char *file, sys_print(buf, len < sizeof(buf) ? len : sizeof(buf)); } -__attribute__((__used__)) -static size_t syscall_terminal_write(const char *buf, size_t len) -{ - if(len) { - errval_t err = sys_print(buf, len); - if (err_is_fail(err)) { - return 0; - } - } - return len; -} +// __attribute__((__used__)) +// static size_t syscall_terminal_write(const char *buf, size_t len) +// { +// if(len) { +// errval_t err = sys_print(buf, len); +// if (err_is_fail(err)) { +// return 0; +// } +// } +// return len; +// } -__attribute__((__used__)) -static size_t dummy_terminal_read(char *buf, size_t len) -{ - debug_printf("Terminal read NYI!\n"); - return 0; -} +// __attribute__((__used__)) +// static size_t dummy_terminal_read(char *buf, size_t len) +// { +// debug_printf("Terminal read NYI!\n"); +// return 0; +// } static void handle_init_recv(void *arg) { @@ -101,7 +101,6 @@ static void handle_init_recv(void *arg) } } -// TODO rueegges: allow partial write static size_t aos_terminal_write(const char *buf, size_t len) { if(len == 0) return 0; @@ -115,7 +114,6 @@ static size_t aos_terminal_write(const char *buf, size_t len) return aos_rpc_serial_write(rpc, buf, len); } -// TODO rueegges: make more efficient? static size_t aos_terminal_read(char *buf, size_t len) { if(len == 0) return 0; @@ -136,10 +134,10 @@ void barrelfish_libc_glue_init(void) // what we need for that // TODO: change these to use the user-space serial driver if possible // TODO: set these functions - // MARKER SHELL: replace functions for init domain or UART driver with non-remote calls + // MARKER SHELL: init should also print through the UART driver if(init_domain) { _libc_terminal_read_func = dummy_terminal_read; - _libc_terminal_write_func = syscall_terminal_write; + _libc_terminal_write_func = dummy_terminal_write; } else { _libc_terminal_read_func = aos_terminal_read; _libc_terminal_write_func = aos_terminal_write; diff --git a/lib/spawn/rpc_server.c b/lib/spawn/rpc_server.c index b754848..7ec040a 100644 --- a/lib/spawn/rpc_server.c +++ b/lib/spawn/rpc_server.c @@ -146,7 +146,7 @@ static errval_t handle_rpc_serial_getchar( // MARKER SHELL: Replace with UART call *ret0 = getchar(); - return LIB_ERR_NOT_IMPLEMENTED; + return SYS_ERR_OK; } static errval_t handle_rpc_serial_putchar( @@ -170,12 +170,8 @@ static errval_t handle_rpc_serial_write( struct capref *ret_cap, size_t *ret_size, uintptr_t *ret0, uintptr_t *ret1 ) { // MARKER SHELL: Replace with UART call - for (size_t i = 0; i < arg_size; ++i){ - putchar(((char *)rpc->shared_mem)[i]); - } - // return the number of characters written. Important for UART for early return when the buffer is full - *ret0 = arg_size; + *ret0 = dummy_terminal_write((char *)rpc->shared_mem, arg_size); return SYS_ERR_OK; } @@ -186,12 +182,8 @@ static errval_t handle_rpc_serial_read( struct capref *ret_cap, size_t *ret_size, uintptr_t *ret0, uintptr_t *ret1 ) { // MARKER SHELL: Replace with UART call - for (size_t i = 0; i < arg_size; ++i){ - ((char *)rpc->shared_mem)[i] = getchar(); - } - // return the number of characters read. Important for UART for early return when the buffer is empty - *ret0 = arg_size; + *ret_size = dummy_terminal_read((char *)rpc->shared_mem, arg0); return SYS_ERR_OK; } diff --git a/usr/hello/hello.c b/usr/hello/hello.c index 27ac44f..7c54e04 100644 --- a/usr/hello/hello.c +++ b/usr/hello/hello.c @@ -24,6 +24,8 @@ #define HELLO_CATCH_COMMAND "catch" #define HELLO_SPAWN_COMMAND "spawn" +#define HELLO_CMDLINE_READ_LEN 100 + int main(int argc, char *argv[]) { errval_t err; @@ -43,10 +45,39 @@ int main(int argc, char *argv[]) // try to spawn a child using rpc if (argc > 1 && !strncmp(argv[1], HELLO_SPAWN_COMMAND, sizeof(HELLO_SPAWN_COMMAND))) { + debug_printf("Waiting for 1s before showing shell because kernel getchar blocks everything!\n"); + barrelfish_usleep(1000000); + + debug_printf("# "); + // try to read cmdline from the terminal (a very very primitive shell) + char cmdline[HELLO_CMDLINE_READ_LEN+1]; + for(int i = 0; i < HELLO_CMDLINE_READ_LEN; ++i) { + char c = getchar(); + if(c == '\r') { + printf("\n"); + cmdline[i] = '\0'; + break; + } + if(c == 0x7f) { + if (i > 0) { + printf("\b \b"); fflush(stdout); + } + --i; + if(i >= 0) --i; + continue; + } + + cmdline[i] = c; + printf("%c", c); fflush(stdout); + } + cmdline[HELLO_CMDLINE_READ_LEN] = '\0'; + + printf("Got command line: %s\n", cmdline); + // start process domainid_t pid; rpc = aos_rpc_get_process_channel(); - err = aos_rpc_process_spawn(rpc, "hello Aurel Jan Sandro", 0, &pid); + err = aos_rpc_process_spawn(rpc, cmdline, 0, &pid); if (err_is_fail(err)) USER_PANIC_ERR(err, "Failed to spawn process"); printf("Started a new process!\n");