diff --git a/gems/run/terminal_log.run b/gems/run/terminal_log.run
new file mode 100644
index 000000000..bc2da1502
--- /dev/null
+++ b/gems/run/terminal_log.run
@@ -0,0 +1,160 @@
+#
+# \brief Showcases terminal_log server
+# \author Stefan Kalkowski
+# \date 2012-05-21
+#
+
+build {
+ core
+ init
+ drivers/framebuffer
+ drivers/input
+ drivers/pci
+ server/nitpicker
+ server/nit_fb
+ server/terminal
+ server/terminal_log
+}
+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_if [expr ! [have_spec sdl]] config {
+
+
+
+
+
+
+
+
+ }
+
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+install_config $config
+
+# generic modules
+set boot_modules {
+ core init
+ timer
+ nitpicker
+ launchpad
+ testnit
+ nit_fb
+ terminal
+ terminal_log
+}
+
+# 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
+
+append qemu_args " -m 256 "
+run_genode_until forever
diff --git a/os/src/server/terminal_log/main.cc b/os/src/server/terminal_log/main.cc
new file mode 100644
index 000000000..b5c426a01
--- /dev/null
+++ b/os/src/server/terminal_log/main.cc
@@ -0,0 +1,167 @@
+/*
+ * \brief LOG service that prints to a terminal
+ * \author Stefan Kalkowski
+ * \date 2012-05-21
+ */
+
+/*
+ * 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.
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+
+namespace Genode {
+
+ class Termlog_component : public Rpc_object
+ {
+ public:
+
+ enum { LABEL_LEN = 64 };
+
+ private:
+
+ char _label[LABEL_LEN];
+ Terminal::Connection *_terminal;
+
+ public:
+
+ /**
+ * Constructor
+ */
+ Termlog_component(const char *label, Terminal::Connection *terminal)
+ : _terminal(terminal) { snprintf(_label, LABEL_LEN, "[%s] ", label); }
+
+
+ /*****************
+ ** Log session **
+ *****************/
+
+ /**
+ * Write a log-message to the terminal.
+ *
+ * The following function's code is a modified variant of the one in:
+ * 'base/src/core/include/log_session_component.h'
+ */
+ size_t write(String const &string_buf)
+ {
+ if (!(string_buf.is_valid_string())) {
+ PERR("corrupted string");
+ return 0;
+ }
+
+ char const *string = string_buf.string();
+ int len = strlen(string);
+
+ /*
+ * Heuristic: The Log console implementation flushes
+ * the output preferably in front of escape
+ * sequences. If the line contains only
+ * the escape sequence, we skip the printing
+ * of the label and cut the line break (last
+ * character).
+ */
+ enum { ESC = 27 };
+ if ((string[0] == ESC) && (len == 5) && (string[4] == '\n')) {
+ char buf[5];
+ strncpy(buf, string, 5);
+ _terminal->write(buf, len);
+ return len;
+ }
+
+ _terminal->write(_label, strlen(_label));
+ _terminal->write(string, len);
+
+ /* if last character of string was not a line break, add one */
+ if ((len > 0) && (string[len - 1] != '\n'))
+ _terminal->write("\n", 1);
+
+ return len;
+ }
+ };
+
+
+ class Termlog_root : public Root_component
+ {
+ private:
+
+ Terminal::Connection *_terminal;
+
+ protected:
+
+ /**
+ * Root component interface
+ */
+ Termlog_component *_create_session(const char *args)
+ {
+ size_t ram_quota =
+ Arg_string::find_arg(args, "ram_quota" ).ulong_value(0);
+
+ /* delete ram quota by the memory needed for the session */
+ size_t session_size = max((size_t)4096, sizeof(Termlog_component));
+ if (ram_quota < session_size)
+ throw Root::Quota_exceeded();
+
+ char label_buf[Termlog_component::LABEL_LEN];
+
+ Arg label_arg = Arg_string::find_arg(args, "label");
+ label_arg.string(label_buf, sizeof(label_buf), "");
+
+ return new (md_alloc()) Termlog_component(label_buf, _terminal);
+ }
+
+ public:
+
+ /**
+ * Constructor
+ *
+ * \param session_ep entry point for managing cpu session objects
+ * \param md_alloc meta-data allocator to be used by root component
+ */
+ Termlog_root(Rpc_entrypoint *session_ep, Allocator *md_alloc,
+ Terminal::Connection *terminal)
+ : Root_component(session_ep, md_alloc),
+ _terminal(terminal) { }
+ };
+}
+
+
+int main(int argc, char **argv)
+{
+ using namespace Genode;
+
+ /*
+ * Open Terminal session
+ */
+ static Terminal::Connection terminal;
+
+ /*
+ * Initialize server entry point
+ */
+ enum { STACK_SIZE = 4096 };
+ static Cap_connection cap;
+ static Rpc_entrypoint ep(&cap, STACK_SIZE, "termlog_ep");
+ static Termlog_root termlog_root(&ep, env()->heap(), &terminal);
+
+ /*
+ * Announce services
+ */
+ env()->parent()->announce(ep.manage(&termlog_root));
+
+ /**
+ * Got to sleep forever
+ */
+ sleep_forever();
+ return 0;
+}
diff --git a/os/src/server/terminal_log/target.mk b/os/src/server/terminal_log/target.mk
new file mode 100644
index 000000000..4f10baf19
--- /dev/null
+++ b/os/src/server/terminal_log/target.mk
@@ -0,0 +1,3 @@
+TARGET = terminal_log
+SRC_CC = main.cc
+LIBS = cxx env server signal