From 452624e1a68b5835df294c278a9c0bdd35f51acb Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Mon, 18 Mar 2013 14:50:32 +0100 Subject: [PATCH] Fiasco(.OC) KDB UART driver The KDB UART driver uses the Fiasco(.OC) kernel debugger console as backend for input and output. This is useful in the case that only one UART is available. Fixes #665. --- base-fiasco/run/env | 6 +- base-foc/run/env | 9 +- os/run/kdb_uart_drv.run | 89 +++++++++++++++++ os/src/drivers/uart/kdb/fiasco/target.mk | 3 + os/src/drivers/uart/kdb/foc/target.mk | 3 + os/src/drivers/uart/kdb/kdb_uart.h | 118 +++++++++++++++++++++++ os/src/drivers/uart/kdb/main.cc | 70 ++++++++++++++ os/src/drivers/uart/kdb/target.inc | 7 ++ os/src/drivers/uart/uart_component.h | 7 +- os/src/test/terminal_echo/main.cc | 8 +- 10 files changed, 314 insertions(+), 6 deletions(-) create mode 100644 os/run/kdb_uart_drv.run create mode 100644 os/src/drivers/uart/kdb/fiasco/target.mk create mode 100644 os/src/drivers/uart/kdb/foc/target.mk create mode 100644 os/src/drivers/uart/kdb/kdb_uart.h create mode 100644 os/src/drivers/uart/kdb/main.cc create mode 100644 os/src/drivers/uart/kdb/target.inc diff --git a/base-fiasco/run/env b/base-fiasco/run/env index d5fe1ad29..82c4045c8 100644 --- a/base-fiasco/run/env +++ b/base-fiasco/run/env @@ -76,8 +76,12 @@ proc bin_dir { } { exit 1 } +set fiasco_serial_esc_arg "-serial_esc " + proc build_boot_image {binaries} { + global fiasco_serial_esc_arg + # # Collect contents of the ISO image # @@ -108,7 +112,7 @@ proc build_boot_image {binaries} { puts $fh "default 0" puts $fh "\ntitle Genode on L4/Fiasco" puts $fh " kernel /fiasco/bootstrap -serial -modaddr=0x02000000" - puts $fh " module /fiasco/fiasco -serial -serial_esc -jdb_cmd=JH" + puts $fh " module /fiasco/fiasco -serial -jdb_cmd=JH $fiasco_serial_esc_arg" puts $fh " module /fiasco/sigma0" puts $fh " module /genode/core" puts $fh " module /genode/config" diff --git a/base-foc/run/env b/base-foc/run/env index 8c774593d..31b288647 100644 --- a/base-foc/run/env +++ b/base-foc/run/env @@ -136,9 +136,12 @@ proc build_boot_uimage { } { } } +set fiasco_serial_esc_arg "-serial_esc " proc build_boot_image_x86 {binaries} { + global fiasco_serial_esc_arg + copy_and_strip_binaries $binaries set foc_targets { } @@ -171,7 +174,7 @@ proc build_boot_image_x86 {binaries} { puts $fh "default 0" puts $fh "\ntitle Genode on Fiasco.OC" puts $fh " kernel /fiasco/bootstrap -modaddr=0x01100000" - puts $fh " module /fiasco/fiasco -serial_esc" + puts $fh " module /fiasco/fiasco $fiasco_serial_esc_arg" puts $fh " module /fiasco/sigma0" puts $fh " module /genode/core" puts $fh " module /genode/config" @@ -187,6 +190,8 @@ proc build_boot_image_x86 {binaries} { proc build_boot_image_arm {binaries} { + global fiasco_serial_esc_arg + copy_and_strip_binaries $binaries build "kernel sigma0 bootstrap" @@ -198,7 +203,7 @@ proc build_boot_image_arm {binaries} { puts $fh "modaddr 0x01100000\n" puts $fh "entry genode" - puts $fh "kernel [fiasco] -serial_esc" + puts $fh "kernel [fiasco] $fiasco_serial_esc_arg" puts $fh "roottask genode/core" puts $fh "module genode/config" foreach binary $binaries { diff --git a/os/run/kdb_uart_drv.run b/os/run/kdb_uart_drv.run new file mode 100644 index 000000000..44cf37b12 --- /dev/null +++ b/os/run/kdb_uart_drv.run @@ -0,0 +1,89 @@ +# +# \brief Test for the KDB UART driver +# \author Christian Prochaska +# \date 2013-01-21 +# + +if {![have_spec foc] && ![have_spec fiasco]} { + puts "Run script only supports Fiasco/Fiasco.OC."; exit 0 } + +# +# Build +# + +build { + core init + drivers/timer + drivers/uart + test/terminal_echo +} + +create_boot_directory + +# +# Generate config +# + +set config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +install_config $config + +# +# Boot modules +# + +# generic modules +set boot_modules { + core init timer + kdb_uart_drv + test-terminal_echo +} + +set fiasco_serial_esc_arg "" + +build_boot_image $boot_modules + +# +# Execute test +# + +# qemu config +append qemu_args " -m 128 -nographic " + +run_genode_until forever diff --git a/os/src/drivers/uart/kdb/fiasco/target.mk b/os/src/drivers/uart/kdb/fiasco/target.mk new file mode 100644 index 000000000..661b91574 --- /dev/null +++ b/os/src/drivers/uart/kdb/fiasco/target.mk @@ -0,0 +1,3 @@ +REQUIRES = fiasco + +include $(PRG_DIR)/../target.inc diff --git a/os/src/drivers/uart/kdb/foc/target.mk b/os/src/drivers/uart/kdb/foc/target.mk new file mode 100644 index 000000000..bbd2f3a61 --- /dev/null +++ b/os/src/drivers/uart/kdb/foc/target.mk @@ -0,0 +1,3 @@ +REQUIRES = foc + +include $(PRG_DIR)/../target.inc diff --git a/os/src/drivers/uart/kdb/kdb_uart.h b/os/src/drivers/uart/kdb/kdb_uart.h new file mode 100644 index 000000000..1a32a4ef4 --- /dev/null +++ b/os/src/drivers/uart/kdb/kdb_uart.h @@ -0,0 +1,118 @@ +/* + * \brief Fiasco(.OC) KDB UART driver + * \author Christian Prochaska + * \date 2013-03-07 + */ + +/* + * Copyright (C) 2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _KDB_UART_H_ +#define _KDB_UART_H_ + +/* Fiasco.OC includes */ +namespace Fiasco { +#include +} + +/* Genode includes */ +#include +#include + +/* local includes */ +#include "uart_driver.h" + +using namespace Genode; + + +class Kdb_uart : public Uart::Driver +{ + private: + + signed char _buffered_char; + Lock _kdb_read_lock; + + enum { STACK_SIZE = 2*1024*sizeof(addr_t) }; + + class Char_avail_checker_thread : public Thread + { + private: + + Uart::Driver &_uart_driver; + Uart::Char_avail_callback &_char_avail_callback; + + public: + + Char_avail_checker_thread(Uart::Driver &uart_driver, + Uart::Char_avail_callback &char_avail_callback) + : _uart_driver(uart_driver), + _char_avail_callback(char_avail_callback) { } + + void entry() + { + Timer::Connection timer; + + for(;;) { + if (_uart_driver.char_avail()) + _char_avail_callback(); + else + timer.msleep(20); + } + } + + } _char_avail_checker_thread; + + public: + + /** + * Constructor + */ + Kdb_uart(Uart::Char_avail_callback &callback) + : _buffered_char(-1), + _char_avail_checker_thread(*this, callback) + { + _char_avail_checker_thread.start(); + } + + /*************************** + ** UART driver interface ** + ***************************/ + + void put_char(char c) + { + Fiasco::outchar(c); + } + + bool char_avail() + { + Lock_guard kdb_read_lock_guard(_kdb_read_lock); + + if (_buffered_char == -1) + _buffered_char = Fiasco::l4kd_inchar(); + + return (_buffered_char != -1); + } + + char get_char() + { + char result; + + if (_buffered_char != -1) { + result = _buffered_char; + _buffered_char = -1; + } else + result = 0; + + return result; + } + + void baud_rate(int bits_per_second) + { + } +}; + +#endif /* _KDB_UART_H_ */ diff --git a/os/src/drivers/uart/kdb/main.cc b/os/src/drivers/uart/kdb/main.cc new file mode 100644 index 000000000..05a48f70f --- /dev/null +++ b/os/src/drivers/uart/kdb/main.cc @@ -0,0 +1,70 @@ +/* + * \brief Fiasco(.OC) KDB UART driver + * \author Christian Prochaska + * \date 2013-03-07 + */ + +/* + * Copyright (C) 2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#include +#include + +#include + +#include "uart_component.h" + +#include "kdb_uart.h" + + +int main(int argc, char **argv) +{ + using namespace Genode; + + printf("--- Fiasco(.OC) KDB UART driver started ---\n"); + + /** + * Factory used by 'Uart::Root' at session creation/destruction time + */ + struct Kdb_uart_driver_factory : Uart::Driver_factory + { + Kdb_uart *uart; + + /** + * Constructor + */ + Kdb_uart_driver_factory() : uart(0) { } + + Uart::Driver *create(unsigned index, unsigned baudrate, + Uart::Char_avail_callback &callback) + { + /* + * We assume the underlying kernel uses UART0 + */ + if (index > 0) + throw Uart::Driver_factory::Not_available(); + + if (!uart) + uart = new (env()->heap()) Kdb_uart(callback); + + return uart; + } + + void destroy(Uart::Driver *driver) { /* TODO */ } + + } driver_factory; + + enum { STACK_SIZE = 2*1024*sizeof(addr_t) }; + static Cap_connection cap; + static Rpc_entrypoint ep(&cap, STACK_SIZE, "uart_ep"); + + static Uart::Root uart_root(&ep, env()->heap(), driver_factory); + env()->parent()->announce(ep.manage(&uart_root)); + + sleep_forever(); + return 0; +} diff --git a/os/src/drivers/uart/kdb/target.inc b/os/src/drivers/uart/kdb/target.inc new file mode 100644 index 000000000..398fb9529 --- /dev/null +++ b/os/src/drivers/uart/kdb/target.inc @@ -0,0 +1,7 @@ +TARGET = kdb_uart_drv +SRC_CC = main.cc +LIBS = base + +INC_DIR += $(PRG_DIR)/.. $(PRG_DIR)/../.. + +vpath main.cc $(PRG_DIR)/.. diff --git a/os/src/drivers/uart/uart_component.h b/os/src/drivers/uart/uart_component.h index 38be48075..191c59b74 100644 --- a/os/src/drivers/uart/uart_component.h +++ b/os/src/drivers/uart/uart_component.h @@ -98,8 +98,11 @@ namespace Uart { */ Size _detect_size() { - /* set cursor position to the max */ - _put_string("\033[1;199r\033[199;199H"); + /* + * Set cursor position to (hopefully) exceed the terminal + * dimensions. + */ + _put_string("\033[1;199r\033[199;255H"); /* flush incoming characters */ for (; _driver.char_avail(); _driver.get_char()); diff --git a/os/src/test/terminal_echo/main.cc b/os/src/test/terminal_echo/main.cc index 9f4e30d48..9104be234 100644 --- a/os/src/test/terminal_echo/main.cc +++ b/os/src/test/terminal_echo/main.cc @@ -17,6 +17,8 @@ using namespace Genode; +static const bool verbose = false; + int main(int, char **) { static Terminal::Connection terminal; @@ -29,13 +31,17 @@ int main(int, char **) terminal.read_avail_sigh(sig_rec.manage(&sig_ctx)); + static const char *intro_text = + "--- Terminal echo test started - now you can type characters to be echoed. ---\n"; + terminal.write(intro_text, strlen(intro_text) + 1); + for (;;) { sig_rec.wait_for_signal(); int num_bytes = terminal.read(read_buffer, sizeof(read_buffer)); - if (num_bytes) + if (verbose && (num_bytes > 0)) PDBG("got %d bytes", num_bytes); for (int i = 0; i < num_bytes; i++)