diff --git a/repos/os/run/rom_to_file.run b/repos/os/run/rom_to_file.run
new file mode 100644
index 0000000000..06a497db34
--- /dev/null
+++ b/repos/os/run/rom_to_file.run
@@ -0,0 +1,84 @@
+assert_spec linux
+
+#
+# Build
+#
+
+build { core init drivers/timer
+ server/dynamic_rom
+ app/rom_to_file
+ server/lx_fs
+}
+
+create_boot_directory
+
+#
+# Generate config
+#
+
+install_config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+#
+# Boot image
+#
+
+exec mkdir -p bin/fs_test
+
+build_boot_image { core init timer
+ dynamic_rom
+ rom_to_file
+ lx_fs
+ fs_test
+}
+
+append qemu_args " -nographic "
+
+run_genode_until "finished" 10
+
+set output [exec cat bin/fs_test/test]
+
+compare_output_to {}
+
+exec rm -r bin/fs_test
diff --git a/repos/os/src/app/rom_to_file/README b/repos/os/src/app/rom_to_file/README
new file mode 100644
index 0000000000..0907d24cd9
--- /dev/null
+++ b/repos/os/src/app/rom_to_file/README
@@ -0,0 +1,10 @@
+The rom_to_file component requests a ROM session and writes the content of the
+ROM dataspace to a File_system. It responds to configuration and ROM-module
+updates.
+
+The name of the ROM module must be specified via the 'rom' attribute of the
+components '' node
+
+!
+
+See run/rom_to_file.run for an example.
diff --git a/repos/os/src/app/rom_to_file/main.cc b/repos/os/src/app/rom_to_file/main.cc
new file mode 100644
index 0000000000..13b993faeb
--- /dev/null
+++ b/repos/os/src/app/rom_to_file/main.cc
@@ -0,0 +1,170 @@
+/*
+ * \brief Write content of ROM module to File_system
+ * \author Johannes Schlatow
+ * \date 2016-03-12
+ */
+
+/*
+ * Copyright (C) 2016 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.
+ */
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+
+namespace Rom_to_file {
+
+ using namespace Genode;
+
+ struct Main;
+
+ enum {
+ BLOCK_SIZE = 512,
+ QUEUE_SIZE = File_system::Session::TX_QUEUE_SIZE,
+ TX_BUF_SIZE = BLOCK_SIZE * (QUEUE_SIZE*2 + 1)
+ };
+}
+
+
+struct Rom_to_file::Main
+{
+ Server::Entrypoint &_ep;
+
+ Allocator_avl alloc;
+
+ File_system::Connection _fs;
+
+ Lazy_volatile_object _rom_ds;
+
+ typedef Genode::String<100> Rom_name;
+
+ /**
+ * Name of currently requested ROM module
+ *
+ * Solely used to detect configuration changes.
+ */
+ Rom_name _rom_name;
+
+ /**
+ * Signal handler that is invoked when the configuration or the ROM module
+ * changes.
+ */
+ void _handle_update(unsigned);
+
+ Signal_rpc_member _update_dispatcher =
+ { _ep, *this, &Main::_handle_update };
+
+ Main(Server::Entrypoint &ep) : _ep(ep), alloc(env()->heap()), _fs(alloc, TX_BUF_SIZE)
+ {
+ config()->sigh(_update_dispatcher);
+ _handle_update(0);
+ }
+};
+
+
+void Rom_to_file::Main::_handle_update(unsigned)
+{
+ config()->reload();
+
+ /*
+ * Query name of ROM module from config
+ */
+ Rom_name rom_name;
+ try {
+ rom_name = config()->xml_node().attribute_value("rom", rom_name);
+
+ } catch (...) {
+ PWRN("could not determine ROM name from config");
+ return;
+ }
+
+ /*
+ * If ROM name changed, reconstruct '_rom_ds'
+ */
+ if (rom_name != _rom_name) {
+ _rom_ds.construct(rom_name.string());
+ _rom_ds->sigh(_update_dispatcher);
+ _rom_name = rom_name;
+ }
+
+ /*
+ * Update ROM module and print content to LOG
+ */
+ if (_rom_ds.is_constructed()) {
+ _rom_ds->update();
+
+ if (_rom_ds->is_valid()) {
+ using namespace File_system;
+
+ char dir_path[] = "/";
+ const char *file_name = _rom_name.string();
+
+ try {
+ Dir_handle dir_handle = ensure_dir(_fs, dir_path);
+ Handle_guard dir_guard(_fs, dir_handle);
+ File_handle handle;
+
+ handle = _fs.file(dir_handle, file_name, File_system::WRITE_ONLY, true);
+
+ _fs.truncate(handle, 0);
+
+ size_t len = max(strlen(_rom_ds->local_addr()), _rom_ds->size());
+ size_t written = write(_fs, handle, _rom_ds->local_addr(), len, 0);
+
+ if (written < len) {
+ PWRN("%zu of %zu bytes have been written", written, len);
+ }
+
+ _fs.close(handle);
+ } catch (Permission_denied) {
+ PERR("%s%s: permission denied", dir_path, file_name);
+
+ } catch (No_space) {
+ PERR("file system out of space");
+
+ } catch (Out_of_metadata) {
+ PERR("server ran out of memory");
+
+ } catch (Invalid_name) {
+ PERR("%s%s: invalid path", dir_path, file_name);
+
+ } catch (Name_too_long) {
+ PERR("%s%s: name too long", dir_path, file_name);
+
+ } catch (...) {
+ PERR("cannot open file %s%s", dir_path, file_name);
+ throw;
+ }
+ } else {
+ PLOG("ROM '%s' is invalid", _rom_name.string());
+ }
+ }
+}
+
+
+namespace Server {
+
+ char const *name() { return "rom_to_file_ep"; }
+
+ size_t stack_size() { return 4*1024*sizeof(long); }
+
+ void construct(Entrypoint &ep)
+ {
+ static Rom_to_file::Main main(ep);
+ }
+}
diff --git a/repos/os/src/app/rom_to_file/target.mk b/repos/os/src/app/rom_to_file/target.mk
new file mode 100644
index 0000000000..f574d896bb
--- /dev/null
+++ b/repos/os/src/app/rom_to_file/target.mk
@@ -0,0 +1,3 @@
+TARGET = rom_to_file
+SRC_CC = main.cc
+LIBS = base config server