diff --git a/ports/include/noux_session/sysio.h b/ports/include/noux_session/sysio.h
index d95de1c21a..12fb5bb91a 100644
--- a/ports/include/noux_session/sysio.h
+++ b/ports/include/noux_session/sysio.h
@@ -120,6 +120,7 @@ namespace Noux {
DIRENT_TYPE_FILE,
DIRENT_TYPE_DIRECTORY,
DIRENT_TYPE_FIFO,
+ DIRENT_TYPE_CHARDEV,
DIRENT_TYPE_SYMLINK,
DIRENT_TYPE_END
};
diff --git a/ports/run/noux_terminal_fs.run b/ports/run/noux_terminal_fs.run
new file mode 100644
index 0000000000..c25136549c
--- /dev/null
+++ b/ports/run/noux_terminal_fs.run
@@ -0,0 +1,219 @@
+#
+# \brief Test for the Noux terminal file system
+# \author Christian Prochaska
+# \date 2012-06-11
+#
+
+#
+# The test shows two framebuffer terminals. The upper terminal runs an
+# interatctive shell and the lower terminal can be accessed from the shell via
+# /dev/terminal.
+#
+# Example for writing to the lower terminal: echo "test" > /dev/terminal
+# Example for reading a line from the lower terminal: head -n 1 /dev/terminal
+#
+
+set build_components {
+ core init drivers/timer noux lib/libc_noux
+ drivers/framebuffer drivers/pci drivers/input
+ server/terminal server/ram_fs server/nitpicker
+ server/nit_fb
+}
+
+#
+# Build Noux packages only once
+#
+foreach pkg {bash coreutils} {
+ lappend_if [expr ![file exists bin/$pkg]] build_components noux-pkg/$pkg }
+
+build $build_components
+
+# strip all binaries prior archiving
+exec sh -c "find bin/bash/ bin/coreutils/ -type f | (xargs strip || true) 2>/dev/null"
+
+exec tar cfv bin/bash.tar -h -C bin/bash .
+exec tar cfv bin/coreutils.tar -h -C bin/coreutils .
+
+create_boot_directory
+
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+
+append_if [have_spec sdl] config {
+
+
+
+
+
+
+ }
+
+append_if [have_spec pci] config {
+
+
+
+ }
+
+append_if [have_spec vesa] config {
+
+
+
+ }
+
+append_if [have_spec pl11x] config {
+
+
+
+ }
+
+append_if [have_spec ps2] config {
+
+
+
+ }
+
+append config {
+
+
+
+ }
+append_if [have_spec ps2] config {
+ }
+append_if [have_spec vesa] config {
+ }
+append_if [have_spec pl11x] config {
+ }
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+install_config $config
+
+
+#
+# Boot modules
+#
+
+# generic modules
+set boot_modules {
+ core init timer ld.lib.so noux terminal ram_fs nitpicker nit_fb
+ libc.lib.so libm.lib.so libc_noux.lib.so
+ bash.tar coreutils.tar
+}
+
+# platform-specific modules
+lappend_if [have_spec linux] boot_modules fb_sdl
+lappend_if [have_spec pci] boot_modules pci_drv
+lappend_if [have_spec vesa] boot_modules vesa_drv
+lappend_if [have_spec ps2] boot_modules ps2_drv
+lappend_if [have_spec pl11x] boot_modules pl11x_drv
+
+build_boot_image $boot_modules
+
+if {[have_spec x86_64]} {
+ # bash.tar is really huge when built for x86_64
+ append qemu_args " -m 300 "
+}
+
+run_genode_until forever
+
+exec rm bin/bash.tar
diff --git a/ports/src/lib/libc_noux/plugin.cc b/ports/src/lib/libc_noux/plugin.cc
index ac564b1e33..2d12de69c1 100644
--- a/ports/src/lib/libc_noux/plugin.cc
+++ b/ports/src/lib/libc_noux/plugin.cc
@@ -931,6 +931,7 @@ namespace {
case Noux::Sysio::DIRENT_TYPE_FILE: dirent->d_type = DT_REG; break;
case Noux::Sysio::DIRENT_TYPE_SYMLINK: dirent->d_type = DT_LNK; break;
case Noux::Sysio::DIRENT_TYPE_FIFO: dirent->d_type = DT_FIFO; break;
+ case Noux::Sysio::DIRENT_TYPE_CHARDEV: dirent->d_type = DT_CHR; break;
case Noux::Sysio::DIRENT_TYPE_END: return 0;
}
diff --git a/ports/src/noux/dir_file_system.h b/ports/src/noux/dir_file_system.h
index e548dbb5f8..5572f9973f 100644
--- a/ports/src/noux/dir_file_system.h
+++ b/ports/src/noux/dir_file_system.h
@@ -22,6 +22,7 @@
#include
#include
#include
+#include
namespace Noux {
@@ -90,6 +91,11 @@ namespace Noux {
continue;
}
+ if (sub_node.has_type("terminal")) {
+ _append_file_system(new Terminal_file_system(sub_node));
+ continue;
+ }
+
{
char type_name[64];
sub_node.type_name(type_name, sizeof(type_name));
diff --git a/ports/src/noux/terminal_file_system.h b/ports/src/noux/terminal_file_system.h
new file mode 100644
index 0000000000..de0669750c
--- /dev/null
+++ b/ports/src/noux/terminal_file_system.h
@@ -0,0 +1,210 @@
+/*
+ * \brief Terminal file system
+ * \author Christian Prochaska
+ * \date 2012-05-23
+ */
+
+/*
+ * Copyright (C) 2012 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 _NOUX__TERMINAL_FILE_SYSTEM_H_
+#define _NOUX__TERMINAL_FILE_SYSTEM_H_
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+
+/* Noux includes */
+#include
+#include "file_system.h"
+
+
+namespace Noux {
+
+ class Terminal_file_system : public File_system
+ {
+ private:
+
+ Terminal::Session_client _terminal;
+ Signal_context _read_avail_sig_ctx;
+ Signal_receiver _read_avail_sig_rec;
+
+ enum { FILENAME_MAX_LEN = 64 };
+ char _filename[FILENAME_MAX_LEN];
+
+ bool _is_root(const char *path)
+ {
+ return (strcmp(path, "") == 0) || (strcmp(path, "/") == 0);
+ }
+
+ bool _is_terminal_file(const char *path)
+ {
+ return (strlen(path) == (strlen(_filename) + 1)) &&
+ (strcmp(&path[1], _filename) == 0);
+ }
+
+ public:
+
+ Terminal_file_system(Xml_node config)
+ : _terminal(env()->parent()->session
+ ("ram_quota=8192, label=\"noux(terminal_fs)\""))
+ {
+ _filename[0] = 0;
+ try { config.attribute("name").value(_filename, sizeof(_filename)); }
+ catch (...) { }
+
+ /*
+ * Wait for connection-established signal
+ */
+
+ /* create signal receiver, just for the single signal */
+ Signal_context sig_ctx;
+ Signal_receiver sig_rec;
+ Signal_context_capability sig_cap = sig_rec.manage(&sig_ctx);
+
+ /* register signal handler */
+ _terminal.connected_sigh(sig_cap);
+
+ /* wati for signal */
+ sig_rec.wait_for_signal();
+ sig_rec.dissolve(&sig_ctx);
+
+ /*
+ * Register "read available" signal handler
+ */
+ _terminal.read_avail_sigh(_read_avail_sig_rec.manage(&_read_avail_sig_ctx));
+ }
+
+
+ /*********************************
+ ** Directory-service interface **
+ *********************************/
+
+ Dataspace_capability dataspace(char const *path)
+ {
+ /* not supported */
+ return Dataspace_capability();
+ }
+
+ void release(char const *path, Dataspace_capability ds_cap)
+ {
+ /* not supported */
+ }
+
+ bool stat(Sysio *sysio, char const *path)
+ {
+ Sysio::Stat st = { 0, 0, 0, 0, 0, 0 };
+
+ if (_is_root(path))
+ st.mode = Sysio::STAT_MODE_DIRECTORY;
+ else if (_is_terminal_file(path)) {
+ st.mode = Sysio::STAT_MODE_CHARDEV;
+ } else {
+ sysio->error.stat = Sysio::STAT_ERR_NO_ENTRY;
+ return false;
+ }
+
+ sysio->stat_out.st = st;
+ return true;
+ }
+
+ bool dirent(Sysio *sysio, char const *path, off_t index)
+ {
+ if (_is_root(path)) {
+ if (index == 0) {
+ sysio->dirent_out.entry.type = Sysio::DIRENT_TYPE_CHARDEV;
+ strncpy(sysio->dirent_out.entry.name,
+ _filename,
+ sizeof(sysio->dirent_out.entry.name));
+ } else {
+ sysio->dirent_out.entry.type = Sysio::DIRENT_TYPE_END;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ size_t num_dirent(char const *path)
+ {
+ if (_is_root(path))
+ return 1;
+ else
+ return 0;
+ }
+
+ bool is_directory(char const *path)
+ {
+ if (_is_root(path))
+ return true;
+
+ return false;
+ }
+
+ char const *leaf_path(char const *path)
+ {
+ return path;
+ }
+
+ Vfs_handle *open(Sysio *sysio, char const *path)
+ {
+ if (!_is_terminal_file(path)) {
+ sysio->error.open = Sysio::OPEN_ERR_UNACCESSIBLE;
+ return 0;
+ }
+
+ return new (env()->heap()) Vfs_handle(this, this, 0);
+ }
+
+ bool unlink(Sysio *sysio, char const *path)
+ {
+ /* not supported */
+ return false;
+ }
+
+ bool rename(Sysio *sysio, char const *from_path, char const *to_path)
+ {
+ /* not supported */
+ return false;
+ }
+
+ bool mkdir(Sysio *sysio, char const *path)
+ {
+ /* not supported */
+ return false;
+ }
+
+ /***************************
+ ** File_system interface **
+ ***************************/
+
+ char const *name() const { return "terminal"; }
+
+
+ /********************************
+ ** File I/O service interface **
+ ********************************/
+
+ bool write(Sysio *sysio, Vfs_handle *handle)
+ {
+ sysio->write_out.count = _terminal.write(sysio->write_in.chunk, sysio->write_in.count);
+ return true;
+ }
+
+ bool read(Sysio *sysio, Vfs_handle *vfs_handle)
+ {
+ _read_avail_sig_rec.wait_for_signal();
+ sysio->read_out.count = _terminal.read(sysio->read_out.chunk, sysio->read_in.count);
+ return true;
+ }
+ };
+}
+
+#endif /* _NOUX__TERMINAL_FILE_SYSTEM_H_ */