diff --git a/repos/os/recipes/src/log_core/content.mk b/repos/os/recipes/src/log_core/content.mk
new file mode 100644
index 0000000000..bd9e705fce
--- /dev/null
+++ b/repos/os/recipes/src/log_core/content.mk
@@ -0,0 +1,2 @@
+SRC_DIR = src/app/log_core
+include $(GENODE_DIR)/repos/base/recipes/src/content.inc
diff --git a/repos/os/recipes/src/log_core/hash b/repos/os/recipes/src/log_core/hash
new file mode 100644
index 0000000000..70c4700841
--- /dev/null
+++ b/repos/os/recipes/src/log_core/hash
@@ -0,0 +1 @@
+2017-12-13-b 766edac0917548ff49d04226d07e314b5b05b48a
diff --git a/repos/os/recipes/src/log_core/used_apis b/repos/os/recipes/src/log_core/used_apis
new file mode 100644
index 0000000000..3a7f09b08d
--- /dev/null
+++ b/repos/os/recipes/src/log_core/used_apis
@@ -0,0 +1,3 @@
+base
+os
+timer_session
diff --git a/repos/os/run/log_core.run b/repos/os/run/log_core.run
new file mode 100644
index 0000000000..e3ad2fe589
--- /dev/null
+++ b/repos/os/run/log_core.run
@@ -0,0 +1,91 @@
+if {[have_spec linux]} {
+ puts "\n Run script is not supported on this platform. \n";
+ exit 0
+}
+if {[get_cmd_switch --autopilot] && ![have_include "power_on/qemu"]} {
+ puts "\n Run script is not supported on this platform. \n";
+ exit 0
+}
+
+proc log_service { } {
+ if { [get_cmd_switch --autopilot] } { return log }
+ return ram
+}
+
+build "core init drivers/timer server/vfs server/fs_log app/log_core"
+
+create_boot_directory
+
+install_config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <} [log_service] { name="log.log"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+build_boot_image "core init timer ld.lib.so vfs fs_log log_core"
+
+append qemu_args " -nographic "
+
+if { [get_cmd_switch --autopilot] } {
+ run_genode_until {.*\[init -> vfs] \[.*\n} 20
+} else {
+ run_genode_until forever
+}
diff --git a/repos/os/src/app/log_core/component.cc b/repos/os/src/app/log_core/component.cc
new file mode 100644
index 0000000000..c35da4a5e2
--- /dev/null
+++ b/repos/os/src/app/log_core/component.cc
@@ -0,0 +1,126 @@
+/*
+ * \brief Component transforming core and kernel output to Genode LOG output
+ * \author Alexander Boettcher
+ * \date 2016-12-22
+ */
+
+/*
+ * Copyright (C) 2016-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+/* base includes */
+#include
+#include
+
+/* os includes */
+#include
+#include
+
+
+class Log
+{
+ private:
+
+ Genode::Attached_rom_dataspace _rom_ds;
+ Genode::Log_connection _log;
+
+ char _buffer [Genode::Log_session::MAX_STRING_LEN + 1];
+ unsigned short _buf_pos { 0 };
+ unsigned _rom_pos { 0 };
+
+ unsigned log_size() const { return _rom_ds.size() - sizeof(_rom_pos); }
+
+ char const * char_from_rom(unsigned offset = 0) const
+ {
+ return _rom_ds.local_addr() + sizeof(_rom_pos) +
+ (_rom_pos + offset) % log_size();
+ }
+
+ unsigned next_pos(unsigned pos) const {
+ return (pos + 1) % log_size(); }
+
+ unsigned end_pos() const {
+ return *_rom_ds.local_addr() % log_size(); }
+
+ void _rom_to_log(unsigned const last_pos)
+ {
+ unsigned up_to_pos = last_pos;
+
+ for (; _rom_pos != next_pos(up_to_pos)
+ ; _rom_pos = next_pos(_rom_pos), up_to_pos = end_pos()) {
+
+ char const c = *char_from_rom();
+
+ _buffer[_buf_pos++] = c;
+
+ if (_buf_pos + 1U < sizeof(_buffer) && c != '\n')
+ continue;
+
+ _buffer[_buf_pos] = 0;
+ _log.write(Genode::Log_session::String(_buffer));
+ _buf_pos = 0;
+ }
+ }
+
+ public:
+
+ Log (Genode::Env &env, char const * const rom_name,
+ char const * const log_name)
+ : _rom_ds(env, rom_name), _log(env, log_name)
+ {
+ unsigned const pos = end_pos();
+
+ /* initial check whether already log wrapped at least one time */
+ enum { COUNT_TO_CHECK_FOR_WRAP = 8 };
+ for (unsigned i = 1; i <= COUNT_TO_CHECK_FOR_WRAP; i++) {
+ if (*char_from_rom(pos + i) == 0)
+ continue;
+
+ /* wrap detected, set pos behind last known pos */
+ _rom_pos = next_pos(pos + 1) % log_size();
+ break;
+ }
+
+ _rom_to_log(pos);
+ }
+
+ void log() { _rom_to_log(end_pos()); }
+};
+
+struct Monitor
+{
+ Genode::Env &env;
+
+ Log output { env, "log", "log" };
+
+ Timer::Connection timer { env };
+
+ Genode::Signal_handler interval { env.ep(), *this, &Monitor::check };
+
+ Monitor(Genode::Env &env) : env(env)
+ {
+ timer.sigh(interval);
+
+ Genode::addr_t period_ms = 1000;
+
+ try {
+ Genode::Attached_rom_dataspace config { env, "config" };
+ period_ms = config.xml().attribute_value("period_ms", 1000UL);
+ } catch (...) { }
+
+ Genode::log("update every ", period_ms," ms");
+
+ timer.trigger_periodic(1000UL * period_ms);
+ }
+
+ void check()
+ {
+ output.log();
+ }
+};
+
+
+void Component::construct(Genode::Env &env) { static Monitor output(env); }
diff --git a/repos/os/src/app/log_core/target.mk b/repos/os/src/app/log_core/target.mk
new file mode 100644
index 0000000000..249fd0ce29
--- /dev/null
+++ b/repos/os/src/app/log_core/target.mk
@@ -0,0 +1,3 @@
+TARGET = log_core
+SRC_CC = component.cc
+LIBS = base
diff --git a/tool/autopilot.list b/tool/autopilot.list
index c348601566..967baea254 100644
--- a/tool/autopilot.list
+++ b/tool/autopilot.list
@@ -105,3 +105,4 @@ nic_dump
slab
ada
fs_report
+log_core