diff --git a/.gitignore b/.gitignore
index 05a22d571..1234a4573 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,8 @@
/dde_linux/download
/dde_oss/contrib
/dde_oss/download
+/dde_rump/contrib
+/dde_rump/include/rump
/libports/contrib
/libports/download
/libports/include/curl/
diff --git a/dde_rump/Makefile b/dde_rump/Makefile
new file mode 100644
index 000000000..1e969fb8b
--- /dev/null
+++ b/dde_rump/Makefile
@@ -0,0 +1,64 @@
+#
+# \brief Checkout rump kernel source code
+# \author Sebastian Sumpf
+# \date 2013-11-27
+#
+
+VERBOSE ?= @
+CONTRIB_DIR = contrib
+ECHO = @echo
+PATCHES := $(shell find patches -name \*.patch)
+
+GIT_RUMP_URI = https://github.com/anttikantee/buildrump.sh.git
+GIT_RUMP_COMMIT = d604845baafa110945cb54a2d9607e6f435c6027
+
+GIT_LIBS_URI = https://github.com/anttikantee/xen-nblibc.git
+GIT_LIBS_COMMIT = b86122315f338042d06ad83ac5bd763a5dbd0c00
+
+RUMP_SRC = src
+
+#
+# Utility to check if a tool is installed
+#
+check_tool = $(if $(shell which $(1)),,$(error Need to have '$(1)' installed.))
+
+$(call check_tool,git)
+
+$(CONTRIB_DIR)/.git:
+ $(VERBOSE) git clone $(GIT_RUMP_URI) $(CONTRIB_DIR)
+
+$(CONTRIB_DIR)/nblibs:
+ $(VERBOSE) git clone $(GIT_LIBS_URI) $(CONTRIB_DIR)/nblibs
+ cd $(CONTRIB_DIR)/nblibs ; ln -sf ../$(RUMP_SRC)/common
+
+$(CONTRIB_DIR)/$(RUMP_SRC):
+ $(VERBOSE) cd $(CONTRIB_DIR); ./buildrump.sh -s $(RUMP_SRC) checkout
+
+commit:
+ $(VERBOSE) cd $(CONTRIB_DIR); git fetch origin
+ $(VERBOSE) cd $(CONTRIB_DIR); git reset --hard $(GIT_RUMP_COMMIT)
+ $(VERBOSE) cd $(CONTRIB_DIR)/nblibs; git fetch origin
+ $(VERBOSE) cd $(CONTRIB_DIR)/nblibs; git reset --hard $(GIT_LIBS_COMMIT)
+ $(ECHO) "applying patches to '$(CONTRIB_DIR)/'"
+ $(VERBOSE)for i in $(PATCHES); do patch -N -d $(CONTRIB_DIR) -p1 < $$i; done
+
+prepare: $(CONTRIB_DIR)/.git $(CONTRIB_DIR)/nblibs $(CONTRIB_DIR)/$(RUMP_SRC) commit
+ $(VERBOSE)mkdir -p include
+ $(VERBOSE)ln -sf ../$(CONTRIB_DIR)/$(RUMP_SRC)/sys/rump/include/rump include/rump
+
+
+clean:
+ $(VERBOSE) rm -rf $(CONTRIB_DIR)
+
+help::
+ $(ECHO)
+ $(ECHO) "Check out rump kernel sources"
+ $(ECHO)
+ $(ECHO) "The source code will be located at the '$(CONTRIB_DIR)/' directory."
+ $(ECHO)
+ $(ECHO) "--- available commands ---"
+ $(ECHO) "prepare - checkout source codes"
+ $(ECHO) "clean - remove source codes"
+ $(ECHO)
+
+.NOTPARALLEL:
diff --git a/dde_rump/README b/dde_rump/README
new file mode 100644
index 000000000..fd62316ab
--- /dev/null
+++ b/dde_rump/README
@@ -0,0 +1,57 @@
+ ================================
+ Genode's Rump Kernel kernel port
+ ================================
+
+This repository contains the Genode version of the [http://wiki.netbsd.org/rumpkernel/ - rump kernel].
+The kernel is currently used to gain file-system access from within Genode. In
+order to achieve that, a Genode file-system server is located at
+_src/server/rump_fs_. For accessing the server through the libc, the _libc_fs_
+plugin can be facilitated, which is available in the _libports_ repository.
+
+Building instructions
+#####################
+
+In order to build the file-system server, issue
+
+! make prepare
+
+from the directory this file is contained in.
+
+
+Add
+
+! REPOSITORIES += $(GENODE_DIR)/dde_rump
+
+to your _etc/build.conf_ file of you build directory.
+
+Finally,
+
+! make server/rumps_fs
+
+called from your build directory will build the server. You may also specify
+
+! make run/rump_ext2
+
+to run a simple test scenario.
+
+
+Configuration
+#############
+
+Here is an example snippet that configures the server:
+
+!
+!
+!
+!
+!
+
+The server is looking for a service that provides a Genode block session. If
+there is more than one block session in the system, the block session must be
+routed to the right block-session server. The value of the _fs_ attribute of
+the _config_ node can be one of the following: _ext2fs_ for EXT2, _cd9660_ for
+ISO-9660, or _msdos_ for FAT file-system support. _root_ defines the directory
+of the file system as seen as root directory by the client. The server hands
+most of its RAM quota to the rump kernel. This means the larger the quota is,
+the larger the internal block caches of the rump kernel will be.
+
diff --git a/dde_rump/include/rump_fs/fs.h b/dde_rump/include/rump_fs/fs.h
new file mode 100644
index 000000000..eb5dac47a
--- /dev/null
+++ b/dde_rump/include/rump_fs/fs.h
@@ -0,0 +1,32 @@
+/**
+ * \brief Definitions for FS front-end
+ * \author Sebastian Sumpf
+ * \date 2014-01-22
+ */
+
+/*
+ * Copyright (C) 2014 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 _INCLUDE__RUMP_FS__FS_H_
+#define _INCLUDE__RUMP_FS__FS_H_
+
+/**
+ * File to upon the back-end will open a block session
+ */
+#define GENODE_BLOCK_SESSION "block_session"
+
+/**
+ * Device to create within rump
+ */
+#define GENODE_DEVICE "/genode"
+
+
+/**
+ * Sync I/O back-end with underlying Genode subsystems
+ */
+void rump_io_backend_sync();
+
+#endif /* _INCLUDE__RUMP_FS__FS_H_ */
diff --git a/dde_rump/include/util/allocator_fap.h b/dde_rump/include/util/allocator_fap.h
new file mode 100644
index 000000000..3d8e9a327
--- /dev/null
+++ b/dde_rump/include/util/allocator_fap.h
@@ -0,0 +1,219 @@
+/**
+ * \brief Fast allocator for porting
+ * \author Sebastian Sumpf
+ * \date 2013-06-12
+ */
+
+/*
+ * Copyright (C) 2013-2014 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 _INCLUDE__UTIL__ALLOCATOR_FAP_H_
+#define _INCLUDE__UTIL__ALLOCATOR_FAP_H_
+
+#include
+#include
+#include
+
+
+namespace Allocator {
+ template class Backend_alloc;
+ template class Fap;
+}
+
+
+namespace Allocator {
+
+ using namespace Genode;
+
+ struct Default_allocator_policy
+ {
+ static int block() { return 0; }
+ static void unblock(int) { }
+ };
+
+ template
+ struct Policy_guard
+ {
+ int val;
+ Policy_guard() { val = POLICY::block(); }
+ ~Policy_guard() { POLICY::unblock(val); }
+ };
+
+ /**
+ * Back-end allocator for Genode's slab allocator
+ */
+ template
+ class Backend_alloc : public Genode::Allocator,
+ public Genode::Rm_connection
+ {
+ private:
+
+ enum {
+ BLOCK_SIZE = 1024 * 1024, /* 1 MB */
+ ELEMENTS = VM_SIZE / BLOCK_SIZE, /* MAX number of dataspaces in VM */
+ };
+
+ typedef Genode::addr_t addr_t;
+ typedef Genode::Ram_dataspace_capability Ram_dataspace_capability;
+ typedef Genode::Allocator_avl Allocator_avl;
+
+ addr_t _base; /* virt. base address */
+ bool _cached; /* non-/cached RAM */
+ Ram_dataspace_capability _ds_cap[ELEMENTS]; /* dataspaces to put in VM */
+ addr_t _ds_phys[ELEMENTS]; /* physical bases of dataspaces */
+ int _index = 0; /* current index in ds_cap */
+ Allocator_avl _range; /* manage allocations */
+ bool _quota_exceeded = false;
+
+ bool _alloc_block()
+ {
+ if (_quota_exceeded)
+ return false;
+
+ if (_index == ELEMENTS) {
+ PERR("Slab-backend exhausted!");
+ return false;
+ }
+
+ Policy_guard guard;
+
+ try {
+ _ds_cap[_index] = Genode::env()->ram_session()->alloc(BLOCK_SIZE, _cached);
+ /* attach at index * BLOCK_SIZE */
+ Rm_connection::attach_at(_ds_cap[_index], _index * BLOCK_SIZE, BLOCK_SIZE, 0);
+ /* lookup phys. address */
+ _ds_phys[_index] = Genode::Dataspace_client(_ds_cap[_index]).phys_addr();
+ } catch (Genode::Ram_session::Quota_exceeded) {
+ PERR("Backend allocator exhausted");
+ _quota_exceeded = true;
+ return false;
+ } catch (Genode::Rm_session::Attach_failed) {
+ PERR("Backend VM region exhausted");
+ _quota_exceeded = true;
+ return false;
+ }
+
+ /* return base + offset in VM area */
+ addr_t block_base = _base + (_index * BLOCK_SIZE);
+ ++_index;
+
+ _range.add_range(block_base, BLOCK_SIZE);
+ return true;
+ }
+
+ public:
+
+ Backend_alloc(bool cached)
+ : Rm_connection(0, VM_SIZE), _cached(cached),
+ _range(Genode::env()->heap())
+ {
+ /* reserver attach us, anywere */
+ _base = Genode::env()->rm_session()->attach(dataspace());
+ }
+
+ /**
+ * Allocate
+ */
+ bool alloc(size_t size, void **out_addr)
+ {
+ bool done = _range.alloc(size, out_addr);
+
+ if (done)
+ return done;
+
+ done = _alloc_block();
+ if (!done) {
+ PERR("Backend allocator exhausted\n");
+ return false;
+ }
+
+ return _range.alloc(size, out_addr);
+ }
+
+ void *alloc_aligned(size_t size, int align = 0)
+ {
+ void *addr;
+
+ if (!_range.alloc_aligned(size, &addr, align).is_error())
+ return addr;
+
+ if (!_alloc_block())
+ return 0;
+
+ if (_range.alloc_aligned(size, &addr, align).is_error()) {
+ PERR("Backend allocator: Unable to allocate memory (size: %zu align: %d:)",
+ size, align);
+ return 0;
+ }
+
+ return addr;
+ }
+
+ void free(void *addr, size_t size) { _range.free(addr, size); }
+ size_t overhead(size_t size) { return 0; }
+ bool need_size_for_free() const override { return false; }
+
+ /**
+ * Return phys address for given virtual addr.
+ */
+ addr_t phys_addr(addr_t addr)
+ {
+ if (addr < _base || addr >= (_base + VM_SIZE))
+ return ~0UL;
+
+ int index = (addr - _base) / BLOCK_SIZE;
+
+ /* physical base of dataspace */
+ addr_t phys = _ds_phys[index];
+
+ if (!phys)
+ return ~0UL;
+
+ /* add offset */
+ phys += (addr - _base - (index * BLOCK_SIZE));
+ return phys;
+ }
+
+ bool inside(addr_t addr) const { return (addr >= _base) && (addr < (_base + VM_SIZE)); }
+ };
+
+
+ /**
+ * Interface
+ */
+ template
+ class Fap
+ {
+ private:
+
+ typedef Allocator::Backend_alloc Backend_alloc;
+
+ Backend_alloc _back_allocator;
+
+ public:
+
+ Fap(bool cached)
+ : _back_allocator(cached) { }
+
+ void *alloc(size_t size, int align = 0)
+ {
+ return _back_allocator.alloc_aligned(size, align);
+ }
+
+ void free(void *addr, size_t size)
+ {
+ _back_allocator.free(addr, size);
+ }
+
+ addr_t phys_addr(void *addr)
+ {
+ return _back_allocator.phys_addr((addr_t)addr);
+ }
+ };
+} /* namespace Allocator */
+
+#endif /* _INCLUDE__UTIL__ALLOCATOR_FAP_H_ */
diff --git a/dde_rump/include/util/hard_context.h b/dde_rump/include/util/hard_context.h
new file mode 100644
index 000000000..374fcd6e3
--- /dev/null
+++ b/dde_rump/include/util/hard_context.h
@@ -0,0 +1,65 @@
+/**
+ * \brief Hard-context for use within rump kernel
+ * \author Sebastian Sumpf
+ * \date 2014-02-05
+ */
+
+/*
+ * Copyright (C) 2014 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 _INCLUDE__HARD_CONTEXT_H_
+#define _INCLUDE__HARD_CONTEXT_H_
+
+extern "C" {
+#include
+#include
+#include
+}
+
+#include
+
+
+/*************
+ ** Threads **
+ *************/
+
+typedef void *(*func)(void *);
+
+namespace Timer {
+ class Connection;
+};
+
+class Hard_context : public Genode::Thread
+{
+ private:
+
+ func _func;
+ void *_arg;
+ int _cookie;
+ lwp *_lwp;
+
+ protected:
+
+ void entry()
+ {
+ _func(_arg);
+ PDBG("Returned from func");
+ }
+
+ public:
+
+ Hard_context(char const *name, func f, void *arg, int cookie, bool run = true)
+ : Thread(name),
+ _func(f), _arg(arg), _cookie(cookie), _lwp(0) { if (run) start(); }
+
+ void set_lwp(lwp *l) { _lwp = l; }
+ lwp *get_lwp() { return _lwp; }
+
+ static Timer::Connection *timer();
+};
+
+#endif /* _INCLUDE__HARD_CONTEXT_H_ */
diff --git a/dde_rump/lib/import/import-rump.mk b/dde_rump/lib/import/import-rump.mk
new file mode 100644
index 000000000..2e4f7ee6c
--- /dev/null
+++ b/dde_rump/lib/import/import-rump.mk
@@ -0,0 +1 @@
+INC_DIR += $(LIBGCC_INC_DIR) $(BUILD_BASE_DIR)/var/libcache/rump/include
diff --git a/dde_rump/lib/mk/arm/rump.mk b/dde_rump/lib/mk/arm/rump.mk
new file mode 100644
index 000000000..3d7465cc3
--- /dev/null
+++ b/dde_rump/lib/mk/arm/rump.mk
@@ -0,0 +1,4 @@
+
+RUMP_OPT =
+
+include $(REP_DIR)/lib/mk/rump_base.inc
diff --git a/dde_rump/lib/mk/rump.inc b/dde_rump/lib/mk/rump.inc
new file mode 100644
index 000000000..6ed8f6131
--- /dev/null
+++ b/dde_rump/lib/mk/rump.inc
@@ -0,0 +1,23 @@
+#
+# \brief Basic definitions for all rump libraries
+# \author Sebastian Sumpf
+# \date 2013-12-12
+#
+
+CONTRIB_DIR = $(REP_DIR)/contrib
+RUMP_BASE = $(BUILD_BASE_DIR)/var/libcache/rump
+RUMP_LIB = $(RUMP_BASE)/lib
+
+SHARED_LIB = yes
+
+#
+# ARCHIVE contains the absolute paths to rump-archive libraries, rump.ld is an
+# additional linker script which is required during initialization
+#
+LD_OPT += --whole-archive --start-group $(ARCHIVE) --end-group \
+ --no-whole-archiv
+
+LD_SCRIPT_SO = $(call select_from_repositories,src/platform/genode_rel.ld) \
+ -T$(REP_DIR)/src/platform/rump.ld
+
+# vi:set ft=make :
diff --git a/dde_rump/lib/mk/rump_base.inc b/dde_rump/lib/mk/rump_base.inc
new file mode 100644
index 000000000..df6fa0e33
--- /dev/null
+++ b/dde_rump/lib/mk/rump_base.inc
@@ -0,0 +1,92 @@
+
+include $(REP_DIR)/lib/mk/rump.inc
+include $(REP_DIR)/lib/import/import-rump.mk
+
+RUMP_OBJ = $(RUMP_BASE)/obj
+RUMP_SRC = $(CONTRIB_DIR)/src
+RUMP_TOOLS = $(RUMP_BASE)/tools
+RMAKE = $(RUMP_TOOLS)/rumpmake
+
+#
+# Can be up to 4 for most verbose output
+#
+VERBOSE_LEVEL ?= 0
+
+#
+# Sources
+#
+SRC_CC = dummies.cc hypercall.cc bootstrap.cc io.cc sync.cc
+
+#
+# TARGET to trigger rump build
+#
+SOURCE = $(addprefix $(REP_DIR)/src/lib/rump/,$(SRC_CC))
+
+#
+# Rump build script
+#
+BUILD_CMD = AR=$(AR) NM=$(NM) OBJCOPY=$(OBJCOPY) \
+ $(CONTRIB_DIR)/buildrump.sh -k -V'MAKEVERBOSE=$(VERBOSE_LEVEL)' \
+ $(RUMP_OPT) -s $(RUMP_SRC) -T $(RUMP_TOOLS) -o $(RUMP_OBJ) \
+ -d $(RUMP_BASE)
+
+#
+# Linkage
+#
+ARCHIVE = $(RUMP_LIB)/librump.a
+CC_OPT = -DLIBRUMPUSER
+
+
+INCSDIRS = adosfs altq arpa crypto dev evbarm filecorefs fs i386 isofs miscfs \
+ msdosfs net net80211 netatalk netbt netinet netinet6 netipsec \
+ netisdn netkey netmpls netnatm netsmb nfs ntfs ppath prop \
+ protocols rpc rpcsvc ssp sys ufs uvm x86
+
+#
+# Make sure include directory exists
+#
+$(shell mkdir -p $(RUMP_BASE)/include)
+
+#
+# Build nbmake for host platform
+#
+$(RUMP_TOOLS):
+ CC=$(CC) $(BUILD_CMD) -N -V RUMP_KERNEL_IS_LIBC=1 tools
+ echo 'CPPFLAGS+=-DMAXPHYS=32768' >> $(RUMP_TOOLS)/mk.conf
+ echo 'CPPFLAGS+= -fPIC' >> $(RUMP_TOOLS)/mk.conf
+
+#
+# Setup install directory
+#
+$(RUMP_OBJ)/dest: $(RUMP_TOOLS)
+ CC=$(CC) $(BUILD_CMD) setupdest
+
+#
+# Build librump
+#
+$(ARCHIVE): $(RUMP_OBJ)/dest
+ @echo "Building rump library ..."
+ CC=$(CC) $(BUILD_CMD) -k build install
+
+#
+# Install kernel, libc, and pthread headers
+#
+$(RUMP_BASE)/include/.prepared: $(ARCHIVE)
+ @for i in $(INCSDIRS); do \
+ mkdir -p $(RUMP_BASE)/include/$$i; done
+ @echo "Installing headers ... (this may take a while)"
+ @cd $(RUMP_SRC)/sys; $(RMAKE) -k obj >/dev/null 2>&1
+ @cd $(RUMP_SRC)/sys; $(RMAKE) -k includes >/dev/null 2>&1
+ @cd $(RUMP_SRC)/include; $(RMAKE) -k includes > /dev/null 2>&1
+ @cd $(CONTRIB_DIR)/nblibs/lib/libc; $(RMAKE) includes >/dev/null 2>&1
+ @cd $(CONTRIB_DIR)/nblibs/lib/libpthread; $(RMAKE) includes >/dev/null 2>&1
+ @touch $(RUMP_BASE)/include/.prepared
+
+#
+# Trigger rump build
+#
+$(SOURCE): $(RUMP_BASE)/include/.prepared
+
+vpath %.cc $(REP_DIR)/src/lib/rump
+
+# vi:set ft=make :
diff --git a/dde_rump/lib/mk/rump_fs.mk b/dde_rump/lib/mk/rump_fs.mk
new file mode 100644
index 000000000..31a5f8c15
--- /dev/null
+++ b/dde_rump/lib/mk/rump_fs.mk
@@ -0,0 +1,23 @@
+
+include $(REP_DIR)/lib/mk/rump.inc
+
+LIBS += rump
+
+RUMP_LIBS = librumpdev.a \
+ librumpdev_disk.a \
+ librumpdev_netsmb.a \
+ librumpkern_crypto.a \
+ librumpnet.a \
+ librumpvfs.a \
+ librumpfs_cd9660.a \
+ librumpfs_ext2fs.a \
+ librumpfs_ffs.a \
+ librumpfs_msdos.a \
+ librumpfs_nfs.a \
+ librumpfs_ntfs.a \
+ librumpfs_smbfs.a \
+ librumpfs_udf.a
+
+ARCHIVE += $(addprefix $(RUMP_LIB)/,$(RUMP_LIBS))
+
+
diff --git a/dde_rump/lib/mk/x86_32/rump.mk b/dde_rump/lib/mk/x86_32/rump.mk
new file mode 100644
index 000000000..20647d28c
--- /dev/null
+++ b/dde_rump/lib/mk/x86_32/rump.mk
@@ -0,0 +1,4 @@
+
+RUMP_OPT = -32
+
+include $(REP_DIR)/lib/mk/rump_base.inc
diff --git a/dde_rump/lib/mk/x86_64/rump.mk b/dde_rump/lib/mk/x86_64/rump.mk
new file mode 100644
index 000000000..3d7465cc3
--- /dev/null
+++ b/dde_rump/lib/mk/x86_64/rump.mk
@@ -0,0 +1,4 @@
+
+RUMP_OPT =
+
+include $(REP_DIR)/lib/mk/rump_base.inc
diff --git a/dde_rump/patches/build.patch b/dde_rump/patches/build.patch
new file mode 100644
index 000000000..6318bd644
--- /dev/null
+++ b/dde_rump/patches/build.patch
@@ -0,0 +1,57 @@
+diff --git a/buildrump.sh b/buildrump.sh
+index f600b6a..e394b47 100755
+--- a/buildrump.sh
++++ b/buildrump.sh
+@@ -570,6 +570,16 @@ evaltools ()
+ : ${NM:=nm}
+ : ${OBJCOPY:=objcopy}
+ else
++ if [ "${MACH_ARCH}" = 'x86_64' ] ; then
++ cc_target=genode-x86
++ elif [ "${MACH_ARCH}" = 'arm' ] ; then
++ cc_target=genode-arm
++ else
++ die Unsupported architectur ${MACH_ARCH}
++ fi
++
++ echo "MACH_ARCH cc ${MACH_ARCH}"
++
+ : ${AR:=${cc_target}-ar}
+ : ${NM:=${cc_target}-nm}
+ : ${OBJCOPY:=${cc_target}-objcopy}
+@@ -600,6 +610,8 @@ evaltools ()
+ ;;
+ esac
+
++ TARGET=freebsd
++
+ # check if we're running from a tarball, i.e. is checkout possible
+ BRDIR=$(dirname $0)
+ unset TARBALLMODE
+@@ -872,26 +884,6 @@ evaltarget ()
+ ccdefault=32
+ fi
+
+- # step 2: if the user specified 32/64, try to establish if it will work
+- if ${THIRTYTWO} && [ "${ccdefault}" -ne 32 ] ; then
+- echo 'int main() {return 0;}' | ${CC} ${EXTRA_CFLAGS} -o /dev/null -x c - \
+- ${EXTRA_RUMPUSER} ${EXTRA_RUMPCOMMON} > /dev/null 2>&1
+- [ $? -eq 0 ] || ${ANYTARGETISGOOD} || \
+- die 'Gave -32, but probe shows it will not work. Try -H?'
+- elif ${SIXTYFOUR} && [ "${ccdefault}" -ne 64 ] ; then
+- echo 'int main() {return 0;}' | ${CC} ${EXTRA_CFLAGS} -o /dev/null -x c - \
+- ${EXTRA_RUMPUSER} ${EXTRA_RUMPCOMMON} > /dev/null 2>&1
+- [ $? -eq 0 ] || ${ANYTARGETISGOOD} || \
+- die 'Gave -64, but probe shows it will not work. Try -H?'
+- else
+- # not specified. use compiler default
+- if [ "${ccdefault}" -eq 64 ]; then
+- SIXTYFOUR=true
+- else
+- THIRTYTWO=true
+- fi
+- fi
+-
+ TOOLABI=''
+ case ${MACH_ARCH} in
+ "amd64"|"x86_64")
diff --git a/dde_rump/patches/evbarm.patch b/dde_rump/patches/evbarm.patch
new file mode 100644
index 000000000..5c88284bd
--- /dev/null
+++ b/dde_rump/patches/evbarm.patch
@@ -0,0 +1,26 @@
+diff --git a/src/sys/arch/arm/include/Makefile.common b/src/sys/arch/arm/include/Makefile.common
+index 6d7643a..c91f55c 100644
+--- a/src/sys/arch/arm/include/Makefile.common
++++ b/src/sys/arch/arm/include/Makefile.common
+@@ -2,7 +2,7 @@
+
+ .PATH: ../../arm/include/common
+
+-.if 0
++.if 1
+ INCS+= ansi.h aout_machdep.h asm.h \
+ bswap.h \
+ cdefs.h cpu.h \
+diff --git a/src/sys/arch/evbarm/Makefile b/src/sys/arch/evbarm/Makefile
+index c4340cb..ec9445b 100644
+--- a/src/sys/arch/evbarm/Makefile
++++ b/src/sys/arch/evbarm/Makefile
+@@ -3,7 +3,7 @@
+ # Makefile for evbarm tags file and boot blocks
+
+ # Find where ARM source files are for inclusion in tags
+-.include <../arm/Makefile.inc>
++#.include <../arm/Makefile.inc>
+
+ TEVBARM= ${SYSDIR}/arch/evbarm/tags
+ SEVBARM= ${SYSDIR}/arch/evbarm/adi_brh/*.[ch]
diff --git a/dde_rump/patches/mk.patch b/dde_rump/patches/mk.patch
new file mode 100644
index 000000000..1d7de4c90
--- /dev/null
+++ b/dde_rump/patches/mk.patch
@@ -0,0 +1,13 @@
+diff --git a/share/mk/bsd.own.mk b/share/mk/bsd.own.mk
+index 57f4909..36235db 100644
+--- a/src/share/mk/bsd.own.mk
++++ b/src/share/mk/bsd.own.mk
+@@ -1045,7 +1045,7 @@ INSTPRIV?= ${INSTPRIV.unpriv} -N ${NETBSDSRCDIR}/etc
+ STRIPFLAG?=
+
+ .if ${NEED_OWN_INSTALL_TARGET} != "no"
+-INSTALL_DIR?= ${INSTALL} ${INSTPRIV} -d
++INSTALL_DIR = ${INSTALL} ${INSTPRIV} -d
+ INSTALL_FILE?= ${INSTALL} ${INSTPRIV} ${COPY} ${PRESERVE} ${RENAME}
+ INSTALL_LINK?= ${INSTALL} ${INSTPRIV} ${HRDLINK} ${RENAME}
+ INSTALL_SYMLINK?= ${INSTALL} ${INSTPRIV} ${SYMLINK} ${RENAME}
diff --git a/dde_rump/run/rump_ext2.run b/dde_rump/run/rump_ext2.run
new file mode 100644
index 000000000..9a828906d
--- /dev/null
+++ b/dde_rump/run/rump_ext2.run
@@ -0,0 +1,89 @@
+#
+# Check used commands
+#
+set mke2fs [check_installed mke2fs]
+set dd [check_installed dd]
+
+#
+# Build
+#
+set build_components {
+ core init
+ drivers/timer
+ server/ram_blk
+ server/rump_fs
+ test/libc_fs
+}
+
+build $build_components
+
+#
+# Build EXT2-file-system image
+#
+catch { exec $dd if=/dev/zero of=bin/ext2.raw bs=1M count=16 }
+catch { exec $mke2fs -F bin/ext2.raw }
+
+create_boot_directory
+
+#
+# Generate config
+#
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+install_config $config
+
+#
+# Boot modules
+#
+
+# generic modules
+set boot_modules {
+ core init timer test-libc_fs ram_blk
+ rump.lib.so rump_fs.lib.so rump_fs
+ ld.lib.so ext2.raw libc.lib.so
+ libc_fs.lib.so libc_log.lib.so
+}
+
+build_boot_image $boot_modules
+
+append qemu_args " -m 256 -nographic"
+
+run_genode_until {.*child exited with exit value 0.*} 60
+
+exec rm -f bin/ext2.raw
+puts "\nTest succeeded\n"
diff --git a/dde_rump/run/rump_fat.run b/dde_rump/run/rump_fat.run
new file mode 100644
index 000000000..5be533bdf
--- /dev/null
+++ b/dde_rump/run/rump_fat.run
@@ -0,0 +1,89 @@
+#
+# Check used commands
+#
+set mkfs.vfat [check_installed mkfs.vfat]
+set dd [check_installed dd]
+
+#
+# Build
+#
+set build_components {
+ core init
+ drivers/timer
+ server/ram_blk
+ server/rump_fs
+ test/libc_fs
+}
+
+build $build_components
+
+#
+# Build FAT-file-system image
+#
+catch { exec $dd if=/dev/zero of=bin/fs.raw bs=1M count=16 }
+catch { exec $mkfs.vfat -F16 bin/fs.raw }
+
+create_boot_directory
+
+#
+# Generate config
+#
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+install_config $config
+
+#
+# Boot modules
+#
+
+# generic modules
+set boot_modules {
+ core init timer test-libc_fs ram_blk
+ rump.lib.so rump_fs.lib.so rump_fs
+ ld.lib.so fs.raw libc.lib.so
+ libc_fs.lib.so libc_log.lib.so
+}
+
+build_boot_image $boot_modules
+
+append qemu_args " -m 256 -nographic"
+
+run_genode_until {.*child exited with exit value 0.*} 60
+
+exec rm -f bin/fs.raw
+puts "\nTest succeeded\n"
diff --git a/dde_rump/run/rump_iso.run b/dde_rump/run/rump_iso.run
new file mode 100644
index 000000000..ced34fd44
--- /dev/null
+++ b/dde_rump/run/rump_iso.run
@@ -0,0 +1,124 @@
+#
+# Check used commands
+#
+set mkisofs [check_installed mkisofs]
+
+#
+#
+# Build
+#
+set build_components {
+ core init
+ drivers/timer
+ server/fs_rom
+ server/rom_blk
+ server/rump_fs
+ test/iso
+}
+
+build $build_components
+create_boot_directory
+
+#
+# Generate config
+#
+append config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+#
+# Create iso
+#
+exec cp -f [genode_dir]/os/src/test/iso/test.txt [run_dir]
+
+for { set i 1 } { $i <= 30 } { incr i } {
+ exec touch [run_dir]/$i.txt
+}
+
+exec rm -f bin/fs.iso
+catch { exec $mkisofs -l -R -hide-rr-moved -jcharset utf-8 -o bin/fs.iso [run_dir]}
+
+
+install_config $config
+
+#
+# Boot modules
+#
+set boot_modules {
+ core init timer test-iso rom_blk
+ rump.lib.so rump_fs.lib.so rump_fs
+ ld.lib.so fs.iso fs_rom
+}
+
+
+build_boot_image $boot_modules
+
+append qemu_args "-nographic -m 64"
+
+run_genode_until "child exited with exit value 0.*\n" 60
+
+# pay only attention to the output of init and its children
+grep_output {^\[init -> test-iso}
+
+unify_output {at [a-f0-9]+} "at "
+
+compare_output_to {
+[init -> test-iso] File size is 31000 at
+[init -> test-iso] 00001000: 61616161 61616161 61616161 61616161 61616161
+[init -> test-iso] 00001014: 61616161 61616161 61616161 61616161 61616161
+[init -> test-iso] 00001028: 61616161 61616161 61616161 61616161 61616161
+[init -> test-iso] 0000103c: 61616161 61616161 61616161 61616161 61616161
+[init -> test-iso]
+[init -> test-iso] 00010000: 62626262 62626262 62626262 62626262 62626262
+[init -> test-iso] 00010014: 62626262 62626262 62626262 62626262 62626262
+[init -> test-iso] 00010028: 62626262 62626262 62626262 62626262 62626262
+[init -> test-iso] 0001003c: 62626262 62626262 62626262 62626262 62626262
+[init -> test-iso]
+[init -> test-iso] 00020000: 63636363 63636363 63636363 63636363 63636363
+[init -> test-iso] 00020014: 63636363 63636363 63636363 63636363 63636363
+[init -> test-iso] 00020028: 63636363 63636363 63636363 63636363 63636363
+[init -> test-iso] 0002003c: 63636363 63636363 63636363 63636363 63636363
+[init -> test-iso]
+}
+
diff --git a/dde_rump/src/lib/rump/bootstrap.cc b/dde_rump/src/lib/rump/bootstrap.cc
new file mode 100644
index 000000000..5c706fe6f
--- /dev/null
+++ b/dde_rump/src/lib/rump/bootstrap.cc
@@ -0,0 +1,258 @@
+/*
+ * \brief Call initialization functions for all modules and components
+ * \author Sebastian Sumpf
+ * \date 2013-12-12
+ */
+
+/*
+ * Copyright (C) 2013-2014 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.
+ */
+
+extern "C" {
+#include
+#include
+#include
+}
+
+#include
+#include
+#include
+
+#include "dl_interface.h"
+
+extern "C" void wait_for_continue();
+
+#ifdef _LP64
+typedef Elf64_Dyn Elf_Dyn;
+typedef Elf64_Sym Elf_Sym;
+#else
+typedef Elf32_Dyn Elf_Dyn;
+typedef Elf32_Sym Elf_Sym;
+#endif
+
+static bool const verbose = false;
+
+
+static void *dl_main;
+
+struct Sym_tab
+{
+ link_map *map;
+
+ void const *dynamic_base = 0;
+ void const *sym_base = 0;
+
+ Elf_Addr str_tab = 0;
+ size_t sym_cnt = 0;
+ size_t out_cnt = 0;
+ size_t str_size = 0;
+
+ Elf_Sym *sym_tab;
+
+ Sym_tab(link_map *map) : map(map), dynamic_base(map->l_ld)
+ {
+ if (!dynamic_base) {
+ PERR("%s: base is bogus %lx", map->l_name, map->l_addr);
+ throw -1;
+ }
+
+ if (verbose)
+ PDBG("for %s at %lx\n", map->l_name, map->l_addr);
+
+ find_tables();
+
+ if (!sym_base) {
+ PERR("%s: could not find symbol table (sym_base %p)", map->l_name,
+ sym_base);
+ throw -2;
+ }
+
+ /* alloc memory for the tables */
+ alloc_memory();
+
+ /* file sym_tab and str_tab */
+ read_symbols();
+ }
+
+ ~Sym_tab()
+ {
+ if (sym_tab)
+ destroy(Genode::env()->heap(), sym_tab);
+ }
+
+
+ Elf_Sym const *elf_symbol(int index = 0)
+ {
+ Elf_Sym const *s = static_cast(sym_base);
+ return &s[index];
+ }
+
+ Elf_Dyn const *elf_dyn(int index = 0)
+ {
+ Elf_Dyn const *d = static_cast(dynamic_base);
+ return &d[index];
+ }
+
+ bool is_wanted(char const *name)
+ {
+ using namespace Genode;
+ return (!strcmp(name, "rump", 4) ||
+ !strcmp(name, "RUMP", 4) ||
+ !strcmp(name, "__", 2)) ? true : false;
+ }
+
+ /**
+ * Find symtab and strtab
+ */
+ void find_tables()
+ {
+ uint64_t dyn_tag = elf_dyn()->d_tag;
+ for (int i = 0;
+ dyn_tag != DT_NULL;
+ i++,
+ dyn_tag = elf_dyn(i)->d_tag) {
+
+ switch (dyn_tag) {
+ case DT_SYMTAB:
+ sym_base = (void *)(elf_dyn(i)->d_un.d_ptr + map->l_addr);
+ break;
+ case DT_STRTAB:
+ str_tab = elf_dyn(i)->d_un.d_ptr + map->l_addr;
+ break;
+ case DT_STRSZ:
+ str_size = elf_dyn(i)->d_un.d_ptr;
+ break;
+ case DT_HASH:
+ {
+ Elf_Symindx *hashtab = (Elf_Symindx *)(elf_dyn(i)->d_un.d_ptr +
+ map->l_addr);
+ sym_cnt = hashtab[1];
+ }
+ break;
+ case DT_SYMENT:
+ {
+ size_t sym_size = elf_dyn(i)->d_un.d_ptr;
+ if (sym_size != sizeof(Elf_Sym))
+ PWRN("Elf symbol size does not match binary %zx != elf %zx",
+ sym_size, sizeof(Elf_Sym));
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+ void alloc_memory()
+ {
+ sym_tab = (Elf_Sym *)Genode::env()->heap()->alloc(sizeof(Elf_Sym) * sym_cnt);
+ }
+
+ void read_symbols()
+ {
+ for (unsigned i = 0; i < sym_cnt; i++) {
+
+ Elf_Sym const *sym = elf_symbol(i);
+ if (sym->st_shndx == SHN_UNDEF || !sym->st_value)
+ continue;
+
+ char const *name = (char const *)sym->st_name + str_tab;
+ if (!is_wanted(name))
+ continue;
+
+ sym_tab[out_cnt] = *sym;
+ /* set absolute value */
+ sym_tab[out_cnt].st_value += map->l_addr;
+ if (verbose)
+ PDBG("Read symbol %s val: %x", name, sym_tab[out_cnt].st_value);
+ out_cnt++;
+ }
+ }
+
+ void rump_load(rump_symload_fn symload)
+ {
+ symload(sym_tab, sizeof(Elf_Sym) * out_cnt, (char *)str_tab, str_size);
+ }
+};
+
+
+char const *_filename(char const *path)
+{
+ int i;
+ int len = Genode::strlen(path);
+ for (i = len; i > 0 && path[i] != '/'; i--) ;
+ return path + i + 1;
+}
+
+/**
+ * Call init functions of libraries
+ */
+static void _dl_init(link_map const *map,
+ rump_modinit_fn mod_init,
+ rump_compload_fn comp_init)
+{
+ void *handle = dlopen(map->l_name, RTLD_LAZY);
+ if (!handle)
+ PERR ("Could not dlopen %s\n", map->l_name);
+
+ struct modinfo **mi_start, **mi_end;
+ struct rump_component **rc_start, **rc_end;
+
+ mi_start = (modinfo **)dlsym(handle, "__start_link_set_modules");
+ mi_end = (modinfo **)dlsym(handle, "__stop_link_set_modules");
+ if (verbose)
+ PDBG("MI: start: %p end: %p", mi_start, mi_end);
+ if (mi_start && mi_end)
+ mod_init(mi_start, (size_t)(mi_end-mi_start));
+
+ rc_start = (rump_component **)dlsym(handle, "__start_link_set_rump_components");
+ rc_end = (rump_component **)dlsym(handle, "__stop_link_set_rump_components");
+ if (verbose)
+ PDBG("RC: start: %p end: %p", rc_start, rc_end);
+ if (rc_start && rc_end) {
+ for (; rc_start < rc_end; rc_start++)
+ comp_init(*rc_start);
+ }
+}
+
+
+void rumpuser_dl_bootstrap(rump_modinit_fn domodinit, rump_symload_fn symload,
+ rump_compload_fn compload)
+{
+ /* open main program and request link map */
+ dl_main = dlopen(0, RTLD_NOW);
+
+ struct link_map *map;
+ if(dlinfo(dl_main, RTLD_DI_LINKMAP, &map)) {
+ PERR("Error: Could not retrieve linkmap from main program");
+ return;
+ }
+
+ for (; map->l_next; map = map->l_next) ;
+
+ struct link_map *curr_map;
+
+ for (curr_map = map; curr_map; curr_map = curr_map->l_prev)
+ if (!Genode::strcmp(_filename(curr_map->l_name), "rump", 4)) {
+ Sym_tab tab(curr_map);
+ /* load into rum kernel */
+ tab.rump_load(symload);
+ /* init modules and components */
+ _dl_init(curr_map, domodinit, compload);
+ }
+ PINF("BOOTSTRAP");
+}
+
+
+void * rumpuser_dl_globalsym(const char *symname)
+{
+
+ void *addr = dlsym(RTLD_DEFAULT, symname);
+
+ if (verbose)
+ PDBG("Lookup: %s addr %p", symname, addr);
+
+ return addr;
+}
diff --git a/dde_rump/src/lib/rump/dl_interface.h b/dde_rump/src/lib/rump/dl_interface.h
new file mode 100644
index 000000000..ccfa6235a
--- /dev/null
+++ b/dde_rump/src/lib/rump/dl_interface.h
@@ -0,0 +1,70 @@
+/*
+ * \brief DL interface to the dynamic linker (since we don't rely on libc)
+ *
+ * These "weak" function should never be reached, because they are
+ * intercepted by ouer dynamic linker, if you see an error message than
+ * you program might not be a dynamic one.
+ *
+ * \author Sebastian Sumpf
+ * \date 2013-13-13
+ */
+
+/*
+ * Copyright (C) 2013-2014 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 _DL_INTERFACE_H_
+#define _DL_INTERFACE_H_
+
+#include
+
+extern "C" {
+
+/**
+ * dlopen
+ */
+enum Open_mode { RTLD_LAZY = 1, RTLD_NOW = 2 };
+
+void __attribute__((weak))
+*dlopen(const char *name, int mode)
+{
+ PERR("dlopen: Local function called");
+ return 0;
+}
+
+/**
+ * dlinfo
+ */
+enum Reqeust { RTLD_DI_LINKMAP = 2 };
+
+struct link_map {
+ unsigned long l_addr; /* Base Address of library */
+ const char *l_name; /* Absolute Path to Library */
+ const void *l_ld; /* Pointer to .dynamic in memory */
+ struct link_map *l_next, *l_prev; /* linked list of of mapped libs */
+};
+
+int __attribute__((weak))
+dlinfo(void *handle, int request, void *p)
+{
+ PERR("dlinfo: Local function called");
+ return 0;
+}
+
+/**
+ * dlsym
+ */
+#define RTLD_DEFAULT ((void *)-2)
+
+void __attribute__((weak))
+*dlsym(void *handle, const char *name)
+{
+ PERR("dlsym: Local function called");
+ return 0;
+}
+
+} /* extern "C" */
+
+#endif /* _DL_INTERFACE_H_ */
diff --git a/dde_rump/src/lib/rump/dummies.cc b/dde_rump/src/lib/rump/dummies.cc
new file mode 100644
index 000000000..953e13b4d
--- /dev/null
+++ b/dde_rump/src/lib/rump/dummies.cc
@@ -0,0 +1,54 @@
+/**
+ * \brief Dummy functions
+ * \author Sebastian Sumpf
+ * \date 2013-12-06
+ */
+
+/*
+ * Copyright (C) 2013-2014 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
+
+extern "C" {
+
+enum {
+ SHOW_DUMMY = 1,
+};
+
+#define DUMMY(retval, name) \
+ int name(void) { \
+ if (SHOW_DUMMY) \
+ PDBG(#name " called (from %p) not implemented", __builtin_return_address(0)); \
+ return retval; \
+}
+
+#define DUMMY_RET(retval, name) \
+ int name(void) { \
+ return retval; \
+}
+
+DUMMY(-1, rumpuser_anonmmap)
+DUMMY(-1, rumpuser_close)
+DUMMY(-1, rumpuser_daemonize_begin)
+DUMMY(-1, rumpuser_daemonize_done)
+DUMMY(-1, rumpuser_dprintf)
+DUMMY(-1, rumpuser_exit)
+DUMMY(-1, rumpuser_iovread)
+DUMMY(-1, rumpuser_iovwrite)
+DUMMY(-1, rumpuser_kill)
+DUMMY(-1, rumpuser_sp_anonmmap)
+DUMMY(-1, rumpuser_sp_copyin)
+DUMMY(-1, rumpuser_sp_copyinstr)
+DUMMY(-1, rumpuser_sp_copyout)
+DUMMY(-1, rumpuser_sp_copyoutstr)
+DUMMY(-1, rumpuser_sp_fini)
+DUMMY(-1, rumpuser_sp_init)
+DUMMY(-1, rumpuser_sp_raise)
+DUMMY(-1, rumpuser_thread_exit)
+DUMMY(-1, rumpuser_thread_join)
+DUMMY(-1, rumpuser_unmap)
+} /* extern "C" */
diff --git a/dde_rump/src/lib/rump/hypercall.cc b/dde_rump/src/lib/rump/hypercall.cc
new file mode 100644
index 000000000..004212817
--- /dev/null
+++ b/dde_rump/src/lib/rump/hypercall.cc
@@ -0,0 +1,293 @@
+/**
+ * \brief Rump hypercall-interface implementation
+ * \author Sebastian Sumpf
+ * \author Josef Soentgen
+ * \date 2013-12-06
+ */
+
+/*
+ * Copyright (C) 2013-2014 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 "sched.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+extern "C" void wait_for_continue();
+enum { SUPPORTED_RUMP_VERSION = 17 };
+
+static bool verbose = false;
+
+/* upcalls to rump kernel */
+struct rumpuser_hyperup _rump_upcalls;
+
+
+/********************
+ ** Initialization **
+ ********************/
+
+int rumpuser_init(int version, const struct rumpuser_hyperup *hyp)
+{
+ PDBG("RUMP ver: %d", version);
+ if (version != SUPPORTED_RUMP_VERSION) {
+ PERR("Unsupported rump-kernel version (%d) - supported is %d)",
+ version, SUPPORTED_RUMP_VERSION);
+ return -1;
+ }
+
+ _rump_upcalls = *hyp;
+
+ /*
+ * Start 'Timeout_thread' so it does not get constructed concurrently (which
+ * causes one thread to spin in cxa_guard_aqcuire), making emulation *really*
+ * slow
+ */
+ Genode::Timeout_thread::alarm_timer();
+
+ return 0;
+}
+
+
+/*************
+ ** Threads **
+ *************/
+
+static Hard_context _main_thread("main thread", 0, 0, 0, false);
+
+static Hard_context *myself()
+{
+ Hard_context *h = dynamic_cast(Genode::Thread_base::myself());
+ return h ? h : &_main_thread;
+}
+
+
+Timer::Connection *Hard_context::timer()
+{
+ static Timer::Connection _timer;
+ return &_timer;
+}
+
+
+void rumpuser_curlwpop(int enum_rumplwpop, struct lwp *l)
+{
+ Hard_context *h = myself();
+ switch (enum_rumplwpop) {
+ case RUMPUSER_LWP_CREATE:
+ case RUMPUSER_LWP_DESTROY:
+ break;
+ case RUMPUSER_LWP_SET:
+ h->set_lwp(l);
+ break;
+ case RUMPUSER_LWP_CLEAR:
+ h->set_lwp(0);
+ break;
+ }
+}
+
+
+struct lwp * rumpuser_curlwp(void)
+{
+ return myself()->get_lwp();
+}
+
+
+int rumpuser_thread_create(func f, void *arg, const char *name,
+ int mustjoin, int priority, int cpui_dx, void **cookie)
+{
+ static int count = 0;
+
+ if (mustjoin)
+ *cookie = (void *)++count;
+
+ new (Genode::env()->heap()) Hard_context(name, f, arg, mustjoin ? count : 0);
+
+ return 0;
+}
+
+int errno;
+void rumpuser_seterrno(int e) { errno = e; }
+
+
+/*************************
+ ** Parameter retrieval **
+ *************************/
+
+int rumpuser_getparam(const char *name, void *buf, size_t buflen)
+{
+ /* support one cpu */
+ PDBG("%s", name);
+ if (!Genode::strcmp(name, "_RUMPUSER_NCPU")) {
+ Genode::strncpy((char *)buf, "1", 2);
+ return 0;
+ }
+
+ /* return out cool host name */
+ if (!Genode::strcmp(name, "_RUMPUSER_HOSTNAME")) {
+ Genode::strncpy((char *)buf, "rump4genode", 12);
+ return 0;
+ }
+
+ if (!Genode::strcmp(name, "RUMP_MEMLIMIT")) {
+
+ /* leave 2 MB for the Genode */
+ size_t rump_ram = Genode::env()->ram_session()->avail() - (2 * 1024 * 1024);
+
+ /* convert to string */
+ Genode::snprintf((char *)buf, buflen, "%zu", rump_ram);
+ PINF("Asserting rump kernel %zu KB of RAM", rump_ram / 1024);
+ return 0;
+ }
+
+ return -1;
+}
+
+
+/*************
+ ** Console **
+ *************/
+
+void rumpuser_putchar(int ch)
+{
+ static unsigned char buf[256];
+ static int count = 0;
+
+ buf[count++] = (unsigned char)ch;
+
+ if (ch == '\n') {
+ buf[count] = 0;
+ int nlocks;
+ if (myself() != &_main_thread)
+ rumpkern_unsched(&nlocks, 0);
+
+ PLOG("rump: %s", buf);
+
+ if (myself() != &_main_thread)
+ rumpkern_sched(nlocks, 0);
+
+ count = 0;
+ }
+}
+
+
+/************
+ ** Memory **
+ ************/
+
+struct Allocator_policy
+{
+ static int block()
+ {
+ int nlocks;
+
+ if (myself() != &_main_thread)
+ rumpkern_unsched(&nlocks, 0);
+ return nlocks;
+ }
+
+ static void unblock(int nlocks)
+ {
+ if (myself() != &_main_thread)
+ rumpkern_sched(nlocks, 0);
+ }
+};
+
+
+typedef Allocator::Fap<128 * 1024 * 1024, Allocator_policy> Rump_alloc;
+static Genode::Lock _alloc_lock;
+
+static Rump_alloc* allocator()
+{
+ static Rump_alloc _fap(true);
+ return &_fap;
+}
+
+int rumpuser_malloc(size_t len, int alignment, void **memp)
+{
+ Genode::Lock::Guard guard(_alloc_lock);
+
+ int align = Genode::log2(alignment);
+ *memp = allocator()->alloc(len, align);
+
+ if (verbose)
+ PWRN("ALLOC: p: %p, s: %zx, a: %d", *memp, len, align);
+
+
+ return *memp ? 0 : -1;
+}
+
+
+void rumpuser_free(void *mem, size_t len)
+{
+ Genode::Lock::Guard guard(_alloc_lock);
+
+ allocator()->free(mem, len);
+
+ if (verbose)
+ PWRN("FREE: p: %p, s: %zx", mem, len);
+}
+
+
+/************
+ ** Clocks **
+ ************/
+
+int rumpuser_clock_gettime(int enum_rumpclock, int64_t *sec, long *nsec)
+{
+ Hard_context *h = myself();
+ unsigned long t = h->timer()->elapsed_ms();
+ *sec = (int64_t)t / 1000;
+ *nsec = (t % 1000) * 1000;
+ return 0;
+}
+
+
+int rumpuser_clock_sleep(int enum_rumpclock, int64_t sec, long nsec)
+{
+ int nlocks;
+ unsigned int msec = 0;
+
+ Timer::Connection *timer = myself()->timer();
+
+ rumpkern_unsched(&nlocks, 0);
+ switch (enum_rumpclock) {
+ case RUMPUSER_CLOCK_RELWALL:
+ msec = sec * 1000 + nsec / (1000*1000UL);
+ break;
+ case RUMPUSER_CLOCK_ABSMONO:
+ msec = timer->elapsed_ms();
+ msec = ((sec * 1000) + (nsec / (1000 * 1000))) - msec;
+ break;
+ }
+
+ timer->msleep(msec);
+ rumpkern_sched(nlocks, 0);
+ return 0;
+}
+
+
+/*****************
+ ** Random pool **
+ *****************/
+
+int rumpuser_getrandom(void *buf, size_t buflen, int flags, size_t *retp)
+{
+ Timer::Connection *timer = myself()->timer();
+
+ uint8_t *rndbuf;
+ for (*retp = 0, rndbuf = (uint8_t *)buf; *retp < buflen; (*retp)++) {
+ *rndbuf++ = timer->elapsed_ms() & 0xff;
+ timer->msleep(timer->elapsed_ms() & 0xf);
+ }
+
+ return 0;
+}
+
diff --git a/dde_rump/src/lib/rump/io.cc b/dde_rump/src/lib/rump/io.cc
new file mode 100644
index 000000000..27c59a6a5
--- /dev/null
+++ b/dde_rump/src/lib/rump/io.cc
@@ -0,0 +1,342 @@
+/**
+ * \brief Connect rump kernel Genode's block interface
+ * \author Sebastian Sumpf
+ * \date 2013-12-16
+ */
+
+/*
+ * Copyright (C) 2013-2014 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 "sched.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+static const bool verbose = false;
+
+enum { GENODE_FD = 64 };
+
+struct Packet : Genode::List::Element
+{
+ Block::sector_t blk;
+ Genode::size_t cnt;
+ Block::Packet_descriptor::Opcode opcode;
+ void *data;
+ long offset;
+ rump_biodone_fn biodone;
+ void *donearg;
+ bool valid;
+ bool pending;
+ bool sync;
+};
+
+
+class Backend : public Hard_context
+{
+
+ private:
+
+ enum { COUNT = Block::Session::TX_QUEUE_SIZE };
+
+ Genode::Allocator_avl _alloc;
+ Block::Connection _session;
+ Genode::size_t _blk_size; /* block size of the device */
+ Block::sector_t _blk_cnt; /* number of blocks of device */
+ Block::Session::Operations _blk_ops;
+ Packet _p[COUNT];
+ Genode::Semaphore _alloc_sem;
+ Genode::Semaphore _packet_sem;
+ int _index_thread = 0;
+ int _index_client = 0;
+ Genode::Lock _alloc_lock;
+ bool _handle;
+ Genode::Signal_receiver _receiver;
+ Genode::Signal_dispatcher _disp_ack;
+ Genode::Signal_dispatcher _disp_submit;
+
+
+ Genode::List *_pending()
+ {
+ static Genode::List _p;
+ return &_p;
+ }
+
+ bool _have_pending()
+ {
+ return !!_pending()->first();
+ }
+
+ Packet *_find(Block::Packet_descriptor &packet)
+ {
+ Packet *p = _pending()->first();
+ while (p) {
+ if (p->offset == packet.offset())
+ return p;
+
+ p = p->next();
+ }
+
+ PERR("Pending packet not found");
+ return 0;
+ }
+
+ Packet *_dequeue()
+ {
+ int idx;
+ for (int i = 0; i < COUNT; i++) {
+ idx = (_index_thread + i) % COUNT;
+ if (_p[idx].valid && !_p[idx].pending) {
+ _index_thread = idx;
+ _p[idx].pending = true;
+ return &_p[idx];
+ }
+ }
+ PWRN("Dequeue returned 0");
+ return 0;
+ }
+
+
+ void _free(Packet *p)
+ {
+ p->valid = false;
+ p->pending = false;
+ _alloc_sem.up();
+ }
+
+ void _ready_to_submit(unsigned) { _handle = false; }
+
+ void _ack_avail(unsigned)
+ {
+ _handle = false;
+
+ while (_session.tx()->ack_avail()) {
+ Block::Packet_descriptor packet = _session.tx()->get_acked_packet();
+ Packet *p = _find(packet);
+
+ if (p->opcode == Block::Packet_descriptor::READ)
+ Genode::memcpy(p->data, _session.tx()->packet_content(packet),
+ packet.block_count() * _blk_size);
+
+
+ /* sync session if requested */
+ if (p->sync)
+ _session.sync();
+
+ int dummy;
+ if (verbose)
+ PDBG("BIO done p: %p bio %p", p, p->donearg);
+
+ rumpkern_sched(0, 0);
+ if (p->biodone)
+ p->biodone(p->donearg, p->cnt * _blk_size,
+ packet.succeeded() ? 0 : EIO);
+ rumpkern_unsched(&dummy, 0);
+
+ _session.tx()->release_packet(packet);
+ _pending()->remove(p);
+ _free(p);
+ }
+ }
+
+ void _handle_signal()
+ {
+ _handle = true;
+
+ while (_handle) {
+ Genode::Signal s = _receiver.wait_for_signal();
+ static_cast
+ (s.context())->dispatch(s.num());
+ }
+ }
+
+ protected:
+
+ void entry()
+ {
+ _rump_upcalls.hyp_schedule();
+ _rump_upcalls.hyp_lwproc_newlwp(0);
+ _rump_upcalls.hyp_unschedule();
+
+ while (true) {
+
+ while (_packet_sem.cnt() <= 0 && _have_pending())
+ _handle_signal();
+
+ _packet_sem.down();
+
+ while (!_session.tx()->ready_to_submit())
+ _handle_signal();
+
+ Packet *p = _dequeue();
+
+ /* zero or sync request */
+ if (!p->cnt) {
+
+ if (p->sync)
+ _session.sync();
+
+ _free(p);
+ continue;
+ }
+
+ for (bool done = false; !done;)
+ try {
+ Block::Packet_descriptor packet(
+ _session.dma_alloc_packet(p->cnt * _blk_size),
+ p->opcode, p->blk, p->cnt);
+ /* got packet copy data */
+ if (p->opcode == Block::Packet_descriptor::WRITE)
+ Genode::memcpy(_session.tx()->packet_content(packet),
+ p->data, p->cnt * _blk_size);
+ _session.tx()->submit_packet(packet);
+
+ /* mark as pending */
+ p->offset = packet.offset();
+ _pending()->insert(p);
+ done = true;
+ } catch(Block::Session::Tx::Source::Packet_alloc_failed) {
+ _handle_signal();
+ }
+ }
+ }
+
+ public:
+
+ Backend()
+ : Hard_context("block_io", 0, 0, 0, false),
+ _alloc(Genode::env()->heap()),
+ _session(&_alloc),
+ _alloc_sem(COUNT),
+ _disp_ack(_receiver, *this, &Backend::_ack_avail),
+ _disp_submit(_receiver, *this, &Backend::_ready_to_submit)
+ {
+ _session.tx_channel()->sigh_ack_avail(_disp_ack);
+ _session.tx_channel()->sigh_ready_to_submit(_disp_submit);
+ _session.info(&_blk_cnt, &_blk_size, &_blk_ops);
+ PDBG("Backend blk_size %zu", _blk_size);
+ Genode::memset(_p, 0, sizeof(_p));
+ start();
+ }
+
+ uint64_t block_count() const { return (uint64_t)_blk_cnt; }
+ size_t block_size() const { return (size_t)_blk_size; }
+
+ bool writable()
+ {
+ return _blk_ops.supported(Block::Packet_descriptor::WRITE);
+ }
+
+ Packet *alloc()
+ {
+ int idx;
+ _alloc_sem.down();
+ Genode::Lock::Guard guard(_alloc_lock);
+ for (int i = 0; i < COUNT; i++) {
+ idx = (_index_client + i) % COUNT;
+ if (!_p[idx].valid) {
+ _p[idx].valid = true;
+ _p[idx].pending = false;
+ _index_client = idx;
+ return &_p[idx];
+ }
+ }
+ PWRN("Alloc returned 0");
+ return 0;
+ }
+
+ void submit() { _packet_sem.up(); }
+};
+
+
+static Backend *backend()
+{
+ static Backend *_b = 0;
+
+ if (_b)
+ return _b;
+ try {
+ int nlocks;
+ rumpkern_unsched(&nlocks, 0);
+ _b = new(Genode::env()->heap())Backend();
+ rumpkern_sched(nlocks, 0);
+ } catch (Genode::Parent::Service_denied) {
+ PERR("Opening block session denied!");
+ }
+ return _b;
+}
+
+
+int rumpuser_getfileinfo(const char *name, uint64_t *size, int *type)
+{
+ if (Genode::strcmp(GENODE_BLOCK_SESSION, name))
+ return ENXIO;
+
+ if (type)
+ *type = RUMPUSER_FT_BLK;
+
+ if (size)
+ *size = backend()->block_count() * backend()->block_size();
+
+ return 0;
+}
+
+
+int rumpuser_open(const char *name, int mode, int *fdp)
+{
+ if (!(mode & RUMPUSER_OPEN_BIO || Genode::strcmp(GENODE_BLOCK_SESSION, name)))
+ return ENXIO;
+
+ /* check for writable */
+ if ((mode & RUMPUSER_OPEN_ACCMODE) && !backend()->writable())
+ return EROFS;
+
+ *fdp = GENODE_FD;
+ return 0;
+}
+
+
+void rumpuser_bio(int fd, int op, void *data, size_t dlen, int64_t off,
+ rump_biodone_fn biodone, void *donearg)
+{
+ int nlocks;
+
+ rumpkern_unsched(&nlocks, 0);
+
+ Packet *p = backend()->alloc();
+
+#if 0
+ PDBG("fd: %d op: %d len: %zu off: %lx p %p bio %p sync %u", fd, op, dlen, off,
+ p, donearg, !!(op & RUMPUSER_BIO_SYNC));
+#endif
+
+ p->opcode= op & RUMPUSER_BIO_WRITE ? Block::Packet_descriptor::WRITE :
+ Block::Packet_descriptor::READ;
+
+ p->cnt = dlen / backend()->block_size();
+ p->blk = off / backend()->block_size();
+ p->data = data;
+ p->biodone = biodone;
+ p->donearg = donearg;
+ p->sync = !!(op & RUMPUSER_BIO_SYNC);
+ backend()->submit();
+ rumpkern_sched(nlocks, 0);
+}
+
+
+void rump_io_backend_sync()
+{
+ /* send empty packet with sync request */
+ Packet *p = backend()->alloc();
+ p->cnt = 0;
+ p->sync = true;
+ backend()->submit();
+}
+
diff --git a/dde_rump/src/lib/rump/sched.h b/dde_rump/src/lib/rump/sched.h
new file mode 100644
index 000000000..bdeb2db95
--- /dev/null
+++ b/dde_rump/src/lib/rump/sched.h
@@ -0,0 +1,43 @@
+/**
+ * \brief Rump-scheduling upcalls
+ * \author Sebastian Sump
+ * \date 2013-12-06
+ */
+
+/*
+ * Copyright (C) 2013-2014 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 _SCHED_H_
+#define _SCHED_H_
+
+extern "C" {
+#include
+#include
+#include
+#include
+#include
+}
+
+#include
+
+/* upcalls to rump kernel */
+extern struct rumpuser_hyperup _rump_upcalls;
+
+static inline void
+rumpkern_unsched(int *nlocks, void *interlock)
+{
+ _rump_upcalls.hyp_backend_unschedule(0, nlocks, interlock);
+}
+
+
+static inline void
+rumpkern_sched(int nlocks, void *interlock)
+{
+ _rump_upcalls.hyp_backend_schedule(nlocks, interlock);
+}
+
+#endif /* _SCHED_H_ */
diff --git a/dde_rump/src/lib/rump/sync.cc b/dde_rump/src/lib/rump/sync.cc
new file mode 100644
index 000000000..805af7e64
--- /dev/null
+++ b/dde_rump/src/lib/rump/sync.cc
@@ -0,0 +1,503 @@
+/**
+ * \brief Rump-synchronization primitives
+ * \author Sebastian Sumpf
+ * \author Christian Prochaska (conditional variables)
+ * \date 2014-01-13
+ */
+
+/*
+ * Copyright (C) 2014 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.
+ */
+
+extern "C" {
+#include
+}
+#include
+#include "sched.h"
+
+
+/*************
+ ** Mutexes **
+ *************/
+
+struct rumpuser_mtx
+{
+ Genode::Semaphore sem;
+ Genode::Lock counter_lock;
+ struct lwp *owner;
+ int flags;
+
+ rumpuser_mtx(int flags) : sem(1), owner(0), flags(flags) { }
+
+
+ bool down(bool try_lock = false)
+ {
+ counter_lock.lock();
+
+ if (sem.cnt() > 1)
+ PERR("SEM cnt > 1");
+
+ bool locked = sem.cnt() <= 0;
+
+ counter_lock.unlock();
+
+ if (locked && try_lock)
+ return false;
+
+ sem.down();
+ set_owner();
+
+ return true;
+ }
+
+ void up()
+ {
+ Genode::Lock::Guard guard(counter_lock);
+ clear_owner();
+ sem.up();
+ }
+
+ bool try_lock()
+ {
+ return down(true);
+ }
+
+ void set_owner()
+ {
+ if (flags & RUMPUSER_MTX_KMUTEX) {
+ if(owner != 0) {
+ PERR("OWNER != 0 %d", sem.cnt());
+ }
+ owner = rumpuser_curlwp();
+ }
+ }
+
+ void clear_owner()
+ {
+ if (flags & RUMPUSER_MTX_KMUTEX) {
+
+ if(owner == 0) {
+ PERR("OWNER 0");
+ }
+ owner = 0;
+ }
+ }
+};
+
+
+void rumpuser_mutex_init(struct rumpuser_mtx **mtxp, int flags)
+{
+ *mtxp = new(Genode::env()->heap()) rumpuser_mtx(flags);
+}
+
+
+void rumpuser_mutex_owner(struct rumpuser_mtx *mtx, struct lwp **lp)
+{
+ *lp = mtx->owner;
+}
+
+
+void rumpuser_mutex_enter_nowrap(struct rumpuser_mtx *mtx)
+{
+ mtx->down();
+}
+
+
+void rumpuser_mutex_enter(struct rumpuser_mtx *mtx)
+{
+ if (mtx->flags & RUMPUSER_MTX_SPIN) {
+ rumpuser_mutex_enter_nowrap(mtx);
+ return;
+ }
+
+ if (!mtx->try_lock()) {
+ int nlocks;
+ rumpkern_unsched(&nlocks, 0);
+ mtx->down();
+ rumpkern_sched(nlocks, 0);
+ }
+}
+
+
+int rumpuser_mutex_tryenter(struct rumpuser_mtx *mtx)
+{
+ return mtx->try_lock() ? 0 : 1;
+}
+
+
+void rumpuser_mutex_exit(struct rumpuser_mtx *mtx)
+{
+ mtx->up();
+}
+
+
+void rumpuser_mutex_destroy(struct rumpuser_mtx *mtx)
+{
+ destroy(Genode::env()->heap(), mtx);
+}
+
+
+/***************************
+ ** Conditional variables **
+ ***************************/
+
+struct timespec {
+ long tv_sec; /* seconds */
+ long tv_nsec;/* nanoseconds */
+};
+
+
+static unsigned long timespec_to_ms(const struct timespec ts)
+{
+ return (ts.tv_sec * 1000) + (ts.tv_nsec / (1000 * 1000));
+}
+
+
+struct Cond
+{
+ int num_waiters;
+ int num_signallers;
+ Genode::Lock counter_lock;
+ Genode::Timed_semaphore signal_sem;
+ Genode::Semaphore handshake_sem;
+
+ Cond() : num_waiters(0), num_signallers(0) { }
+
+ int timedwait(struct rumpuser_mtx *mutex,
+ const struct timespec *abstime)
+ {
+ using namespace Genode;
+ int result = 0;
+ Alarm::Time timeout = 0;
+
+ counter_lock.lock();
+ num_waiters++;
+ counter_lock.unlock();
+
+ mutex->up();
+
+ if (!abstime)
+ signal_sem.down();
+ else {
+ struct timespec currtime;
+ rumpuser_clock_gettime(0, (int64_t *)&currtime.tv_sec, &currtime.tv_nsec);
+ unsigned long abstime_ms = timespec_to_ms(*abstime);
+ unsigned long currtime_ms = timespec_to_ms(currtime);
+ if (abstime_ms > currtime_ms)
+ timeout = abstime_ms - currtime_ms;
+ try {
+ signal_sem.down(timeout);
+ } catch (Timeout_exception) {
+ result = -2;
+ }
+ catch (Nonblocking_exception) {
+ result = 0;
+ }
+ }
+
+ counter_lock.lock();
+ if (num_signallers > 0) {
+ if (result == -2) /* timeout occured */
+ signal_sem.down();
+ handshake_sem.up();
+ --num_signallers;
+ }
+ num_waiters--;
+ counter_lock.unlock();
+
+ mutex->down();
+
+ return result == -2 ? ETIMEDOUT : 0;
+ }
+
+ int wait(struct rumpuser_mtx *mutex)
+ {
+ return timedwait(mutex, 0);
+ }
+
+ int signal()
+ {
+ counter_lock.lock();
+ if (num_waiters > num_signallers) {
+ ++num_signallers;
+ signal_sem.up();
+ counter_lock.unlock();
+ handshake_sem.down();
+ } else
+ counter_lock.unlock();
+ return 0;
+ }
+
+ int broadcast()
+ {
+ counter_lock.lock();
+ if (num_waiters > num_signallers) {
+ int still_waiting = num_waiters - num_signallers;
+ num_signallers = num_waiters;
+ for (int i = 0; i < still_waiting; i++)
+ signal_sem.up();
+ counter_lock.unlock();
+ for (int i = 0; i < still_waiting; i++)
+ handshake_sem.down();
+ } else
+ counter_lock.unlock();
+
+ return 0;
+ }
+};
+
+
+struct rumpuser_cv {
+ Cond cond;
+};
+
+
+void rumpuser_cv_init(struct rumpuser_cv **cv)
+{
+ *cv = new(Genode::env()->heap()) rumpuser_cv();
+}
+
+
+void rumpuser_cv_destroy(struct rumpuser_cv *cv)
+{
+ destroy(Genode::env()->heap(), cv);
+}
+
+
+static void cv_unschedule(struct rumpuser_mtx *mtx, int *nlocks)
+{
+ rumpkern_unsched(nlocks, mtx);
+}
+
+
+static void cv_reschedule(struct rumpuser_mtx *mtx, int nlocks)
+{
+
+ /*
+ * If the cv interlock is a spin mutex, we must first release
+ * the mutex that was reacquired by _pth_cond_wait(),
+ * acquire the CPU context and only then relock the mutex.
+ * This is to preserve resource allocation order so that
+ * we don't deadlock. Non-spinning mutexes don't have this
+ * problem since they don't use a hold-and-wait approach
+ * to acquiring the mutex wrt the rump kernel CPU context.
+ *
+ * The more optimal solution would be to rework rumpkern_sched()
+ * so that it's possible to tell the scheduler
+ * "if you need to block, drop this lock first", but I'm not
+ * going poking there without some numbers on how often this
+ * path is taken for spin mutexes.
+ */
+ if ((mtx->flags & (RUMPUSER_MTX_SPIN | RUMPUSER_MTX_KMUTEX)) ==
+ (RUMPUSER_MTX_SPIN | RUMPUSER_MTX_KMUTEX)) {
+ mtx->up();
+ rumpkern_sched(nlocks, mtx);
+ rumpuser_mutex_enter_nowrap(mtx);
+ } else {
+ rumpkern_sched(nlocks, mtx);
+ }
+}
+
+
+void rumpuser_cv_wait(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx)
+{
+ int nlocks;
+
+ cv_unschedule(mtx, &nlocks);
+ cv->cond.wait(mtx);
+ cv_reschedule(mtx, nlocks);
+}
+
+
+void rumpuser_cv_wait_nowrap(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx)
+{
+ cv->cond.wait(mtx);
+}
+
+
+int rumpuser_cv_timedwait(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx,
+ int64_t sec, int64_t nsec)
+{
+ struct timespec ts;
+ int rv, nlocks;
+
+ /*
+ * Get clock already here, just in case we will be put to sleep
+ * after releasing the kernel context.
+ *
+ * The condition variables should use CLOCK_MONOTONIC, but since
+ * that's not available everywhere, leave it for another day.
+ */
+ rumpuser_clock_gettime(0, (int64_t *)&ts.tv_sec, &ts.tv_nsec);
+
+ cv_unschedule(mtx, &nlocks);
+
+ ts.tv_sec += sec;
+ ts.tv_nsec += nsec;
+ if (ts.tv_nsec >= 1000*1000*1000) {
+ ts.tv_sec++;
+ ts.tv_nsec -= 1000*1000*1000;
+ }
+
+ rv = cv->cond.timedwait(mtx, &ts);
+
+ cv_reschedule(mtx, nlocks);
+
+ return rv;
+}
+
+
+void rumpuser_cv_signal(struct rumpuser_cv *cv)
+{
+ cv->cond.signal();
+}
+
+
+void rumpuser_cv_broadcast(struct rumpuser_cv *cv)
+{
+ cv->cond.broadcast();
+}
+
+
+void rumpuser_cv_has_waiters(struct rumpuser_cv *cv, int *nwaiters)
+{
+ *nwaiters = cv->cond.num_waiters;
+}
+
+
+/*********************
+ ** Read/write lock **
+ *********************/
+
+struct Rw_lock {
+
+ Genode::Semaphore _lock;
+ Genode::Lock _inc;
+ Genode::Lock _write;
+
+ int _read;
+
+ Rw_lock() : _lock(1), _read(0) {}
+
+ bool read_lock(bool try_lock)
+ {
+ Genode::Lock::Guard guard(_inc);
+
+ if (_read > 0) {
+ _read++;
+ return true;
+ }
+
+ bool locked = lock(true);
+
+ if (locked) {
+ _read = 1;
+ return true;
+ }
+
+ if (try_lock)
+ return false;
+
+ lock(false);
+ _read = 1;
+ return true;
+ }
+
+ void read_unlock()
+ {
+ Genode::Lock::Guard guard(_inc);
+ if (--_read == 0)
+ unlock();
+ }
+
+ bool lock(bool try_lock)
+ {
+ Genode::Lock::Guard guard(_write);
+ if (_lock.cnt() > 0) {
+ _lock.down();
+ return true;
+ }
+
+ if (try_lock)
+ return false;
+
+ _lock.down();
+ return true;
+ }
+
+ void unlock()
+ {
+ Genode::Lock::Guard guard(_write);
+ _lock.up();
+ }
+
+ int readers() { return _read; }
+ int writer() { return (_lock.cnt() <= 0 && !_read) ? 1 : 0; }
+};
+
+
+struct rumpuser_rw
+{
+ Rw_lock rw;
+};
+
+
+void rumpuser_rw_init(struct rumpuser_rw **rw)
+{
+ *rw = new(Genode::env()->heap()) rumpuser_rw();
+}
+
+
+void rumpuser_rw_enter(int enum_rumprwlock, struct rumpuser_rw *rw)
+{
+ if (enum_rumprwlock == RUMPUSER_RW_WRITER)
+ rw->rw.lock(false);
+ else
+ rw->rw.read_lock(false);
+}
+
+
+int rumpuser_rw_tryenter(int enum_rumprwlock, struct rumpuser_rw *rw)
+{
+ bool locked = enum_rumprwlock == RUMPUSER_RW_WRITER ?
+ rw->rw.lock(true) : rw->rw.read_lock(true);
+
+ return locked ? 0 : 1;
+}
+
+
+int rumpuser_rw_tryupgrade(struct rumpuser_rw *rw)
+{
+ return 1;
+}
+
+
+void rumpuser_rw_downgrade(struct rumpuser_rw *rw)
+{
+}
+
+
+void rumpuser_rw_exit(struct rumpuser_rw *rw)
+{
+ if (rw->rw.readers())
+ rw->rw.read_unlock();
+ else
+ rw->rw.unlock();
+}
+
+
+void rumpuser_rw_held(int enum_rumprwlock, struct rumpuser_rw *rw, int *rv)
+{
+ *rv = enum_rumprwlock == RUMPUSER_RW_WRITER ? rw->rw.writer() :
+ rw->rw.readers();
+}
+
+
+void rumpuser_rw_destroy(struct rumpuser_rw *rw)
+{
+ destroy(Genode::env()->heap(), rw);
+}
+
diff --git a/dde_rump/src/platform/rump.ld b/dde_rump/src/platform/rump.ld
new file mode 100644
index 000000000..d04c194fe
--- /dev/null
+++ b/dde_rump/src/platform/rump.ld
@@ -0,0 +1,32 @@
+/*
+ * \brief Additonial sections required by all rump libraries
+ *
+ * Modified version of original linker script
+ *
+ * \author Sebastiasn Sumpf
+ * \date 2013-12-12
+ */
+
+SECTIONS
+{
+ .rump_modules :
+ {
+ __start_link_set_modules = .;
+ KEEP(*(link_set_modules));
+ __stop_link_set_modules = .;
+ } : rw
+
+ .rump_domains :
+ {
+ __start_link_set_domains = .;
+ KEEP(*(link_set_domains));
+ __stop_link_set_domains = .;
+ } : rw
+
+ .rump_components :
+ {
+ __start_link_set_rump_components = .;
+ KEEP(*(link_set_rump_components));
+ __stop_link_set_rump_components = .;
+ } : rw
+}
diff --git a/dde_rump/src/server/rump_fs/directory.h b/dde_rump/src/server/rump_fs/directory.h
new file mode 100644
index 000000000..c03d09532
--- /dev/null
+++ b/dde_rump/src/server/rump_fs/directory.h
@@ -0,0 +1,254 @@
+/**
+ * \brief File-system directory node
+ * \author Norman Feske
+ * \author Christian Helmuth
+ * \author Sebastian Sumpf
+ * \date 2013-11-11
+ */
+
+/*
+ * Copyright (C) 2013-2014 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 _DIRECTORY_H_
+#define _DIRECTORY_H_
+
+/* Genode include */
+#include
+
+/* local includes */
+#include "node.h"
+#include "util.h"
+#include "file.h"
+#include "symlink.h"
+
+namespace File_system {
+ class Directory;
+}
+
+class File_system::Directory : public Node
+{
+ private:
+
+ enum { BUFFER_SIZE = 4096 };
+
+ typedef Genode::Path Path;
+
+ int _fd;
+ Path _path;
+ Allocator &_alloc;
+
+ unsigned long _inode(char const *path, bool create)
+ {
+ int ret;
+
+ if (create) {
+ mode_t ugo = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+ ret = rump_sys_mkdir(path, ugo);
+ if (ret == -1)
+ throw No_space();
+ }
+
+ struct stat s;
+
+ ret = rump_sys_lstat(path, &s);
+ if (ret == -1)
+ throw Lookup_failed();
+ return s.st_ino;
+ }
+
+ int _open(char const *path)
+ {
+ struct stat s;
+ int ret = rump_sys_lstat(path, &s);
+ if (ret == -1 || !S_ISDIR(s.st_mode))
+ throw Lookup_failed();
+
+ int fd = rump_sys_open(path, O_RDONLY);
+ if (fd == -1)
+ throw Lookup_failed();
+
+ return fd;
+ }
+
+ static char *_buffer()
+ {
+ /* buffer for directory entries */
+ static char buf[BUFFER_SIZE];
+ return buf;
+ }
+
+ public:
+
+ Directory(Allocator &alloc, char const *path, bool create)
+ :
+ Node(_inode(path, create)),
+ _fd(_open(path)),
+ _path(path, "./"),
+ _alloc(alloc)
+ {
+ Node::name(basename(path));
+ }
+
+ virtual ~Directory()
+ {
+ rump_sys_close(_fd);
+ }
+
+ File * file(char const *name, Mode mode, bool create)
+ {
+ return new (&_alloc) File(_fd, name, mode, create);
+ }
+
+ Symlink * symlink(char const *name, bool create)
+ {
+ return new (&_alloc) Symlink(_path.base(), name, create);
+ }
+
+ Directory * subdir(char const *path, bool create)
+ {
+ Path dir_path(path, _path.base());
+ Directory *dir = new (&_alloc) Directory(_alloc, dir_path.base(), create);
+ return dir;
+ }
+
+ Node * node(char const *path)
+ {
+ Path node_path(path, _path.base());
+
+ struct stat s;
+ int ret = rump_sys_lstat(node_path.base(), &s);
+ if (ret == -1)
+ throw Lookup_failed();
+
+ Node *node = 0;
+
+ if (S_ISDIR(s.st_mode))
+ node = new (&_alloc) Directory(_alloc, node_path.base(), false);
+ else if (S_ISREG(s.st_mode))
+ node = new (&_alloc) File(node_path.base(), STAT_ONLY);
+ else if (S_ISLNK(s.st_mode))
+ node = new (&_alloc)Symlink(node_path.base());
+ else
+ throw Lookup_failed();
+
+ return node;
+ }
+
+ size_t read(char *dst, size_t len, seek_off_t seek_offset)
+ {
+ if (len < sizeof(Directory_entry)) {
+ PERR("read buffer too small for directory entry");
+ return 0;
+ }
+
+ if (seek_offset % sizeof(Directory_entry)) {
+ PERR("seek offset not aligned to sizeof(Directory_entry)");
+ return 0;
+ }
+
+ seek_off_t index = seek_offset / sizeof(Directory_entry);
+
+ int bytes;
+ rump_sys_lseek(_fd, 0, SEEK_SET);
+
+ struct dirent *dent = 0;
+ seek_off_t i = 0;
+ char *buf = _buffer();
+ do {
+ bytes = rump_sys_getdents(_fd, buf, BUFFER_SIZE);
+ void *current, *end;
+ for (current = buf, end = &buf[bytes];
+ current < end;
+ current = _DIRENT_NEXT((dirent *)current), i++)
+ if (i == index) {
+ dent = (dirent *)current;
+ break;
+ }
+ } while(bytes && !dent);
+
+ if (!dent)
+ return 0;
+
+ /*
+ * Build absolute path, this becomes necessary as our 'Path' class strips
+ * trailing dots, which will not work for '.' and '..' directories.
+ */
+ size_t base_len = strlen(_path.base());
+ char path[dent->d_namlen + base_len + 2];
+
+ memcpy(path, _path.base(), base_len);
+ path[base_len] = '/';
+ strncpy(path + base_len + 1, dent->d_name, dent->d_namlen + 1);
+
+ /*
+ * We cannot use 'd_type' member of 'dirent' here since the EXT2
+ * implementation sets the type to unkown. Hence we use stat.
+ */
+ struct stat s;
+ rump_sys_lstat(path, &s);
+
+ Directory_entry *e = (Directory_entry *)(dst);
+ if (S_ISDIR(s.st_mode))
+ e->type = Directory_entry::TYPE_DIRECTORY;
+ else if (S_ISREG(s.st_mode))
+ e->type = Directory_entry::TYPE_FILE;
+ else if (S_ISLNK(s.st_mode))
+ e->type = Directory_entry::TYPE_SYMLINK;
+ else
+ return 0;
+
+ strncpy(e->name, dent->d_name, dent->d_namlen + 1);
+ return sizeof(Directory_entry);
+ }
+
+ size_t write(char const *src, size_t len, seek_off_t seek_offset)
+ {
+ /* writing to directory nodes is not supported */
+ return 0;
+ }
+
+ size_t num_entries() const
+ {
+ int bytes = 0;
+ int count = 0;
+
+ rump_sys_lseek(_fd, 0, SEEK_SET);
+
+ char *buf = _buffer();
+ do {
+ bytes = rump_sys_getdents(_fd, buf, BUFFER_SIZE);
+ void *current, *end;
+ for (current = buf, end = &buf[bytes];
+ current < end;
+ current = _DIRENT_NEXT((dirent *)current), count++) { }
+ } while(bytes);
+
+ return count;
+ }
+
+ void unlink(char const *path)
+ {
+ Path node_path(path, _path.base());
+
+ struct stat s;
+ int ret = rump_sys_lstat(node_path.base(), &s);
+ if (ret == -1)
+ throw Lookup_failed();
+
+ if (S_ISDIR(s.st_mode))
+ ret = rump_sys_rmdir(node_path.base());
+ else if (S_ISREG(s.st_mode) || S_ISLNK(s.st_mode))
+ ret = rump_sys_unlink(node_path.base());
+ else
+ throw Lookup_failed();
+
+ if (ret == -1)
+ PERR("Error during unlink of %s", node_path.base());
+ }
+};
+
+#endif /* _DIRECTORY_H_ */
diff --git a/dde_rump/src/server/rump_fs/file.h b/dde_rump/src/server/rump_fs/file.h
new file mode 100644
index 000000000..38a4923c2
--- /dev/null
+++ b/dde_rump/src/server/rump_fs/file.h
@@ -0,0 +1,154 @@
+/**
+ * \brief File node
+ * \author Norman Feske
+ * \author Christian Helmuth
+ * \auhtor Sebastian Sumpf
+ * \date 2013-11-11
+ */
+
+/*
+ * Copyright (C) 2013-2014 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 _FILE_H_
+#define _FILE_H_
+
+#include "node.h"
+#include "util.h"
+
+namespace File_system {
+ class File;
+}
+
+class File_system::File : public Node
+{
+ private:
+
+ int _fd;
+
+ int _access_mode(Mode const &mode)
+ {
+ switch (mode) {
+ case STAT_ONLY:
+ case READ_ONLY: return O_RDONLY;
+ case WRITE_ONLY: return O_WRONLY;
+ case READ_WRITE: return O_RDWR;
+ default: return O_RDONLY;
+ }
+ }
+
+ unsigned long _inode(int dir, char const *name, bool create)
+ {
+ int ret;
+
+ if (create) {
+ mode_t ugo = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+ ret = rump_sys_mknodat(dir, name, S_IFREG | ugo, 0);
+ if (ret == -1 && errno != EEXIST)
+ throw No_space();
+ }
+
+ struct stat s;
+
+ ret = rump_sys_fstatat(dir, name, &s, 0);
+ if (ret == -1)
+ throw Lookup_failed();
+
+ return s.st_ino;
+ }
+
+ unsigned long _inode_path(char const *path)
+ {
+ int ret;
+ struct stat s;
+
+ ret = rump_sys_stat(path, &s);
+ if (ret == -1)
+ throw Lookup_failed();
+
+ return s.st_ino;
+ }
+
+ int _open(int dir, char const *name, Mode mode)
+ {
+ int fd = rump_sys_openat(dir, name, _access_mode(mode));
+ if (fd == -1)
+ throw Lookup_failed();
+
+ return fd;
+ }
+
+ int _open_path(char const *path, Mode mode)
+ {
+ int fd = rump_sys_open(path, _access_mode(mode));
+ if (fd == -1)
+ throw Lookup_failed();
+
+ return fd;
+ }
+
+ public:
+
+ File(int dir,
+ char const *name,
+ Mode mode,
+ bool create)
+ : Node(_inode(dir, name, create)),
+ _fd(_open(dir, name, mode))
+ {
+ Node::name(name);
+ }
+
+ File(char const *path, Mode mode)
+ :
+ Node(_inode_path(path)),
+ _fd(_open_path(path, mode))
+ {
+ Node::name(basename(path));
+ }
+
+ virtual ~File() { rump_sys_close(_fd); }
+
+ size_t read(char *dst, size_t len, seek_off_t seek_offset)
+ {
+ ssize_t ret = rump_sys_pread(_fd, dst, len, seek_offset);
+
+ return ret == -1 ? 0 : ret;
+ }
+
+ size_t write(char const *src, size_t len, seek_off_t seek_offset)
+ {
+ /* should we append? */
+ if (seek_offset == ~0ULL) {
+ off_t off = rump_sys_lseek(_fd, 0, SEEK_END);
+ if (off == -1)
+ return 0;
+ seek_offset = off;
+ }
+
+ ssize_t ret = rump_sys_pwrite(_fd, src, len, seek_offset);
+ return ret == -1 ? 0 : ret;
+ }
+
+ file_size_t length() const
+ {
+ struct stat s;
+
+ if(rump_sys_fstat(_fd, &s) < 0)
+ return 0;
+
+ return s.st_size;
+ }
+
+ void truncate(file_size_t size)
+ {
+ rump_sys_ftruncate(_fd, size);
+
+ mark_as_updated();
+ }
+};
+
+#endif /* _FILE_H_ */
diff --git a/dde_rump/src/server/rump_fs/file_system.cc b/dde_rump/src/server/rump_fs/file_system.cc
new file mode 100644
index 000000000..89e7f8233
--- /dev/null
+++ b/dde_rump/src/server/rump_fs/file_system.cc
@@ -0,0 +1,171 @@
+/*
+ * \brief Rump initialization
+ * \author Sebastian Sumpf
+ * \date 2014-01-17
+ */
+
+/*
+ * Copyright (C) 2014 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 "file_system.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+/**
+ * We define our own fs arg structure to fit all sizes, we assume that 'fspec'
+ * is the only valid argument and all other fields are unused.
+ */
+struct fs_args
+{
+ char *fspec;
+ char pad[150];
+
+ fs_args() { Genode::memset(pad, 0, sizeof(pad)); }
+};
+
+namespace File_system {
+ class Sync;
+};
+
+static char const *fs_types[] = { RUMP_MOUNT_CD9660, RUMP_MOUNT_EXT2FS,
+ RUMP_MOUNT_FFS, RUMP_MOUNT_MSDOS,
+ RUMP_MOUNT_NFS, RUMP_MOUNT_NTFS,
+ RUMP_MOUNT_SMBFS, RUMP_MOUNT_UDF, 0 };
+
+static char _fs_type[10];
+static bool _supports_symlinks;
+
+static bool _check_type(char const *type)
+{
+ for (int i = 0; fs_types[i]; i++)
+ if (!Genode::strcmp(type, fs_types[i]))
+ return true;
+ return false;
+}
+
+
+static void _print_types()
+{
+ PERR("fs types:");
+ for (int i = 0; fs_types[i]; i++)
+ PERR("\t%s", fs_types[i]);
+}
+
+
+static bool check_symlinks()
+{
+ if (!Genode::strcmp(_fs_type, RUMP_MOUNT_EXT2FS))
+ return true;
+
+ if (!Genode::strcmp(_fs_type, RUMP_MOUNT_FFS))
+ return true;
+
+ return false;
+}
+
+
+static bool check_read_only()
+{
+ if (!Genode::strcmp(_fs_type, RUMP_MOUNT_CD9660))
+ return true;
+
+ return false;
+}
+
+
+class File_system::Sync : public Genode::Thread<1024 * sizeof(Genode::addr_t)>
+{
+ private:
+
+ Timer::Connection _timer;
+ Genode::Signal_rpc_member _sync_dispatcher;
+
+ void _process_sync(unsigned)
+ {
+ /* sync through front-end */
+ rump_sys_sync();
+ /* sync Genode back-end */
+ rump_io_backend_sync();
+ }
+
+ protected:
+
+ void entry()
+ {
+ while (1) {
+ _timer.msleep(1000);
+ /* send sync request, this goes to server entry point thread */
+ Genode::Signal_transmitter(_sync_dispatcher).submit();
+ }
+ }
+
+ public:
+
+ Sync(Server::Entrypoint &ep)
+ :
+ Thread("rump_fs_sync"),
+ _sync_dispatcher(ep, *this, &Sync::_process_sync)
+ {
+ start();
+ }
+};
+
+
+void File_system::init(Server::Entrypoint &ep)
+{
+ if (!Genode::config()->xml_node().attribute("fs").value(_fs_type, 10) ||
+ !_check_type(_fs_type)) {
+ PERR("Invalid or no file system given (use \'\"/>)");
+ _print_types();
+ throw Genode::Exception();
+ }
+ PINF("Using %s as file system", _fs_type);
+
+ /* start rump kernel */
+ rump_init();
+
+ /* register block device */
+ rump_pub_etfs_register(GENODE_DEVICE, GENODE_BLOCK_SESSION, RUMP_ETFS_BLK);
+
+ /* mount into extra-terrestrial-file system */
+ struct fs_args args;
+ int opts = check_read_only() ? RUMP_MNT_RDONLY : 0;
+
+ args.fspec = (char *)GENODE_DEVICE;
+ if (rump_sys_mount(_fs_type, "/", opts, &args, sizeof(args)) == -1) {
+ PERR("Mounting '%s' file system failed (errno %u)", _fs_type, errno);
+ throw Genode::Exception();
+ }
+
+ /* check support for symlinks */
+ _supports_symlinks = check_symlinks();
+
+ new (Genode::env()->heap()) Sync(ep);
+}
+
+
+bool File_system::supports_symlinks() { return _supports_symlinks; }
+
+
+/*
+ * On some platforms we end-up pulling in string.h prototypes
+ */
+extern "C" void *memcpy(void *d, void *s, size_t n)
+{
+ return Genode::memcpy(d, s, n);
+}
+
+
+extern "C" void *memset(void *s, int c, size_t n)
+{
+ return Genode::memset(s, c, n);
+}
diff --git a/dde_rump/src/server/rump_fs/file_system.h b/dde_rump/src/server/rump_fs/file_system.h
new file mode 100644
index 000000000..7484baa12
--- /dev/null
+++ b/dde_rump/src/server/rump_fs/file_system.h
@@ -0,0 +1,38 @@
+/**
+ * \brief Rump initialization and required header
+ * \author Sebastian Sumpf
+ * \date 2014-01-17
+ */
+
+/*
+ * Copyright (C) 2014 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 _FILE_SYSTEM_H_
+#define _FILE_SYSTEM_H_
+
+extern "C" {
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+}
+
+#include
+#include
+
+namespace File_system {
+ void init(Server::Entrypoint &ep);
+ bool supports_symlinks();
+}
+
+extern int errno;
+
+#endif /* _FILE_SYSTEM_H_ */
diff --git a/dde_rump/src/server/rump_fs/main.cc b/dde_rump/src/server/rump_fs/main.cc
new file mode 100644
index 000000000..f83e1ea32
--- /dev/null
+++ b/dde_rump/src/server/rump_fs/main.cc
@@ -0,0 +1,456 @@
+/**
+ * \brief RUMP file system interface implementation
+ * \author Christian Helmuth
+ * \author Sebastian Sumpf
+ * \date 2014-01-14
+ */
+
+/*
+ * Copyright (C) 2014 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 "undef.h"
+
+#include
+#include
+#include
+#include
+#include
+#include "file_system.h"
+#include "directory.h"
+#include "node_handle_registry.h"
+
+
+namespace File_system {
+ struct Main;
+ struct Root;
+ struct Session_component;
+}
+
+class File_system::Session_component : public Session_rpc_object
+{
+ private:
+
+ Allocator &_md_alloc;
+ Directory &_root;
+ Node_handle_registry _handle_registry;
+ bool _writable;
+
+ Signal_rpc_member _process_packet_dispatcher;
+
+
+ /******************************
+ ** Packet-stream processing **
+ ******************************/
+
+ /**
+ * Perform packet operation
+ *
+ * \return true on success, false on failure
+ */
+ void _process_packet_op(Packet_descriptor &packet, Node &node)
+ {
+ void * const content = tx_sink()->packet_content(packet);
+ size_t const length = packet.length();
+ seek_off_t const offset = packet.position();
+
+ if (!content || (packet.length() > packet.size())) {
+ packet.succeeded(false);
+ return;
+ }
+
+ /* resulting length */
+ size_t res_length = 0;
+
+ switch (packet.operation()) {
+
+ case Packet_descriptor::READ:
+ res_length = node.read((char *)content, length, offset);
+ break;
+
+ case Packet_descriptor::WRITE:
+ res_length = node.write((char const *)content, length, offset);
+ break;
+ }
+
+ packet.length(res_length);
+ packet.succeeded(res_length > 0);
+ }
+
+ void _process_packet()
+ {
+ Packet_descriptor packet = tx_sink()->get_packet();
+
+ /* assume failure by default */
+ packet.succeeded(false);
+
+ try {
+ Node *node = _handle_registry.lookup(packet.handle());
+
+ _process_packet_op(packet, *node);
+ }
+ catch (Invalid_handle) { PERR("Invalid_handle"); }
+ catch (Size_limit_reached) { PERR("Size_limit_reached"); }
+
+ /*
+ * The 'acknowledge_packet' function cannot block because we
+ * checked for 'ready_to_ack' in '_process_packets'.
+ */
+ tx_sink()->acknowledge_packet(packet);
+ }
+
+ /**
+ * Called by signal dispatcher, executed in the context of the main
+ * thread (not serialized with the RPC functions)
+ */
+ void _process_packets(unsigned)
+ {
+ while (tx_sink()->packet_avail()) {
+
+ /*
+ * Make sure that the '_process_packet' function does not
+ * block.
+ *
+ * If the acknowledgement queue is full, we defer packet
+ * processing until the client processed pending
+ * acknowledgements and thereby emitted a ready-to-ack
+ * signal. Otherwise, the call of 'acknowledge_packet()'
+ * in '_process_packet' would infinitely block the context
+ * of the main thread. The main thread is however needed
+ * for receiving any subsequent 'ready-to-ack' signals.
+ */
+ if (!tx_sink()->ready_to_ack())
+ return;
+
+ _process_packet();
+ }
+ }
+
+ /**
+ * Check if string represents a valid path (must start with '/')
+ */
+ static void _assert_valid_path(char const *path)
+ {
+ if (!path || path[0] != '/') {
+ PWRN("malformed path '%s'", path);
+ throw Lookup_failed();
+ }
+ }
+
+ public:
+
+ /**
+ * Constructor
+ */
+ Session_component(size_t tx_buf_size,
+ Server::Entrypoint &ep,
+ char const *root_dir,
+ bool writeable,
+ Allocator &md_alloc)
+ :
+ Session_rpc_object(env()->ram_session()->alloc(tx_buf_size), ep.rpc_ep()),
+ _md_alloc(md_alloc),
+ _root(*new (&_md_alloc) Directory(_md_alloc, root_dir, false)),
+ _writable(writeable),
+ _process_packet_dispatcher(ep, *this, &Session_component::_process_packets)
+ {
+ /*
+ * Register '_process_packets' dispatch function as signal
+ * handler for packet-avail and ready-to-ack signals.
+ */
+ _tx.sigh_packet_avail(_process_packet_dispatcher);
+ _tx.sigh_ready_to_ack(_process_packet_dispatcher);
+ }
+
+ /**
+ * Destructor
+ */
+ ~Session_component()
+ {
+ Dataspace_capability ds = tx_sink()->dataspace();
+ env()->ram_session()->free(static_cap_cast(ds));
+ destroy(&_md_alloc, &_root);
+ }
+
+ /***************************
+ ** File_system interface **
+ ***************************/
+
+ File_handle file(Dir_handle dir_handle, Name const &name, Mode mode, bool create)
+ {
+ if (!valid_name(name.string()))
+ throw Invalid_name();
+
+ Directory *dir = _handle_registry.lookup(dir_handle);
+
+ if (!_writable)
+ if (create || (mode != STAT_ONLY && mode != READ_ONLY))
+ throw Permission_denied();
+
+ File *file = dir->file(name.string(), mode, create);
+ return _handle_registry.alloc(file);
+ }
+
+ Symlink_handle symlink(Dir_handle dir_handle, Name const &name, bool create)
+ {
+ if (!File_system::supports_symlinks())
+ return Symlink_handle();
+
+ if (!valid_name(name.string()))
+ throw Invalid_name();
+
+ Directory *dir = _handle_registry.lookup(dir_handle);
+
+ if (create && !_writable)
+ throw Permission_denied();
+
+ Symlink *link = dir->symlink(name.string(), create);
+ return _handle_registry.alloc(link);
+ }
+
+ Dir_handle dir(Path const &path, bool create)
+ {
+ char const *path_str = path.string();
+ _assert_valid_path(path_str);
+
+ /* skip leading '/' */
+ path_str++;
+
+ if (!_writable && create)
+ throw Permission_denied();
+
+ if (!path.is_valid_string())
+ throw Name_too_long();
+
+ Directory *dir = _root.subdir(path_str, create);
+ return _handle_registry.alloc(dir);
+ }
+
+ Node_handle node(Path const &path)
+ {
+ char const *path_str = path.string();
+
+ _assert_valid_path(path_str);
+ Node *node = _root.node(path_str + 1);
+ Node_handle h = _handle_registry.alloc(node);
+ return h;
+ }
+
+ void close(Node_handle handle)
+ {
+ Node *node = 0;
+
+ try {
+ node = _handle_registry.lookup(handle);
+ } catch (Invalid_handle) { return; }
+
+ _handle_registry.free(handle);
+ /* destruct node */
+ if (node)
+ destroy(&_md_alloc, node);
+ }
+
+ Status status(Node_handle node_handle)
+ {
+ Node *node = _handle_registry.lookup(node_handle);
+ Status s;
+ s.inode = node->inode();
+ s.size = 0;
+ s.mode = 0;
+
+
+ File *file = dynamic_cast(node);
+ if (file) {
+ s.size = file->length();
+ s.mode = File_system::Status::MODE_FILE;
+ return s;
+ }
+
+ Directory *dir = dynamic_cast(node);
+ if (dir) {
+ s.size = dir->num_entries()*sizeof(Directory_entry);
+ s.mode = File_system::Status::MODE_DIRECTORY;
+ return s;
+ }
+
+ Symlink *link = dynamic_cast(node);
+ if (link) {
+ s.size = link->length();
+ s.mode = File_system::Status::MODE_SYMLINK;
+ return s;
+ }
+
+ return Status();
+ }
+
+ void control(Node_handle, Control)
+ {
+ PERR("%s not implemented", __func__);
+ }
+
+ void unlink(Dir_handle dir_handle, Name const &name)
+ {
+ if (!valid_name(name.string()))
+ throw Invalid_name();
+
+ if (!_writable)
+ throw Permission_denied();
+
+ Directory *dir = _handle_registry.lookup(dir_handle);
+ dir->unlink(name.string());
+ }
+
+ void truncate(File_handle file_handle, file_size_t size)
+ {
+ if (!_writable)
+ throw Permission_denied();
+
+ File *file = _handle_registry.lookup(file_handle);
+ file->truncate(size);
+ }
+
+ void move(Dir_handle, Name const &, Dir_handle, Name const &)
+ {
+ PERR("%s not implemented", __func__);
+ }
+
+ void sigh(Node_handle node_handle, Signal_context_capability sigh)
+ {
+ _handle_registry.sigh(node_handle, sigh);
+ }
+
+ void sync() { rump_sys_sync(); }
+};
+
+class File_system::Root : public Root_component
+{
+ private:
+
+ Server::Entrypoint &_ep;
+
+ protected:
+
+ Session_component *_create_session(const char *args)
+ {
+ /*
+ * Determine client-specific policy defined implicitly by
+ * the client's label.
+ */
+
+ char const *root_dir = ".";
+ bool writeable = false;
+
+ enum { ROOT_MAX_LEN = 256 };
+ char root[ROOT_MAX_LEN];
+ root[0] = 0;
+
+ try {
+ Session_label label(args);
+ Session_policy policy(label);
+
+ /*
+ * Determine directory that is used as root directory of
+ * the session.
+ */
+ try {
+ policy.attribute("root").value(root, sizeof(root));
+
+ /*
+ * Make sure the root path is specified with a
+ * leading path delimiter. For performing the
+ * lookup, we skip the first character.
+ */
+ if (root[0] != '/')
+ throw Lookup_failed();
+
+ root_dir = root;
+ } catch (Xml_node::Nonexistent_attribute) {
+ PERR("Missing \"root\" attribute in policy definition");
+ throw Root::Unavailable();
+ } catch (Lookup_failed) {
+ PERR("Session root directory \"%s\" does not exist", root);
+ throw Root::Unavailable();
+ }
+
+ /*
+ * Determine if write access is permitted for the session.
+ */
+ try {
+ writeable = policy.attribute("writeable").has_value("yes");
+ } catch (Xml_node::Nonexistent_attribute) { }
+
+ } catch (Session_policy::No_policy_defined) {
+ PERR("Invalid session request, no matching policy");
+ throw Root::Unavailable();
+ }
+
+ size_t ram_quota =
+ Arg_string::find_arg(args, "ram_quota" ).ulong_value(0);
+ size_t tx_buf_size =
+ Arg_string::find_arg(args, "tx_buf_size").ulong_value(0);
+
+ /*
+ * Check if donated ram quota suffices for session data,
+ * and communication buffer.
+ */
+ size_t session_size = sizeof(Session_component) + tx_buf_size;
+ if (max((size_t)4096, session_size) > ram_quota) {
+ PERR("insufficient 'ram_quota', got %zd, need %zd",
+ ram_quota, session_size);
+ throw Root::Quota_exceeded();
+ }
+ return new (md_alloc())
+ Session_component(tx_buf_size, _ep, root_dir, writeable, *md_alloc());
+ }
+
+ public:
+
+ /**
+ * Constructor
+ *
+ * \param ep entrypoint
+ * \param sig_rec signal receiver used for handling the
+ * data-flow signals of packet streams
+ * \param md_alloc meta-data allocator
+ */
+ Root(Server::Entrypoint &ep, Allocator &md_alloc)
+ :
+ Root_component(&ep.rpc_ep(), &md_alloc),
+ _ep(ep)
+ { }
+};
+
+
+struct File_system::Main
+{
+ Server::Entrypoint &ep;
+
+ /*
+ * Initialize root interface
+ */
+ Sliced_heap sliced_heap = { env()->ram_session(), env()->rm_session() };
+
+ Root fs_root = { ep, sliced_heap };
+
+
+ Main(Server::Entrypoint &ep)
+ :
+ ep(ep)
+ {
+ File_system::init(ep);
+ env()->parent()->announce(ep.manage(fs_root));
+ }
+};
+
+
+/**********************
+ ** Server framework **
+ **********************/
+
+char const * Server::name() { return "rump_fs_ep"; }
+Genode::size_t Server::stack_size() { return 2048 * sizeof(long); }
+void Server::construct(Server::Entrypoint &ep) { static File_system::Main inst(ep); }
+
diff --git a/dde_rump/src/server/rump_fs/node.h b/dde_rump/src/server/rump_fs/node.h
new file mode 100644
index 000000000..d2a8142ce
--- /dev/null
+++ b/dde_rump/src/server/rump_fs/node.h
@@ -0,0 +1,121 @@
+/*
+ * \brief File-system node
+ * \author Norman Feske
+ * \author Christian Helmuth
+ * \author Sebastian Sumpf
+ * \date 2013-11-11
+ */
+
+/*
+ * Copyright (C) 2013-2014 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 _NODE_H_
+#define _NODE_H_
+
+/* Genode includes */
+#include
+#include
+
+
+namespace File_system {
+ class Listener;
+ class Node;
+}
+
+class File_system::Listener : public List::Element
+{
+ private:
+
+ Signal_context_capability _sigh;
+ bool _marked_as_updated;
+
+ public:
+
+ Listener() : _marked_as_updated(false) { }
+
+ Listener(Signal_context_capability sigh)
+ : _sigh(sigh), _marked_as_updated(false) { }
+
+ void notify()
+ {
+ if (_marked_as_updated && _sigh.valid())
+ Signal_transmitter(_sigh).submit();
+
+ _marked_as_updated = false;
+ }
+
+ void mark_as_updated()
+ {
+ _marked_as_updated = true;
+ }
+
+ bool valid() const { return _sigh.valid(); }
+};
+
+
+class File_system::Node : public List::Element
+{
+ public:
+
+ typedef char Name[128];
+
+ private:
+
+ Name _name;
+ unsigned long const _inode;
+
+ List _listeners;
+
+ public:
+
+ Node(unsigned long inode) : _inode(inode) { _name[0] = 0; }
+
+ virtual ~Node()
+ {
+ /* propagate event to listeners */
+ mark_as_updated();
+ notify_listeners();
+
+ while (_listeners.first())
+ _listeners.remove(_listeners.first());
+ }
+
+ unsigned long inode() const { return _inode; }
+ char const *name() const { return _name; }
+
+ /**
+ * Assign name
+ */
+ void name(char const *name) { strncpy(_name, name, sizeof(_name)); }
+
+ virtual size_t read(char *dst, size_t len, seek_off_t) = 0;
+ virtual size_t write(char const *src, size_t len, seek_off_t) = 0;
+
+ void add_listener(Listener *listener)
+ {
+ _listeners.insert(listener);
+ }
+
+ void remove_listener(Listener *listener)
+ {
+ _listeners.remove(listener);
+ }
+
+ void notify_listeners()
+ {
+ for (Listener *curr = _listeners.first(); curr; curr = curr->next())
+ curr->notify();
+ }
+
+ void mark_as_updated()
+ {
+ for (Listener *curr = _listeners.first(); curr; curr = curr->next())
+ curr->mark_as_updated();
+ }
+};
+
+#endif /* _NODE_H_ */
diff --git a/dde_rump/src/server/rump_fs/node_handle_registry.h b/dde_rump/src/server/rump_fs/node_handle_registry.h
new file mode 100644
index 000000000..527994997
--- /dev/null
+++ b/dde_rump/src/server/rump_fs/node_handle_registry.h
@@ -0,0 +1,184 @@
+/*
+ * \brief Facility for managing the session-local node-handle namespace
+ * \author Norman Feske
+ * \date 2012-04-11
+ */
+
+/*
+ * Copyright (C) 2012-2014 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 _NODE_HANDLE_REGISTRY_H_
+#define _NODE_HANDLE_REGISTRY_H_
+
+namespace File_system {
+
+ class Node;
+ class Directory;
+ class File;
+ class Symlink;
+
+ /**
+ * Type trait for determining the node type for a given handle type
+ */
+ template struct Node_type;
+ template<> struct Node_type { typedef Node Type; };
+ template<> struct Node_type { typedef Directory Type; };
+ template<> struct Node_type { typedef File Type; };
+ template<> struct Node_type { typedef Symlink Type; };
+
+
+ /**
+ * Type trait for determining the handle type for a given node type
+ */
+ template struct Handle_type;
+ template<> struct Handle_type { typedef Node_handle Type; };
+ template<> struct Handle_type { typedef Dir_handle Type; };
+ template<> struct Handle_type { typedef File_handle Type; };
+ template<> struct Handle_type { typedef Symlink_handle Type; };
+
+
+ class Node_handle_registry
+ {
+ private:
+
+ /* maximum number of open nodes per session */
+ enum { MAX_NODE_HANDLES = 128U };
+
+ Node *_nodes[MAX_NODE_HANDLES];
+
+ /**
+ * Each open node handle can act as a listener to be informed about
+ * node changes.
+ */
+ Listener _listeners[MAX_NODE_HANDLES];
+
+ /**
+ * Allocate node handle
+ *
+ * \throw Out_of_node_handles
+ */
+ int _alloc(Node *node)
+ {
+ for (unsigned i = 0; i < MAX_NODE_HANDLES; i++)
+ if (!_nodes[i]) {
+ _nodes[i] = node;
+ return i;
+ }
+
+ throw Out_of_node_handles();
+ }
+
+ bool _in_range(int handle) const
+ {
+ return ((handle >= 0) && (handle < MAX_NODE_HANDLES));
+ }
+
+ public:
+
+ Node_handle_registry()
+ {
+ for (unsigned i = 0; i < MAX_NODE_HANDLES; i++)
+ _nodes[i] = 0;
+ }
+
+ template
+ typename Handle_type::Type alloc(NODE_TYPE *node)
+ {
+ typedef typename Handle_type::Type Handle;
+ return Handle(_alloc(node));
+ }
+
+ /**
+ * Release node handle
+ */
+ void free(Node_handle handle)
+ {
+ if (!_in_range(handle.value))
+ return;
+
+ /*
+ * Notify listeners about the changed file.
+ */
+ Node *node = dynamic_cast(_nodes[handle.value]);
+ if (!node) { return; }
+
+ node->notify_listeners();
+
+ /*
+ * De-allocate handle
+ */
+ Listener &listener = _listeners[handle.value];
+
+ if (listener.valid())
+ node->remove_listener(&listener);
+
+ _nodes[handle.value] = 0;
+ listener = Listener();
+ }
+
+ /**
+ * Lookup node using its handle as key
+ *
+ * \throw Invalid_handle
+ */
+ template
+ typename Node_type::Type *lookup(HANDLE_TYPE handle)
+ {
+ if (!_in_range(handle.value))
+ throw Invalid_handle();
+
+ typedef typename Node_type::Type Node;
+ Node *node = dynamic_cast(_nodes[handle.value]);
+ if (!node)
+ throw Invalid_handle();
+
+ return node;
+ }
+
+ bool refer_to_same_node(Node_handle h1, Node_handle h2) const
+ {
+ if (!_in_range(h1.value) || !_in_range(h2.value)) {
+ PDBG("refer_to_same_node -> Invalid_handle");
+ throw Invalid_handle();
+ }
+
+ return _nodes[h1.value] == _nodes[h2.value];
+ }
+
+ /**
+ * Register signal handler to be notified of node changes
+ */
+ void sigh(Node_handle handle, Signal_context_capability sigh)
+ {
+ if (!_in_range(handle.value))
+ throw Invalid_handle();
+
+ Node *node = dynamic_cast(_nodes[handle.value]);
+ if (!node) {
+ PDBG("Invalid_handle");
+ throw Invalid_handle();
+ }
+
+ Listener &listener = _listeners[handle.value];
+
+ /*
+ * If there was already a handler registered for the node,
+ * remove the old handler.
+ */
+ if (listener.valid())
+ node->remove_listener(&listener);
+
+ /*
+ * Register new handler
+ */
+ listener = Listener(sigh);
+ node->add_listener(&listener);
+ }
+ };
+}
+
+#endif /* _NODE_HANDLE_REGISTRY_H_ */
diff --git a/dde_rump/src/server/rump_fs/symlink.h b/dde_rump/src/server/rump_fs/symlink.h
new file mode 100644
index 000000000..b4dcf554d
--- /dev/null
+++ b/dde_rump/src/server/rump_fs/symlink.h
@@ -0,0 +1,71 @@
+/**
+ * \brief Rump symlink node
+ * \author Sebastian Sumpf
+ * \date 2014-01-20
+ */
+
+/*
+ * Copyright (C) 2014 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 _SYMLINK_H_
+#define _SYMLINK_H_
+
+#include
+
+#include "node.h"
+#include "util.h"
+
+namespace File_system {
+ class Symlink;
+}
+
+class File_system::Symlink : public Node
+{
+ private:
+
+ typedef Genode::Path Path;
+
+ Path _path;
+ bool _create;
+
+ public:
+
+ Symlink(char const *dir, char const *name, bool create)
+ : Node(0), _path(name, dir), _create(create)
+ {
+ Node::name(name);
+ }
+
+ Symlink(char const *path)
+ : Node(0), _path(path), _create(false)
+ {
+ Node::name(basename(path));
+ }
+
+ size_t write(char const *src, size_t len, seek_off_t seek_offset)
+ {
+ if (!_create)
+ return 0;
+
+ int ret = rump_sys_symlink(src, _path.base());
+ return ret == -1 ? 0 : ret;
+ }
+
+ size_t read(char *dst, size_t len, seek_off_t seek_offset)
+ {
+ int ret = rump_sys_readlink(_path.base(), dst, len);
+ return ret == -1 ? 0 : ret;
+ }
+
+ file_size_t length()
+ {
+ char link_to[MAX_PATH_LEN];
+ return read(link_to, MAX_PATH_LEN, 0);
+ }
+};
+
+#endif /* _SYMLINK_H_ */
diff --git a/dde_rump/src/server/rump_fs/target.mk b/dde_rump/src/server/rump_fs/target.mk
new file mode 100644
index 000000000..b251639a3
--- /dev/null
+++ b/dde_rump/src/server/rump_fs/target.mk
@@ -0,0 +1,5 @@
+TARGET = rump_fs
+SRC_CC = main.cc file_system.cc
+LIBS = rump rump_fs server startup
+
+
diff --git a/dde_rump/src/server/rump_fs/undef.h b/dde_rump/src/server/rump_fs/undef.h
new file mode 100644
index 000000000..05c33ab0b
--- /dev/null
+++ b/dde_rump/src/server/rump_fs/undef.h
@@ -0,0 +1,21 @@
+/**
+ * \brief Undef macro clashes
+ * \author Sebastian Sumpf
+ * \date 2014-01-24
+ */
+
+/*
+ * Copyright (C) 2014 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 _UNDEF_H_
+#define _UNDEF_H_
+
+extern "C" {
+#include
+}
+
+#endif /* _UNDEF_H_ */
diff --git a/dde_rump/src/server/rump_fs/util.h b/dde_rump/src/server/rump_fs/util.h
new file mode 100644
index 000000000..23ad85a7f
--- /dev/null
+++ b/dde_rump/src/server/rump_fs/util.h
@@ -0,0 +1,70 @@
+/*
+ * \brief Utilities
+ * \author Norman Feske
+ * \date 2012-04-11
+ */
+
+/*
+ * Copyright (C) 2012-2014 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 _UTIL_H_
+#define _UTIL_H_
+
+/**
+ * Return base-name portion of null-terminated path string
+ */
+static inline char const *basename(char const *path)
+{
+ char const *start = path;
+
+ for (; *path; path++)
+ if (*path == '/')
+ start = path + 1;
+
+ return start;
+}
+
+
+/**
+ * Return true if specified path is a base name (contains no path delimiters)
+ */
+static inline bool is_basename(char const *path)
+{
+ for (; *path; path++)
+ if (*path == '/')
+ return false;
+
+ return true;
+}
+
+
+/**
+ * Return true if character 'c' occurs in null-terminated string 'str'
+ */
+static inline bool string_contains(char const *str, char c)
+{
+ for (; *str; str++)
+ if (*str == c)
+ return true;
+ return false;
+}
+
+
+/**
+ * Return true if 'str' is a valid node name
+ */
+static inline bool valid_name(char const *str)
+{
+ if (string_contains(str, '/')) return false;
+
+ /* must have at least one character */
+ if (str[0] == 0) return false;
+
+ return true;
+}
+
+#endif /* _UTIL_H_ */
diff --git a/os/src/test/iso/main.cc b/os/src/test/iso/main.cc
index e4db8af14..9084870ac 100644
--- a/os/src/test/iso/main.cc
+++ b/os/src/test/iso/main.cc
@@ -12,10 +12,7 @@
*/
#include
-#include
-#include
-#include
-#include
+#include
using namespace Genode;
@@ -38,120 +35,31 @@ void dump(uint8_t *ptr, unsigned long offset)
}
-class Pager : public Thread<8192>
-{
- private:
-
- Signal_receiver _receiver;
- Dataspace_capability _ds;
- Rm_connection *_rm;
-
- public:
-
- Pager() : Thread("pager") { }
-
- Signal_receiver *signal_receiver() { return &_receiver; }
-
- void entry()
- {
- while (true) {
- Signal signal = _receiver.wait_for_signal();
-
- for (unsigned i = 0; i < signal.num(); i++)
- handle_fault();
- }
- }
-
- void handle_fault()
- {
- Rm_session::State state = _rm->state();
- addr_t addr = state.addr & ~(0xfff);
- _rm->attach_at(_ds, addr, 0x1000, addr - 0x1000);
- }
-
- void dataspace(Dataspace_capability ds) { _ds = ds; }
- void rm(Rm_connection *rm) { _rm = rm; }
-
- static Pager* pager()
- {
- static Pager _pager;
- return &_pager;
- }
-
- static Pager* pager2()
- {
- static Pager _pager;
- return &_pager;
- }
-
- static Pager* pager3()
- {
- static Pager _pager;
- return &_pager;
- }
-};
-
-
int main()
{
- Dataspace_capability ds;
+ Attached_rom_dataspace *ds;
uint8_t *ptr = 0;
- static Signal_context context;
- static Signal_context context2;
try {
- Rom_connection rom("/test.txt");
- rom.on_destruction(Rom_connection::KEEP_OPEN);
- ds = rom.dataspace();
- Dataspace_client client(ds);
- ptr = env()->rm_session()->attach(ds);
- printf("File size is %zx at %p\n", client.size(), ptr);
+ ds = new (env()->heap())Attached_rom_dataspace("/test.txt");
+ ptr = ds->local_addr();
+ printf("File size is %zx at %p\n", ds->size(), ptr);
}
catch (...) {
PDBG("Rom error");
return 1;
}
- Rm_connection rm(0, Dataspace_client(ds).size());
- rm.fault_handler(Pager::pager()->signal_receiver()->manage(&context));
- Pager::pager()->dataspace(ds);
- Pager::pager()->rm(&rm);
-
- /* start pager thread */
- Pager::pager()->start();
-
- uint8_t *ptr_nest = env()->rm_session()->attach(rm.dataspace());
-
- Rm_connection rm2(0, Dataspace_client(ds).size());
- rm2.fault_handler(Pager::pager2()->signal_receiver()->manage(&context2));
- Pager::pager2()->dataspace(rm.dataspace());
- Pager::pager2()->rm(&rm2);
-
- Pager::pager2()->start();
-
- uint8_t *ptr_nest2 = env()->rm_session()->attach(rm2.dataspace());
-
dump(ptr, 0x1000);
- dump(ptr_nest, 0x2000);
- dump(ptr_nest2, 0x3000);
-
dump(ptr, 0x10000);
dump(ptr, 0x20000);
- dump(ptr, 0x1000);
- dump(ptr_nest, 0x2000);
- dump(ptr_nest2, 0x3000);
-
- try {
-
- Rom_connection rom("/notavail.txt");
- PERR("found file where no file should be!");
- }
- catch (...) {
+ Attached_rom_dataspace rom("/notavail.txt");
+ if (!rom.is_valid())
PDBG("Expected ROM error occured");
- return 1;
- }
+ else
+ PERR("found file where no file should be!");
return 0;
}
diff --git a/tool/autopilot.list b/tool/autopilot.list
index c8e2af7c1..380d47ebf 100644
--- a/tool/autopilot.list
+++ b/tool/autopilot.list
@@ -38,3 +38,4 @@ gdb_monitor
part_blk
xml_generator
blk_cache
+rump_ext2