Index: kernel/generic/include/syscall/syscall.h
===================================================================
--- kernel/generic/include/syscall/syscall.h	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ kernel/generic/include/syscall/syscall.h	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -82,6 +82,8 @@
 	SYS_PREEMPT_CONTROL,
 	
-	SYS_SYSINFO_VALID,
-	SYS_SYSINFO_VALUE,
+	SYS_SYSINFO_GET_TAG,
+	SYS_SYSINFO_GET_VALUE,
+	SYS_SYSINFO_GET_DATA_SIZE,
+	SYS_SYSINFO_GET_DATA,
 	
 	SYS_DEBUG_ENABLE_CONSOLE,
Index: kernel/generic/include/sysinfo/sysinfo.h
===================================================================
--- kernel/generic/include/sysinfo/sysinfo.h	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ kernel/generic/include/sysinfo/sysinfo.h	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -41,51 +41,79 @@
 extern bool fb_exported;
 
-typedef union sysinfo_item_val {
+typedef enum {
+	SYSINFO_VAL_UNDEFINED = 0,
+	SYSINFO_VAL_VAL = 1,
+	SYSINFO_VAL_DATA = 2,
+	SYSINFO_VAL_FUNCTION_VAL = 3,
+	SYSINFO_VAL_FUNCTION_DATA = 4
+} sysinfo_item_val_type_t;
+
+typedef enum {
+	SYSINFO_SUBTREE_NONE = 0,
+	SYSINFO_SUBTREE_TABLE = 1,
+	SYSINFO_SUBTREE_FUNCTION = 2
+} sysinfo_subtree_type_t;
+
+struct sysinfo_item;
+
+typedef unative_t (*sysinfo_fn_val_t)(struct sysinfo_item *);
+typedef void *(*sysinfo_fn_data_t)(struct sysinfo_item *, size_t *);
+typedef struct sysinfo_item *(*sysinfo_fn_subtree_t)(const char *);
+
+typedef struct {
+	void *data;
+	size_t size;
+} sysinfo_data_t;
+
+typedef union {
 	unative_t val;
-	void *fn; 
+	sysinfo_fn_val_t fn_val;
+	sysinfo_fn_data_t fn_data;
+	sysinfo_data_t data;
 } sysinfo_item_val_t;
+
+typedef union {
+	struct sysinfo_item *table;
+	sysinfo_fn_subtree_t find_item;
+} sysinfo_subtree_t;
 
 typedef struct sysinfo_item {
 	char *name;
+	
+	sysinfo_item_val_type_t val_type;
+	sysinfo_item_val_t val;
+	
+	sysinfo_subtree_type_t subtree_type;
+	sysinfo_subtree_t subtree;
+	
+	struct sysinfo_item *next;
+} sysinfo_item_t;
+
+typedef struct {
+	sysinfo_item_val_type_t tag;
 	union {
 		unative_t val;
-		void *fn; 
-	} val;
+		sysinfo_data_t data;
+	};
+} sysinfo_return_t;
 
-	union {
-		struct sysinfo_item *table;
-		void *fn;
-	} subinfo;
+extern void sysinfo_init(void);
 
-	struct sysinfo_item *next;
-	int val_type;
-	int subinfo_type;
-} sysinfo_item_t;
+extern void sysinfo_set_item_val(const char *, sysinfo_item_t **, unative_t);
+extern void sysinfo_set_item_data(const char *, sysinfo_item_t **, void *,
+    size_t);
+extern void sysinfo_set_item_val_fn(const char *, sysinfo_item_t **,
+    sysinfo_fn_val_t);
+extern void sysinfo_set_item_data_fn(const char *, sysinfo_item_t **,
+    sysinfo_fn_data_t);
+extern void sysinfo_set_item_undefined(const char *, sysinfo_item_t **);
 
-#define SYSINFO_VAL_VAL        0
-#define SYSINFO_VAL_FUNCTION   1
-#define SYSINFO_VAL_UNDEFINED  U_SPECIAL
+extern sysinfo_return_t sysinfo_get_item(const char *, sysinfo_item_t **);
+extern void sysinfo_dump(sysinfo_item_t **, unsigned int);
 
-#define SYSINFO_SUBINFO_NONE      0
-#define SYSINFO_SUBINFO_TABLE     1
-#define SYSINFO_SUBINFO_FUNCTION  2
-
-typedef unative_t (*sysinfo_val_fn_t)(sysinfo_item_t *root);
-typedef unative_t (*sysinfo_subinfo_fn_t)(const char *subname);
-
-typedef struct sysinfo_rettype {
-	unative_t val;
-	unative_t valid;
-} sysinfo_rettype_t;
-
-void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, unative_t val);
-void sysinfo_dump(sysinfo_item_t **root, int depth);
-void sysinfo_set_item_function(const char *name, sysinfo_item_t **root, sysinfo_val_fn_t fn);
-void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root);
-
-sysinfo_rettype_t sysinfo_get_val(const char *name, sysinfo_item_t **root);
-
-unative_t sys_sysinfo_valid(unative_t ptr, unative_t len);
-unative_t sys_sysinfo_value(unative_t ptr, unative_t len);
+unative_t sys_sysinfo_get_tag(void *, size_t);
+unative_t sys_sysinfo_get_value(void *, size_t, void *);
+unative_t sys_sysinfo_get_data_size(void *, size_t, void *);
+unative_t sys_sysinfo_get_data(void *, size_t, void *, size_t);
 
 #endif
Index: kernel/generic/src/main/main.c
===================================================================
--- kernel/generic/src/main/main.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ kernel/generic/src/main/main.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -84,4 +84,5 @@
 #include <main/main.h>
 #include <ipc/event.h>
+#include <sysinfo/sysinfo.h>
 
 /** Global configuration structure. */
@@ -209,4 +210,5 @@
 	/* Initialize at least 1 memory segment big enough for slab to work. */
 	LOG_EXEC(slab_cache_init());
+	LOG_EXEC(sysinfo_init());
 	LOG_EXEC(btree_init());
 	LOG_EXEC(as_init());
Index: kernel/generic/src/syscall/syscall.c
===================================================================
--- kernel/generic/src/syscall/syscall.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ kernel/generic/src/syscall/syscall.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -153,6 +153,8 @@
 	
 	/* Sysinfo syscalls */
-	(syshandler_t) sys_sysinfo_valid,
-	(syshandler_t) sys_sysinfo_value,
+	(syshandler_t) sys_sysinfo_get_tag,
+	(syshandler_t) sys_sysinfo_get_value,
+	(syshandler_t) sys_sysinfo_get_data_size,
+	(syshandler_t) sys_sysinfo_get_data,
 	
 	/* Debug calls */
Index: kernel/generic/src/sysinfo/sysinfo.c
===================================================================
--- kernel/generic/src/sysinfo/sysinfo.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ kernel/generic/src/sysinfo/sysinfo.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -37,281 +37,411 @@
 #include <print.h>
 #include <syscall/copy.h>
+#include <errno.h>
+
+#define SYSINFO_MAX_PATH  2048
 
 bool fb_exported = false;
-sysinfo_item_t *_root = NULL;
-
-static sysinfo_item_t *sysinfo_find_item(const char *name, sysinfo_item_t *subtree)
-{
-	if (subtree == NULL)
-		return NULL;
-	
-	while (subtree != NULL) {
-		int i = 0;
-		char *a = (char *) name;
-		char *b = subtree->name;
-		
-		while ((a[i] == b[i]) && (b[i]))
+
+static sysinfo_item_t *global_root = NULL;
+static slab_cache_t *sysinfo_item_slab;
+
+static int sysinfo_item_constructor(void *obj, int kmflag)
+{
+	sysinfo_item_t *item = (sysinfo_item_t *) obj;
+	
+	item->name = NULL;
+	item->val_type = SYSINFO_VAL_UNDEFINED;
+	item->subtree_type = SYSINFO_SUBTREE_NONE;
+	item->next = NULL;
+	
+	return 0;
+}
+
+static int sysinfo_item_destructor(void *obj)
+{
+	sysinfo_item_t *item = (sysinfo_item_t *) obj;
+	
+	if (item->name != NULL)
+		free(item->name);
+	
+	return 0;
+}
+
+void sysinfo_init(void)
+{
+	sysinfo_item_slab = slab_cache_create("sysinfo_item_slab",
+	    sizeof(sysinfo_item_t), 0, sysinfo_item_constructor,
+	    sysinfo_item_destructor, SLAB_CACHE_MAGDEFERRED);
+}
+
+static sysinfo_item_t *sysinfo_find_item(const char *name,
+    sysinfo_item_t *subtree)
+{
+	sysinfo_item_t *cur = subtree;
+	
+	while (cur != NULL) {
+		size_t i = 0;
+		
+		/* Compare name with path */
+		while ((cur->name[i] != 0) && (name[i] == cur->name[i]))
 			i++;
 		
-		if ((!a[i]) && (!b[i]))  /* Last name in path matches */
-			return subtree;
-		
-		if ((a[i] == '.') && (!b[i])) { /* Middle name in path matches */
-			if (subtree->subinfo_type == SYSINFO_SUBINFO_TABLE)
-				return sysinfo_find_item(a + i + 1, subtree->subinfo.table);
+		/* Check for perfect name and path match */
+		if ((name[i] == 0) && (cur->name[i] == 0))
+			return cur;
+		
+		/* Partial match up to the delimiter */
+		if ((name[i] == '.') && (cur->name[i] == 0)) {
+			/* Look into the subtree */
+			switch (cur->subtree_type) {
+			case SYSINFO_SUBTREE_TABLE:
+				/* Recursively find in subtree */
+				return sysinfo_find_item(name + i + 1, cur->subtree.table);
+			case SYSINFO_SUBTREE_FUNCTION:
+				/* Get generated item */
+				return cur->subtree.find_item(name + i + 1);
+			default:
+				/* Not found */
+				return NULL;
+			}
+		}
+		
+		cur = cur->next;
+	}
+	
+	return NULL;
+}
+
+static sysinfo_item_t *sysinfo_create_path(const char *name,
+    sysinfo_item_t **psubtree)
+{
+	if (*psubtree == NULL) {
+		/* No parent */
+		
+		size_t i = 0;
+		
+		/* Find the first delimiter in name */
+		while ((name[i] != 0) && (name[i] != '.'))
+			i++;
+		
+		*psubtree =
+		    (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
+		ASSERT(*psubtree);
+		
+		/* Fill in item name up to the delimiter */
+		(*psubtree)->name = str_ndup(name, i);
+		ASSERT((*psubtree)->name);
+		
+		/* Create subtree items */
+		if (name[i] == '.') {
+			(*psubtree)->subtree_type = SYSINFO_SUBTREE_TABLE;
+			return sysinfo_create_path(name + i + 1,
+			    &((*psubtree)->subtree.table));
+		}
+		
+		/* No subtree needs to be created */
+		return *psubtree;
+	}
+	
+	sysinfo_item_t *cur = *psubtree;
+	
+	while (cur != NULL) {
+		size_t i = 0;
+		
+		/* Compare name with path */
+		while ((cur->name[i] != 0) && (name[i] == cur->name[i]))
+			i++;
+		
+		/* Check for perfect name and path match
+		 * -> item is already present.
+		 */
+		if ((name[i] == 0) && (cur->name[i] == 0))
+			return cur;
+		
+		/* Partial match up to the delimiter */
+		if ((name[i] == '.') && (cur->name[i] == 0)) {
+			switch (cur->subtree_type) {
+			case SYSINFO_SUBTREE_NONE:
+				/* No subtree yet, create one */
+				cur->subtree_type = SYSINFO_SUBTREE_TABLE;
+				return sysinfo_create_path(name + i + 1,
+				    &(cur->subtree.table));
+			case SYSINFO_SUBTREE_TABLE:
+				/* Subtree already created, add new sibling */
+				return sysinfo_create_path(name + i + 1,
+				    &(cur->subtree.table));
+			default:
+				/* Subtree items handled by a function, this
+				 * cannot be overriden.
+				 */
+				return NULL;
+			}
+		}
+		
+		/* No match and no more siblings to check
+		 * -> create a new sibling item.
+		 */
+		if (cur->next == NULL) {
+			/* Find the first delimiter in name */
+			i = 0;
+			while ((name[i] != 0) && (name[i] != '.'))
+				i++;
 			
-			//if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */
-			//	return NULL; 
+			sysinfo_item_t *item =
+			    (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
+			ASSERT(item);
 			
-			return NULL; /* No subinfo */
-		}
-		/* No matches try next */
-		subtree = subtree->next;
-	}
-	return NULL;
-}
-
-static sysinfo_item_t *sysinfo_create_path(const char *name, sysinfo_item_t **psubtree)
-{
-	sysinfo_item_t *subtree;
-	subtree = *psubtree;
-	
-	if (subtree == NULL) {
-		sysinfo_item_t *item = malloc(sizeof(sysinfo_item_t), 0);
-		int i = 0, j;
+			cur->next = item;
 			
-		ASSERT(item);
-		*psubtree = item;
-		item->next = NULL;
-		item->val_type = SYSINFO_VAL_UNDEFINED;
-		item->subinfo.table = NULL;
-
-		while (name[i] && (name[i] != '.'))
-			i++;
+			/* Fill in item name up to the delimiter */
+			item->name = str_ndup(name, i);
+			ASSERT(item->name);
 			
-		item->name = malloc(i, 0);
-		ASSERT(item->name);
-
-		for (j = 0; j < i; j++)
-			item->name[j] = name[j];
-		item->name[j] = 0;
-			
-		if (name[i]) { /* =='.' */
-			item->subinfo_type = SYSINFO_SUBINFO_TABLE;
-			return sysinfo_create_path(name + i + 1, &(item->subinfo.table));
-		}
-		item->subinfo_type = SYSINFO_SUBINFO_NONE;
-		return item;
-	}
-
-	while (subtree != NULL) {
-		int i = 0, j;
-		char *a = (char *) name;
-		char *b = subtree->name;
-		
-		while ((a[i] == b[i]) && (b[i]))
-			i++;
-		
-		if ((!a[i]) && (!b[i])) /* Last name in path matches */
-			return subtree;
-		
-		if ((a[i] == '.') && (!b[i])) { /* Middle name in path matches */
-			if (subtree->subinfo_type == SYSINFO_SUBINFO_TABLE)
-				return sysinfo_create_path(a + i + 1, &(subtree->subinfo.table));
-			
-			if (subtree->subinfo_type == SYSINFO_SUBINFO_NONE) {
-				subtree->subinfo_type = SYSINFO_SUBINFO_TABLE;
-				return sysinfo_create_path(a + i + 1,&(subtree->subinfo.table));
+			/* Create subtree items */
+			if (name[i] == '.') {
+				item->subtree_type = SYSINFO_SUBTREE_TABLE;
+				return sysinfo_create_path(name + i + 1,
+				    &(item->subtree.table));
 			}
 			
-			//if (subtree->subinfo_type == SYSINFO_SUBINFO_FUNCTION) /* Subinfo managed by subsystem */
-			//	return NULL; 
-			
-			return NULL;
-		}
-		/* No matches try next or create new*/
-		if (subtree->next == NULL) {
-			sysinfo_item_t *item = malloc(sizeof(sysinfo_item_t), 0);
-			
-			ASSERT(item);
-			subtree->next = item;
-			item->next = NULL;
-			item->val_type = SYSINFO_VAL_UNDEFINED;
-			item->subinfo.table = NULL;
-
-			i = 0;
-			while (name[i] && (name[i] != '.'))
-				i++;
-
-			item->name = malloc(i, 0);
-			ASSERT(item->name);
-			
-			for (j = 0; j < i; j++)
-				item->name[j] = name[j];
-			
-			item->name[j] = 0;
-
-			if(name[i]) { /* =='.' */
-				item->subinfo_type = SYSINFO_SUBINFO_TABLE;
-				return sysinfo_create_path(name + i + 1, &(item->subinfo.table));
-			}
-			item->subinfo_type = SYSINFO_SUBINFO_NONE;
+			/* No subtree needs to be created */
 			return item;
-		} else
-			subtree = subtree->next;
-	}
-
-	panic("Not reached.");
+		}
+		
+		/* Get next sibling */
+		cur = cur->next;
+	}
+	
+	/* Unreachable */
+	ASSERT(false);
 	return NULL;
 }
 
-void sysinfo_set_item_val(const char *name, sysinfo_item_t **root, unative_t val)
-{
-	if (root == NULL)
-		root = &_root;
-	
-	/* If already created create only returns pointer 
-	   If not, create it */
+void sysinfo_set_item_val(const char *name, sysinfo_item_t **root,
+    unative_t val)
+{
+	if (root == NULL)
+		root = &global_root;
+	
 	sysinfo_item_t *item = sysinfo_create_path(name, root);
-	
-	if (item != NULL) { /* If in subsystem, unable to create or return so unable to set */
-		item->val.val = val;                   
+	if (item != NULL) {
 		item->val_type = SYSINFO_VAL_VAL;
-	}
-}
-
-void sysinfo_set_item_function(const char *name, sysinfo_item_t **root, sysinfo_val_fn_t fn)
-{
-	if (root == NULL)
-		root = &_root;
-	
-	/* If already created create only returns pointer 
-	   If not, create it */
+		item->val.val = val;
+	}
+}
+
+void sysinfo_set_item_data(const char *name, sysinfo_item_t **root,
+    void *data, size_t size)
+{
+	if (root == NULL)
+		root = &global_root;
+	
 	sysinfo_item_t *item = sysinfo_create_path(name, root);
-	
-	if (item != NULL) { /* If in subsystem, unable to create or return so  unable to set */
-		item->val.fn = fn;                   
-		item->val_type = SYSINFO_VAL_FUNCTION;
-	}
-}
-
+	if (item != NULL) {
+		item->val_type = SYSINFO_VAL_DATA;
+		item->val.data.data = data;
+		item->val.data.size = size;
+	}
+}
+
+void sysinfo_set_item_val_fn(const char *name, sysinfo_item_t **root,
+    sysinfo_fn_val_t fn)
+{
+	if (root == NULL)
+		root = &global_root;
+	
+	sysinfo_item_t *item = sysinfo_create_path(name, root);
+	if (item != NULL) {
+		item->val_type = SYSINFO_VAL_FUNCTION_VAL;
+		item->val.fn_val = fn;
+	}
+}
+
+void sysinfo_set_item_data_fn(const char *name, sysinfo_item_t **root,
+    sysinfo_fn_data_t fn)
+{
+	if (root == NULL)
+		root = &global_root;
+	
+	sysinfo_item_t *item = sysinfo_create_path(name, root);
+	if (item != NULL) {
+		item->val_type = SYSINFO_VAL_FUNCTION_DATA;
+		item->val.fn_data = fn;
+	}
+}
 
 void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root)
 {
 	if (root == NULL)
-		root = &_root;
-	
-	/* If already created create only returns pointer 
-	   If not, create it */
+		root = &global_root;
+	
 	sysinfo_item_t *item = sysinfo_create_path(name, root);
-	
 	if (item != NULL)
 		item->val_type = SYSINFO_VAL_UNDEFINED;
 }
 
-
-void sysinfo_dump(sysinfo_item_t **proot, int depth)
-{
-	sysinfo_item_t *root;
+static void sysinfo_indent(unsigned int depth)
+{
+	unsigned int i;
+	for (i = 0; i < depth; i++)
+		printf("  ");
+}
+
+void sysinfo_dump(sysinfo_item_t **proot, unsigned int depth)
+{
 	if (proot == NULL)
-		proot = &_root;
-	
-	root = *proot;
-	
-	while (root != NULL) {
-		int i;
-		unative_t val = 0;
-		const char *vtype = NULL;
-		
-		
-		for (i = 0; i < depth; i++)
-			printf("  ");
-		
-		switch (root->val_type) {
+		proot = &global_root;
+	
+	sysinfo_item_t *cur = *proot;
+	
+	while (cur != NULL) {
+		sysinfo_indent(depth);
+		
+		unative_t val;
+		size_t size;
+		
+		switch (cur->val_type) {
 		case SYSINFO_VAL_UNDEFINED:
-			val = 0;
-			vtype = "UND";
+			printf("+ %s\n", cur->name);
 			break;
 		case SYSINFO_VAL_VAL:
-			val = root->val.val;
-			vtype = "VAL";
-			break;
-		case SYSINFO_VAL_FUNCTION:
-			val = ((sysinfo_val_fn_t) (root->val.fn)) (root);
-			vtype = "FUN";
-			break;
-		}
-		
-		printf("%s    %s val:%" PRIun "(%" PRIxn ") sub:%s\n", root->name, vtype, val,
-			val, (root->subinfo_type == SYSINFO_SUBINFO_NONE) ?
-			"NON" : ((root->subinfo_type == SYSINFO_SUBINFO_TABLE) ?
-			"TAB" : "FUN"));
-		
-		if (root->subinfo_type == SYSINFO_SUBINFO_TABLE)
-			sysinfo_dump(&(root -> subinfo.table), depth + 1);
-		
-		root = root->next;
-	}
-}
-
-sysinfo_rettype_t sysinfo_get_val(const char *name, sysinfo_item_t **root)
-{
-	// TODO: Implement Subsystem subinfo (by function implemented subinfo)
-
-	sysinfo_rettype_t ret = {0, false};
-
-	if (root == NULL)
-		root = &_root;
+			printf("+ %s -> %" PRIun" (%#" PRIxn ")\n", cur->name,
+			    cur->val.val, cur->val.val);
+			break;
+		case SYSINFO_VAL_DATA:
+			printf("+ %s (%" PRIs" bytes)\n", cur->name,
+			    cur->val.data.size);
+			break;
+		case SYSINFO_VAL_FUNCTION_VAL:
+			val = cur->val.fn_val(cur);
+			printf("+ %s -> %" PRIun" (%#" PRIxn ") [generated]\n",
+			    cur->name, val, val);
+			break;
+		case SYSINFO_VAL_FUNCTION_DATA:
+			cur->val.fn_data(cur, &size);
+			printf("+ %s (%" PRIs" bytes) [generated]\n", cur->name,
+			    size);
+			break;
+		default:
+			printf("+ %s [unknown]\n", cur->name);
+		}
+		
+		switch (cur->subtree_type) {
+		case SYSINFO_SUBTREE_NONE:
+			break;
+		case SYSINFO_SUBTREE_TABLE:
+			sysinfo_dump(&(cur->subtree.table), depth + 1);
+			break;
+		case SYSINFO_SUBTREE_FUNCTION:
+			sysinfo_indent(depth + 1);
+			printf("  [generated subtree]\n");
+			break;
+		default:
+			sysinfo_indent(depth + 1);
+			printf("  [unknown subtree]\n");
+		}
+		
+		cur = cur->next;
+	}
+}
+
+sysinfo_return_t sysinfo_get_item(const char *name, sysinfo_item_t **root)
+{
+	if (root == NULL)
+		root = &global_root;
 	
 	sysinfo_item_t *item = sysinfo_find_item(name, *root);
+	sysinfo_return_t ret;
 	
 	if (item != NULL) {
-		if (item->val_type == SYSINFO_VAL_UNDEFINED) 
-			return ret;
-		else
-			ret.valid = true;
-		
-		if (item->val_type == SYSINFO_VAL_VAL)
+		switch (item->val_type) {
+		case SYSINFO_VAL_UNDEFINED:
+			ret.tag = SYSINFO_VAL_UNDEFINED;
+			break;
+		case SYSINFO_VAL_VAL:
+			ret.tag = SYSINFO_VAL_VAL;
 			ret.val = item->val.val;
-		else
-			ret.val = ((sysinfo_val_fn_t) (item->val.fn)) (item);
-	}
+			break;
+		case SYSINFO_VAL_DATA:
+			ret.tag = SYSINFO_VAL_DATA;
+			ret.data = item->val.data;
+			break;
+		case SYSINFO_VAL_FUNCTION_VAL:
+			ret.tag = SYSINFO_VAL_VAL;
+			ret.val = item->val.fn_val(item);
+			break;
+		case SYSINFO_VAL_FUNCTION_DATA:
+			ret.tag = SYSINFO_VAL_DATA;
+			ret.data.data = item->val.fn_data(item, &ret.data.size);
+			break;
+		}
+	} else
+		ret.tag = SYSINFO_VAL_UNDEFINED;
+	
 	return ret;
 }
 
-#define SYSINFO_MAX_LEN	1024
-
-unative_t sys_sysinfo_valid(unative_t ptr, unative_t len)
-{
-	char *str;
-	sysinfo_rettype_t ret = {0, 0};
-
-	if (len > SYSINFO_MAX_LEN)
-		return ret.valid;
-	str = malloc(len + 1, 0);
-	
-	ASSERT(str);
-	if (!((copy_from_uspace(str, (void *) ptr, len + 1)) || (str[len])))
-		ret = sysinfo_get_val(str, NULL);
-	
-	free(str);
-	return ret.valid;
-}
-
-unative_t sys_sysinfo_value(unative_t ptr, unative_t len)
-{
-	char *str;
-	sysinfo_rettype_t ret = {0, 0};
-	
-	if (len > SYSINFO_MAX_LEN)
-		return ret.val;
-	str = malloc(len + 1, 0);
-	
-	ASSERT(str);
-	if (!((copy_from_uspace(str, (void *) ptr, len + 1)) || (str[len]))) 
-		ret = sysinfo_get_val(str, NULL);
-	
-	free(str);
-	return ret.val;
+static sysinfo_return_t sysinfo_get_item_uspace(void *ptr, size_t size)
+{
+	sysinfo_return_t ret;
+	ret.tag = SYSINFO_VAL_UNDEFINED;
+	
+	if (size > SYSINFO_MAX_PATH)
+		return ret;
+	
+	char *path = (char *) malloc(size + 1, 0);
+	ASSERT(path);
+	
+	if ((copy_from_uspace(path, ptr, size + 1) == 0)
+	    && (path[size] == 0)) {
+		ret = sysinfo_get_item(path, NULL);
+		free(path);
+	}
+	
+	return ret;
+}
+
+unative_t sys_sysinfo_get_tag(void *path_ptr, size_t path_size)
+{
+	return (unative_t) sysinfo_get_item_uspace(path_ptr, path_size).tag;
+}
+
+unative_t sys_sysinfo_get_value(void *path_ptr, size_t path_size,
+    void *value_ptr)
+{
+	sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size);
+	
+	if (ret.tag != SYSINFO_VAL_VAL)
+		return (unative_t) EINVAL;
+	
+	return (unative_t) copy_to_uspace(value_ptr, &ret.val,
+	    sizeof(ret.val));
+}
+
+unative_t sys_sysinfo_get_data_size(void *path_ptr, size_t path_size,
+    void *size_ptr)
+{
+	sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size);
+	
+	if (ret.tag != SYSINFO_VAL_DATA)
+		return (unative_t) EINVAL;
+	
+	return (unative_t) copy_to_uspace(size_ptr, &ret.data.size,
+	    sizeof(ret.data.size));
+}
+
+unative_t sys_sysinfo_get_data(void *path_ptr, size_t path_size,
+    void *buffer_ptr, size_t buffer_size)
+{
+	sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size);
+	
+	if (ret.tag != SYSINFO_VAL_DATA)
+		return (unative_t) EINVAL;
+	
+	if (ret.data.size != buffer_size)
+		return ENOMEM;
+	
+	return (unative_t) copy_to_uspace(buffer_ptr, ret.data.data,
+	    ret.data.size);
 }
 
Index: uspace/app/bdsh/exec.c
===================================================================
--- uspace/app/bdsh/exec.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/app/bdsh/exec.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -121,9 +121,10 @@
 	free(found);
 
-	tid = task_spawn(tmp, (const char **) argv);
+	tid = task_spawn(tmp, (const char **) argv, &retval);
 	free(tmp);
 
 	if (tid == 0) {
-		cli_error(CL_EEXEC, "%s: Cannot spawn `%s'", progname, cmd);
+		cli_error(CL_EEXEC, "%s: Cannot spawn `%s' (%s)", progname, cmd,
+		    str_error(retval));
 		return 1;
 	}
Index: uspace/app/getterm/getterm.c
===================================================================
--- uspace/app/getterm/getterm.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/app/getterm/getterm.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -40,9 +40,12 @@
 #include <stdio.h>
 #include <task.h>
+#include <str_error.h>
 #include "version.h"
+
+#define APP_NAME  "getterm"
 
 static void usage(void)
 {
-	printf("Usage: getterm <terminal> <path>\n");
+	printf("Usage: %s <terminal> <path>\n", APP_NAME);
 }
 
@@ -76,8 +79,10 @@
 	args[1] = NULL;
 	
-	task_id_t id = task_spawn(fname, args);
+	int err;
+	task_id_t id = task_spawn(fname, args, &err);
 	
 	if (id == 0)
-		printf("Error spawning %s\n", fname);
+		printf("%s: Error spawning %s (%s)\n", APP_NAME, fname,
+		    str_error(err));
 	
 	return id;
Index: uspace/app/init/init.c
===================================================================
--- uspace/app/init/init.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/app/init/init.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -48,7 +48,19 @@
 #include <str.h>
 #include <devmap.h>
+#include <str_error.h>
 #include "init.h"
 
+#define ROOT_DEVICE       "bd/initrd"
+#define ROOT_MOUNT_POINT  "/"
+
+#define DEVFS_FS_TYPE      "devfs"
 #define DEVFS_MOUNT_POINT  "/dev"
+
+#define SCRATCH_FS_TYPE      "tmpfs"
+#define SCRATCH_MOUNT_POINT  "/scratch"
+
+#define DATA_FS_TYPE      "fat"
+#define DATA_DEVICE       "bd/disk0"
+#define DATA_MOUNT_POINT  "/data"
 
 #define SRV_CONSOLE  "/srv/console"
@@ -57,5 +69,34 @@
 static void info_print(void)
 {
-	printf(NAME ": HelenOS init\n");
+	printf("%s: HelenOS init\n", NAME);
+}
+
+static bool mount_report(const char *desc, const char *mntpt,
+    const char *fstype, const char *dev, int rc)
+{
+	switch (rc) {
+	case EOK:
+		if (dev != NULL)
+			printf("%s: %s mounted on %s (%s at %s)\n", NAME, desc, mntpt,
+			    fstype, dev);
+		else
+			printf("%s: %s mounted on %s (%s)\n", NAME, desc, mntpt, fstype);
+		break;
+	case EBUSY:
+		printf("%s: %s already mounted on %s\n", NAME, desc, mntpt);
+		return false;
+	case ELIMIT:
+		printf("%s: %s limit exceeded\n", NAME, desc);
+		return false;
+	case ENOENT:
+		printf("%s: %s unknown type (%s)\n", NAME, desc, fstype);
+		return false;
+	default:
+		printf("%s: %s not mounted on %s (%s)\n", NAME, desc, mntpt,
+		    str_error(rc));
+		return false;
+	}
+	
+	return true;
 }
 
@@ -63,56 +104,20 @@
 {
 	const char *opts = "";
-	const char *root_dev = "bd/initrd";
 	
 	if (str_cmp(fstype, "tmpfs") == 0)
 		opts = "restore";
 	
-	int rc = mount(fstype, "/", root_dev, opts, IPC_FLAG_BLOCKING);
-	
-	switch (rc) {
-	case EOK:
-		printf(NAME ": Root filesystem mounted, %s at %s\n",
-		    fstype, root_dev);
-		break;
-	case EBUSY:
-		printf(NAME ": Root filesystem already mounted\n");
-		return false;
-	case ELIMIT:
-		printf(NAME ": Unable to mount root filesystem\n");
-		return false;
-	case ENOENT:
-		printf(NAME ": Unknown filesystem type (%s)\n", fstype);
-		return false;
-	default:
-		printf(NAME ": Error mounting root filesystem (%d)\n", rc);
-		return false;
-	}
-	
-	return true;
+	int rc = mount(fstype, ROOT_MOUNT_POINT, ROOT_DEVICE, opts,
+	    IPC_FLAG_BLOCKING);
+	return mount_report("Root filesystem", ROOT_MOUNT_POINT, fstype,
+	    ROOT_DEVICE, rc);
 }
 
 static bool mount_devfs(void)
 {
-	int rc = mount("devfs", DEVFS_MOUNT_POINT, "", "", IPC_FLAG_BLOCKING);
-	
-	switch (rc) {
-	case EOK:
-		printf(NAME ": Device filesystem mounted\n");
-		break;
-	case EBUSY:
-		printf(NAME ": Device filesystem already mounted\n");
-		return false;
-	case ELIMIT:
-		printf(NAME ": Unable to mount device filesystem\n");
-		return false;
-	case ENOENT:
-		printf(NAME ": Unknown filesystem type (devfs)\n");
-		return false;
-	default:
-		printf(NAME ": Error mounting device filesystem (%d)\n", rc);
-		return false;
-	}
-	
-	return true;
+	int rc = mount(DEVFS_FS_TYPE, DEVFS_MOUNT_POINT, "", "",
+	    IPC_FLAG_BLOCKING);
+	return mount_report("Device filesystem", DEVFS_MOUNT_POINT, DEVFS_FS_TYPE,
+	    NULL, rc);
 }
 
@@ -125,11 +130,13 @@
 		return;
 	
-	printf(NAME ": Spawning %s\n", fname);
+	printf("%s: Spawning %s\n", NAME, fname);
 	
 	argv[0] = fname;
 	argv[1] = NULL;
 	
-	if (!task_spawn(fname, argv))
-		printf(NAME ": Error spawning %s\n", fname);
+	int err;
+	if (!task_spawn(fname, argv, &err))
+		printf("%s: Error spawning %s (%s)\n", NAME, fname,
+		    str_error(err));
 }
 
@@ -145,24 +152,26 @@
 		return;
 	
-	printf(NAME ": Starting %s\n", fname);
+	printf("%s: Starting %s\n", NAME, fname);
 	
 	argv[0] = fname;
 	argv[1] = NULL;
 	
-	id = task_spawn(fname, argv);
+	id = task_spawn(fname, argv, &retval);
 	if (!id) {
-		printf(NAME ": Error spawning %s\n", fname);
+		printf("%s: Error spawning %s (%s)\n", NAME, fname,
+		    str_error(retval));
 		return;
 	}
-
+	
 	rc = task_wait(id, &texit, &retval);
 	if (rc != EOK) {
-		printf(NAME ": Error waiting for %s\n", fname);
+		printf("%s: Error waiting for %s (%s(\n", NAME, fname,
+		    str_error(retval));
 		return;
 	}
-
+	
 	if ((texit != TASK_EXIT_NORMAL) || (retval != 0)) {
-		printf(NAME ": Server %s failed to start (returned %d)\n",
-			fname, retval);
+		printf("%s: Server %s failed to start (%s)\n", NAME,
+			fname, str_error(retval));
 	}
 }
@@ -176,5 +185,5 @@
 	snprintf(hid_in, DEVMAP_NAME_MAXLEN, "%s/%s", DEVFS_MOUNT_POINT, dev);
 	
-	printf(NAME ": Spawning %s with %s\n", SRV_CONSOLE, hid_in);
+	printf("%s: Spawning %s %s\n", NAME, SRV_CONSOLE, hid_in);
 	
 	/* Wait for the input device to be ready */
@@ -187,8 +196,10 @@
 		argv[2] = NULL;
 		
-		if (!task_spawn(SRV_CONSOLE, argv))
-			printf(NAME ": Error spawning %s with %s\n", SRV_CONSOLE, hid_in);
+		if (!task_spawn(SRV_CONSOLE, argv, &rc))
+			printf("%s: Error spawning %s %s (%s)\n", NAME, SRV_CONSOLE,
+			    hid_in, str_error(rc));
 	} else
-		printf(NAME ": Error waiting on %s\n", hid_in);
+		printf("%s: Error waiting on %s (%s)\n", NAME, hid_in,
+		    str_error(rc));
 }
 
@@ -201,5 +212,5 @@
 	snprintf(term, DEVMAP_NAME_MAXLEN, "%s/%s", DEVFS_MOUNT_POINT, dev);
 	
-	printf(NAME ": Spawning %s with %s %s\n", APP_GETTERM, term, app);
+	printf("%s: Spawning %s %s %s\n", NAME, APP_GETTERM, term, app);
 	
 	/* Wait for the terminal device to be ready */
@@ -213,37 +224,24 @@
 		argv[3] = NULL;
 		
-		if (!task_spawn(APP_GETTERM, argv))
-			printf(NAME ": Error spawning %s with %s %s\n", APP_GETTERM,
-			    term, app);
+		if (!task_spawn(APP_GETTERM, argv, &rc))
+			printf("%s: Error spawning %s %s %s (%s)\n", NAME, APP_GETTERM,
+			    term, app, str_error(rc));
 	} else
-		printf(NAME ": Error waiting on %s\n", term);
-}
-
-static void mount_scratch(void)
-{
-	int rc;
-
-	printf("Trying to mount null/0 on /scratch... ");
-	fflush(stdout);
-
-	rc = mount("tmpfs", "/scratch", "null/0", "", 0);
-	if (rc == EOK)
-		printf("OK\n");
-	else
-		printf("Failed\n");
-}
-
-static void mount_data(void)
-{
-	int rc;
-
-	printf("Trying to mount bd/disk0 on /data... ");
-	fflush(stdout);
-
-	rc = mount("fat", "/data", "bd/disk0", "wtcache", 0);
-	if (rc == EOK)
-		printf("OK\n");
-	else
-		printf("Failed\n");
+		printf("%s: Error waiting on %s (%s)\n", NAME, term,
+		    str_error(rc));
+}
+
+static bool mount_scratch(void)
+{
+	int rc = mount(SCRATCH_FS_TYPE, SCRATCH_MOUNT_POINT, "", "", 0);
+	return mount_report("Scratch filesystem", SCRATCH_MOUNT_POINT,
+	    SCRATCH_FS_TYPE, NULL, rc);
+}
+
+static bool mount_data(void)
+{
+	int rc = mount(DATA_FS_TYPE, DATA_MOUNT_POINT, DATA_DEVICE, "wtcache", 0);
+	return mount_report("Data filesystem", DATA_MOUNT_POINT, DATA_FS_TYPE,
+	    DATA_DEVICE, rc);
 }
 
@@ -253,8 +251,8 @@
 	
 	if (!mount_root(STRING(RDFMT))) {
-		printf(NAME ": Exiting\n");
+		printf("%s: Exiting\n", NAME);
 		return -1;
 	}
-
+	
 	/* Make sure tmpfs is running. */
 	if (str_cmp(STRING(RDFMT), "tmpfs") != 0) {
@@ -266,8 +264,8 @@
 	
 	if (!mount_devfs()) {
-		printf(NAME ": Exiting\n");
+		printf("%s: Exiting\n", NAME);
 		return -2;
 	}
-
+	
 	mount_scratch();
 	
@@ -278,5 +276,5 @@
 	srv_start("/srv/adb_ms");
 	srv_start("/srv/char_ms");
-
+	
 	spawn("/srv/fb");
 	spawn("/srv/kbd");
@@ -284,5 +282,5 @@
 	
 	spawn("/srv/clip");
-
+	
 	/*
 	 * Start these synchronously so that mount_data() can be
@@ -295,5 +293,5 @@
 	(void) srv_start;
 #endif
-
+	
 #ifdef CONFIG_MOUNT_DATA
 	mount_data();
@@ -301,5 +299,5 @@
 	(void) mount_data;
 #endif
-
+	
 	getterm("term/vc0", "/app/bdsh");
 	getterm("term/vc1", "/app/bdsh");
@@ -309,5 +307,5 @@
 	getterm("term/vc5", "/app/bdsh");
 	getterm("term/vc6", "/app/klog");
-
+	
 	return 0;
 }
Index: uspace/app/klog/klog.c
===================================================================
--- uspace/app/klog/klog.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/app/klog/klog.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -64,5 +64,10 @@
 int main(int argc, char *argv[])
 {
-	size_t klog_pages = sysinfo_value("klog.pages");
+	size_t klog_pages;
+	if (sysinfo_get_value("klog.pages", &klog_pages) != EOK) {
+		printf("%s: Error getting klog address\n", NAME);
+		return -1;
+	}
+	
 	size_t klog_size = klog_pages * PAGE_SIZE;
 	klog_length = klog_size / sizeof(wchar_t);
@@ -70,5 +75,5 @@
 	klog = (wchar_t *) as_get_mappable_page(klog_size);
 	if (klog == NULL) {
-		printf(NAME ": Error allocating memory area\n");
+		printf("%s: Error allocating memory area\n", NAME);
 		return -1;
 	}
@@ -77,10 +82,10 @@
 	    klog_size, SERVICE_MEM_KLOG);
 	if (res != EOK) {
-		printf(NAME ": Error initializing memory area\n");
+		printf("%s: Error initializing memory area\n", NAME);
 		return -1;
 	}
 	
 	if (event_subscribe(EVENT_KLOG, 0) != EOK) {
-		printf(NAME ": Error registering klog notifications\n");
+		printf("%s: Error registering klog notifications\n", NAME);
 		return -1;
 	}
Index: uspace/app/redir/redir.c
===================================================================
--- uspace/app/redir/redir.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/app/redir/redir.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -42,8 +42,12 @@
 #include <stdio.h>
 #include <task.h>
+#include <str_error.h>
+
+#define NAME  "redir"
 
 static void usage(void)
 {
-	printf("Usage: redir [-i <stdin>] [-o <stdout>] [-e <stderr>] -- <cmd> [args ...]\n");
+	printf("Usage: %s [-i <stdin>] [-o <stdout>] [-e <stderr>] -- <cmd> [args ...]\n",
+	    NAME);
 }
 
@@ -84,10 +88,12 @@
 	args[argc] = NULL;
 	
-	task_id_t id = task_spawn(argv[0], args);
+	int err;
+	task_id_t id = task_spawn(argv[0], args, &err);
 	
 	free(args);
 	
 	if (id == 0)
-		printf("Error spawning %s\n", argv[0]);
+		printf("%s: Error spawning %s (%s)\n", NAME, argv[0],
+		    str_error(err));
 	
 	return id;
Index: uspace/app/sbi/src/os/helenos.c
===================================================================
--- uspace/app/sbi/src/os/helenos.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/app/sbi/src/os/helenos.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -35,4 +35,5 @@
 #include <task.h>
 #include <tinput.h>
+#include <str_error.h>
 
 #include "os.h"
@@ -154,7 +155,8 @@
 	int retval;
 
-	tid = task_spawn(cmd[0], (char const * const *) cmd);
+	tid = task_spawn(cmd[0], (char const * const *) cmd, &retval);
 	if (tid == 0) {
-		printf("Error: Failed spawning '%s'.\n", cmd[0]);
+		printf("Error: Failed spawning '%s' (%s).\n", cmd[0],
+		    str_error(retval));
 		exit(1);
 	}
Index: uspace/app/trace/syscalls.c
===================================================================
--- uspace/app/trace/syscalls.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/app/trace/syscalls.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -75,6 +75,9 @@
     [SYS_PREEMPT_CONTROL] = { "preempt_control",	1,	V_ERRNO },
 
-    [SYS_SYSINFO_VALID] = { "sysinfo_valid",		2,	V_HASH },
-    [SYS_SYSINFO_VALUE] = { "sysinfo_value",		2,	V_HASH },
+    [SYS_SYSINFO_GET_TAG] = { "sysinfo_get_tag",		2,	V_INTEGER },
+    [SYS_SYSINFO_GET_VALUE] = { "sysinfo_get_value",		3,	V_ERRNO },
+    [SYS_SYSINFO_GET_DATA_SIZE] = { "sysinfo_get_data_size",	3,	V_ERRNO },
+    [SYS_SYSINFO_GET_DATA] = { "sysinfo_get_data",		4,	V_ERRNO },
+
     [SYS_DEBUG_ENABLE_CONSOLE] = { "debug_enable_console", 0,	V_ERRNO },
     [SYS_IPC_CONNECT_KBOX] = { "ipc_connect_kbox",	1,	V_ERRNO }
Index: uspace/lib/c/arch/ia64/src/ddi.c
===================================================================
--- uspace/lib/c/arch/ia64/src/ddi.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/lib/c/arch/ia64/src/ddi.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -2,12 +2,13 @@
 #include <sysinfo.h>
 
-uint64_t ia64_iospace_address=0;
-
+uint64_t ia64_iospace_address = 0;
 
 uint64_t get_ia64_iospace_address(void)
 {
-
-	return sysinfo_value("ia64_iospace.address.virtual");
-
+	sysarg_t addr;
+	if (sysinfo_get_value("ia64_iospace.address.virtual", &addr) != 0)
+		addr = 0;
+	
+	return addr;
 }
 
Index: uspace/lib/c/generic/sysinfo.c
===================================================================
--- uspace/lib/c/generic/sysinfo.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/lib/c/generic/sysinfo.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -31,14 +31,52 @@
  */
 /** @file
- */ 
+ */
 
 #include <libc.h>
 #include <sysinfo.h>
 #include <str.h>
+#include <errno.h>
+#include <malloc.h>
+#include <bool.h>
 
-sysarg_t sysinfo_value(const char *name)
+sysinfo_item_tag_t sysinfo_get_tag(const char *path)
 {
-	return __SYSCALL2(SYS_SYSINFO_VALUE, (sysarg_t) name,
-	    (sysarg_t) str_size(name));
+	return (sysinfo_item_tag_t) __SYSCALL2(SYS_SYSINFO_GET_TAG,
+	    (sysarg_t) path, (sysarg_t) str_size(path));
+}
+
+int sysinfo_get_value(const char *path, sysarg_t *value)
+{
+	return (int) __SYSCALL3(SYS_SYSINFO_GET_VALUE, (sysarg_t) path,
+	    (sysarg_t) str_size(path), (sysarg_t) value);
+}
+
+static int sysinfo_get_data_size(const char *path, size_t *size)
+{
+	return (int) __SYSCALL3(SYS_SYSINFO_GET_DATA_SIZE, (sysarg_t) path,
+	    (sysarg_t) str_size(path), (sysarg_t) size);
+}
+
+extern void *sysinfo_get_data(const char *path, size_t *size)
+{
+	while (true) {
+		int ret = sysinfo_get_data_size(path, size);
+		if (ret != EOK)
+			return NULL;
+		
+		void *data = malloc(*size);
+		if (data == NULL)
+			return NULL;
+		
+		ret = __SYSCALL4(SYS_SYSINFO_GET_DATA, (sysarg_t) path,
+		    (sysarg_t) str_size(path), (sysarg_t) data, (sysarg_t) *size);
+		if (ret == EOK)
+			return data;
+		
+		if (ret != ENOMEM)
+			return NULL;
+		
+		free(data);
+	}
 }
 
Index: uspace/lib/c/generic/task.c
===================================================================
--- uspace/lib/c/generic/task.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/lib/c/generic/task.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -70,16 +70,21 @@
  * loader API.
  *
- * @param path pathname of the binary to execute
- * @param argv command-line arguments
+ * @param path Pathname of the binary to execute.
+ * @param argv Command-line arguments.
+ * @param err  If not NULL, the error value is stored here.
  *
  * @return ID of the newly created task or zero on error.
  *
  */
-task_id_t task_spawn(const char *path, const char *const args[])
+task_id_t task_spawn(const char *path, const char *const args[], int *err)
 {
 	/* Connect to a program loader. */
 	loader_t *ldr = loader_connect();
-	if (ldr == NULL)
+	if (ldr == NULL) {
+		if (err != NULL)
+			*err = EREFUSED;
+		
 		return 0;
+	}
 	
 	/* Get task ID. */
@@ -143,4 +148,8 @@
 	/* Success */
 	free(ldr);
+	
+	if (err != NULL)
+		*err = EOK;
+	
 	return task_id;
 	
@@ -149,4 +158,7 @@
 	loader_abort(ldr);
 	free(ldr);
+	
+	if (err != NULL)
+		*err = rc;
 	
 	return 0;
Index: uspace/lib/c/include/sysinfo.h
===================================================================
--- uspace/lib/c/include/sysinfo.h	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/lib/c/include/sysinfo.h	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -31,5 +31,5 @@
  */
 /** @file
- */ 
+ */
 
 #ifndef LIBC_SYSINFO_H_
@@ -37,8 +37,14 @@
 
 #include <libc.h>
-#include <sysinfo.h>
-#include <str.h>
 
-sysarg_t sysinfo_value(const char *name);
+typedef enum {
+	SYSINFO_VAL_UNDEFINED = 0,
+	SYSINFO_VAL_VAL = 1,
+	SYSINFO_VAL_DATA = 2
+} sysinfo_item_tag_t;
+
+extern sysinfo_item_tag_t sysinfo_get_tag(const char *);
+extern int sysinfo_get_value(const char *, sysarg_t *);
+extern void *sysinfo_get_data(const char *, size_t *);
 
 #endif
Index: uspace/lib/c/include/task.h
===================================================================
--- uspace/lib/c/include/task.h	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/lib/c/include/task.h	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -46,9 +46,8 @@
 
 extern task_id_t task_get_id(void);
-extern int task_set_name(const char *name);
-extern task_id_t task_spawn(const char *path, const char *const argv[]);
-extern int task_wait(task_id_t id, task_exit_t *texit, int *retval);
-extern int task_retval(int val);
-
+extern int task_set_name(const char *);
+extern task_id_t task_spawn(const char *, const char *const[], int *);
+extern int task_wait(task_id_t id, task_exit_t *, int *);
+extern int task_retval(int);
 
 #endif
Index: uspace/lib/net/adt/module_map.c
===================================================================
--- uspace/lib/net/adt/module_map.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/lib/net/adt/module_map.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -94,12 +94,13 @@
 }
 
-task_id_t spawn(const char * fname){
-	const char * argv[2];
+task_id_t spawn(const char *fname)
+{
+	const char *argv[2];
 	task_id_t res;
-
+	
 	argv[0] = fname;
 	argv[1] = NULL;
-	res = task_spawn(fname, argv);
-
+	res = task_spawn(fname, argv, NULL);
+	
 	return res;
 }
Index: uspace/srv/bd/rd/rd.c
===================================================================
--- uspace/srv/bd/rd/rd.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/bd/rd/rd.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -32,9 +32,9 @@
 /** @addtogroup rd
  * @{
- */ 
+ */
 
 /**
- * @file	rd.c
- * @brief	Initial RAM disk for HelenOS.
+ * @file rd.c
+ * @brief Initial RAM disk for HelenOS.
  */
 
@@ -61,4 +61,5 @@
 /** Pointer to the ramdisk's image */
 static void *rd_addr;
+
 /** Size of the ramdisk */
 static size_t rd_size;
@@ -70,16 +71,17 @@
 static int rd_write_blocks(uint64_t ba, size_t cnt, const void *buf);
 
-/**
- * This rwlock protects the ramdisk's data.
+/** This rwlock protects the ramdisk's data.
+ *
  * If we were to serve multiple requests (read + write or several writes)
- * concurrently (i.e. from two or more threads), each read and write needs to be
- * protected by this rwlock.
- */ 
+ * concurrently (i.e. from two or more threads), each read and write needs to
+ * be protected by this rwlock.
+ *
+ */
 fibril_rwlock_t rd_lock;
 
 /** Handle one connection to ramdisk.
  *
- * @param iid		Hash of the request that opened the connection.
- * @param icall		Call data of the request that opened the connection.
+ * @param iid   Hash of the request that opened the connection.
+ * @param icall Call data of the request that opened the connection.
  */
 static void rd_connection(ipc_callid_t iid, ipc_call_t *icall)
@@ -92,10 +94,10 @@
 	size_t cnt;
 	size_t comm_size;
-
+	
 	/*
 	 * Answer the first IPC_M_CONNECT_ME_TO call.
 	 */
 	ipc_answer_0(iid, EOK);
-
+	
 	/*
 	 * Now we wait for the client to send us its communication as_area.
@@ -108,5 +110,5 @@
 		} else {
 			ipc_answer_0(callid, EHANGUP);
-			return;		
+			return;
 		}
 	} else {
@@ -178,9 +180,9 @@
 		return ELIMIT;
 	}
-
+	
 	fibril_rwlock_read_lock(&rd_lock);
 	memcpy(buf, rd_addr + ba * block_size, block_size * cnt);
 	fibril_rwlock_read_unlock(&rd_lock);
-
+	
 	return EOK;
 }
@@ -193,9 +195,9 @@
 		return ELIMIT;
 	}
-
+	
 	fibril_rwlock_write_lock(&rd_lock);
 	memcpy(rd_addr + ba * block_size, buf, block_size * cnt);
 	fibril_rwlock_write_unlock(&rd_lock);
-
+	
 	return EOK;
 }
@@ -204,9 +206,14 @@
 static bool rd_init(void)
 {
-	rd_size = sysinfo_value("rd.size");
-	void *rd_ph_addr = (void *) sysinfo_value("rd.address.physical");
-	
-	if (rd_size == 0) {
-		printf(NAME ": No RAM disk found\n");
+	int ret = sysinfo_get_value("rd.size", &rd_size);
+	if ((ret != EOK) || (rd_size == 0)) {
+		printf("%s: No RAM disk found\n", NAME);
+		return false;
+	}
+	
+	sysarg_t rd_ph_addr;
+	ret = sysinfo_get_value("rd.address.physical", &rd_ph_addr);
+	if ((ret != EOK) || (rd_ph_addr == 0)) {
+		printf("%s: Invalid RAM disk physical address\n", NAME);
 		return false;
 	}
@@ -215,17 +222,17 @@
 	
 	int flags = AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE;
-	int retval = physmem_map(rd_ph_addr, rd_addr,
+	int retval = physmem_map((void *) rd_ph_addr, rd_addr,
 	    ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags);
 	
 	if (retval < 0) {
-		printf(NAME ": Error mapping RAM disk\n");
-		return false;
-	}
-	
-	printf(NAME ": Found RAM disk at %p, %d bytes\n", rd_ph_addr, rd_size);
+		printf("%s: Error mapping RAM disk\n", NAME);
+		return false;
+	}
+	
+	printf("%s: Found RAM disk at %p, %d bytes\n", NAME, rd_ph_addr, rd_size);
 	
 	int rc = devmap_driver_register(NAME, rd_connection);
 	if (rc < 0) {
-		printf(NAME ": Unable to register driver (%d)\n", rc);
+		printf("%s: Unable to register driver (%d)\n", NAME, rc);
 		return false;
 	}
@@ -234,5 +241,5 @@
 	if (devmap_device_register("bd/initrd", &dev_handle) != EOK) {
 		devmap_hangup_phone(DEVMAP_DRIVER);
-		printf(NAME ": Unable to register device\n");
+		printf("%s: Unable to register device\n", NAME);
 		return false;
 	}
@@ -245,10 +252,10 @@
 int main(int argc, char **argv)
 {
-	printf(NAME ": HelenOS RAM disk server\n");
+	printf("%s: HelenOS RAM disk server\n", NAME);
 	
 	if (!rd_init())
 		return -1;
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
 	async_manager();
 
Index: uspace/srv/hid/fb/ega.c
===================================================================
--- uspace/srv/hid/fb/ega.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hid/fb/ega.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -415,21 +415,36 @@
 	void *ega_ph_addr;
 	size_t sz;
-
-	ega_ph_addr = (void *) sysinfo_value("fb.address.physical");
-	scr_width = sysinfo_value("fb.width");
-	scr_height = sysinfo_value("fb.height");
-
-	if (sysinfo_value("fb.blinking")) {
+	
+	sysarg_t paddr;
+	if (sysinfo_get_value("fb.address.physical", &paddr) != EOK)
+		return -1;
+	
+	sysarg_t width;
+	if (sysinfo_get_value("fb.width", &width) != EOK)
+		return -1;
+	
+	sysarg_t height;
+	if (sysinfo_get_value("fb.width", &height) != EOK)
+		return -1;
+	
+	sysarg_t blinking;
+	if (sysinfo_get_value("fb.blinking", &blinking) != EOK)
+		blinking = false;
+	
+	ega_ph_addr = (void *) paddr;
+	scr_width = width;
+	scr_height = height;
+	if (blinking) {
 		ega_normal_color &= 0x77;
 		ega_inverted_color &= 0x77;
 	}
-
+	
 	style = NORMAL_COLOR;
-
+	
 	iospace_enable(task_get_id(), (void *) EGA_IO_BASE, 2);
-
+	
 	sz = scr_width * scr_height * 2;
 	scr_addr = as_get_mappable_page(sz);
-
+	
 	if (physmem_map(ega_ph_addr, scr_addr, ALIGN_UP(sz, PAGE_SIZE) >>
 	    PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE) != 0)
Index: uspace/srv/hid/fb/fb.c
===================================================================
--- uspace/srv/hid/fb/fb.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hid/fb/fb.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -1756,21 +1756,38 @@
 	async_set_client_connection(fb_client_connection);
 	
-	void *fb_ph_addr = (void *) sysinfo_value("fb.address.physical");
-	unsigned int fb_offset = sysinfo_value("fb.offset");
-	unsigned int fb_width = sysinfo_value("fb.width");
-	unsigned int fb_height = sysinfo_value("fb.height");
-	unsigned int fb_scanline = sysinfo_value("fb.scanline");
-	unsigned int fb_visual = sysinfo_value("fb.visual");
-
-	unsigned int fbsize = fb_scanline * fb_height;
+	sysarg_t fb_ph_addr;
+	if (sysinfo_get_value("fb.address.physical", &fb_ph_addr) != EOK)
+		return -1;
+	
+	sysarg_t fb_offset;
+	if (sysinfo_get_value("fb.offset", &fb_offset) != EOK)
+		fb_offset = 0;
+	
+	sysarg_t fb_width;
+	if (sysinfo_get_value("fb.width", &fb_width) != EOK)
+		return -1;
+	
+	sysarg_t fb_height;
+	if (sysinfo_get_value("fb.height", &fb_height) != EOK)
+		return -1;
+	
+	sysarg_t fb_scanline;
+	if (sysinfo_get_value("fb.scanline", &fb_scanline) != EOK)
+		return -1;
+	
+	sysarg_t fb_visual;
+	if (sysinfo_get_value("fb.visual", &fb_visual) != EOK)
+		return -1;
+	
+	sysarg_t fbsize = fb_scanline * fb_height;
 	void *fb_addr = as_get_mappable_page(fbsize);
-
-	if (physmem_map(fb_ph_addr + fb_offset, fb_addr,
+	
+	if (physmem_map((void *) fb_ph_addr + fb_offset, fb_addr,
 	    ALIGN_UP(fbsize, PAGE_SIZE) >> PAGE_WIDTH, AS_AREA_READ | AS_AREA_WRITE) != 0)
 		return -1;
-
+	
 	if (screen_init(fb_addr, fb_width, fb_height, fb_scanline, fb_visual))
 		return 0;
-
+	
 	return -1;
 }
Index: uspace/srv/hid/fb/main.c
===================================================================
--- uspace/srv/hid/fb/main.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hid/fb/main.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -60,11 +60,20 @@
 int main(int argc, char *argv[])
 {
-	printf(NAME ": HelenOS Framebuffer service\n");
+	printf("%s: HelenOS Framebuffer service\n", NAME);
 	
-	ipcarg_t phonead;
 	bool initialized = false;
+	sysarg_t fb_present;
+	sysarg_t fb_kind;
+	
+	if (sysinfo_get_value("fb", &fb_present) != EOK)
+		fb_present = false;
+	
+	if (sysinfo_get_value("fb.kind", &fb_kind) != EOK) {
+		printf("%s: Unable to detect framebuffer configuration\n", NAME);
+		return -1;
+	}
 	
 #ifdef FB_ENABLED
-	if (sysinfo_value("fb.kind") == 1) {
+	if ((!initialized) && (fb_kind == 1)) {
 		if (fb_init() == 0)
 			initialized = true;
@@ -72,5 +81,5 @@
 #endif
 #ifdef EGA_ENABLED
-	if ((!initialized) && (sysinfo_value("fb.kind") == 2)) {
+	if ((!initialized) && (fb_kind == 2)) {
 		if (ega_init() == 0)
 			initialized = true;
@@ -78,5 +87,5 @@
 #endif
 #ifdef MSIM_ENABLED
-	if ((!initialized) && (sysinfo_value("fb.kind") == 3)) {
+	if ((!initialized) && (fb_kind == 3)) {
 		if (msim_init() == 0)
 			initialized = true;
@@ -84,5 +93,5 @@
 #endif
 #ifdef SGCN_ENABLED
-	if ((!initialized) && (sysinfo_value("fb.kind") == 4)) {
+	if ((!initialized) && (fb_kind == 4)) {
 		if (sgcn_init() == 0)
 			initialized = true;
@@ -90,5 +99,5 @@
 #endif
 #ifdef NIAGARA_ENABLED
-	if ((!initialized) && (sysinfo_value("fb.kind") == 5)) {
+	if ((!initialized) && (fb_kind == 5)) {
 		if (niagara_init() == 0)
 			initialized = true;
@@ -96,5 +105,5 @@
 #endif
 #ifdef SKI_ENABLED
-	if ((!initialized) && (sysinfo_value("fb") != true)) {
+	if ((!initialized) && (!fb_present)) {
 		if (ski_init() == 0)
 			initialized = true;
@@ -105,8 +114,9 @@
 		return -1;
 	
+	ipcarg_t phonead;
 	if (ipc_connect_to_me(PHONE_NS, SERVICE_VIDEO, 0, 0, &phonead) != 0) 
 		return -1;
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
 	async_manager();
 	
Index: uspace/srv/hid/fb/msim.c
===================================================================
--- uspace/srv/hid/fb/msim.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hid/fb/msim.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -29,8 +29,8 @@
 
 /** @defgroup msimfb MSIM text console
- * @brief	HelenOS MSIM text console.
+ * @brief HelenOS MSIM text console.
  * @ingroup fbs
  * @{
- */ 
+ */
 /** @file
  */
@@ -41,4 +41,5 @@
 #include <as.h>
 #include <ddi.h>
+#include <errno.h>
 
 #include "serial_console.h"
@@ -57,8 +58,12 @@
 int msim_init(void)
 {
-	void *phys_addr = (void *) sysinfo_value("fb.address.physical");
+	sysarg_t phys_addr;
+	if (sysinfo_get_value("fb.address.physical", &phys_addr) != EOK)
+		return -1;
+	
 	virt_addr = (char *) as_get_mappable_page(1);
 	
-	if (physmem_map(phys_addr, virt_addr, 1, AS_AREA_READ | AS_AREA_WRITE) != 0)
+	if (physmem_map((void *) phys_addr, virt_addr, 1,
+	    AS_AREA_READ | AS_AREA_WRITE) != 0)
 		return -1;
 	
@@ -69,5 +74,4 @@
 }
 
-/** 
- * @}
+/** @}
  */
Index: uspace/srv/hid/fb/niagara.c
===================================================================
--- uspace/srv/hid/fb/niagara.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hid/fb/niagara.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -91,9 +91,12 @@
 int niagara_init(void)
 {
+	sysarg_t paddr;
+	if (sysinfo_get_value("niagara.outbuf.address", &paddr) != EOK)
+		return -1;
+	
 	output_buffer_addr = (uintptr_t) as_get_mappable_page(PAGE_SIZE);
-	int result = physmem_map(
-		(void *) sysinfo_value("niagara.outbuf.address"),
-		(void *) output_buffer_addr,
-		1, AS_AREA_READ | AS_AREA_WRITE);
+	int result = physmem_map((void *) paddr,
+	    (void *) output_buffer_addr, 1,
+	    AS_AREA_READ | AS_AREA_WRITE);
 
 	if (result != 0) {
Index: uspace/srv/hid/fb/sgcn.c
===================================================================
--- uspace/srv/hid/fb/sgcn.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hid/fb/sgcn.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -122,14 +122,22 @@
 int sgcn_init(void)
 {
-	sram_virt_addr = (uintptr_t) as_get_mappable_page(sysinfo_value("sram.area.size"));
+	sysarg_t sram_paddr;
+	if (sysinfo_get_value("sram.address.physical", &sram_paddr) != EOK)
+		return -1;
 	
-	if (physmem_map((void *) sysinfo_value("sram.address.physical"),
-	    (void *) sram_virt_addr, sysinfo_value("sram.area.size") / PAGE_SIZE,
-	    AS_AREA_READ | AS_AREA_WRITE) != 0)
+	sysarg_t sram_size;
+	if (sysinfo_get_value("sram.area.size", &sram_size) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("sram.buffer.offset", &sram_buffer_offset) != EOK)
+		sram_buffer_offset = 0;
+	
+	sram_virt_addr = (uintptr_t) as_get_mappable_page(sram_size);
+	
+	if (physmem_map((void *) sram_paddr, (void *) sram_virt_addr,
+	    sram_size / PAGE_SIZE, AS_AREA_READ | AS_AREA_WRITE) != 0)
 		return -1;
 	
 	serial_console_init(sgcn_putc, WIDTH, HEIGHT);
-	
-	sram_buffer_offset = sysinfo_value("sram.buffer.offset");
 	
 	async_set_client_connection(serial_client_connection);
Index: uspace/srv/hid/kbd/generic/kbd.c
===================================================================
--- uspace/srv/hid/kbd/generic/kbd.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hid/kbd/generic/kbd.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -212,9 +212,12 @@
 int main(int argc, char **argv)
 {
-	printf(NAME ": HelenOS Keyboard service\n");
-	
-	if (sysinfo_value("kbd.cir.fhc") == 1)
+	printf("%s: HelenOS Keyboard service\n", NAME);
+	
+	sysarg_t fhc;
+	sysarg_t obio;
+	
+	if ((sysinfo_get_value("kbd.cir.fhc", &fhc) == EOK) && (fhc))
 		cir_service = SERVICE_FHC;
-	else if (sysinfo_value("kbd.cir.obio") == 1)
+	else if ((sysinfo_get_value("kbd.cir.obio", &obio) == EOK) && (obio))
 		cir_service = SERVICE_OBIO;
 	
@@ -240,5 +243,5 @@
 	int rc = devmap_driver_register(NAME, client_connection);
 	if (rc < 0) {
-		printf(NAME ": Unable to register driver (%d)\n", rc);
+		printf("%s: Unable to register driver (%d)\n", NAME, rc);
 		return -1;
 	}
@@ -249,5 +252,5 @@
 	dev_handle_t dev_handle;
 	if (devmap_device_register(kbd, &dev_handle) != EOK) {
-		printf(NAME ": Unable to register device %s\n", kbd);
+		printf("%s: Unable to register device %s\n", NAME, kbd);
 		return -1;
 	}
Index: uspace/srv/hid/kbd/port/gxemul.c
===================================================================
--- uspace/srv/hid/kbd/port/gxemul.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hid/kbd/port/gxemul.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -41,4 +41,5 @@
 #include <kbd.h>
 #include <ddi.h>
+#include <errno.h>
 
 static irq_cmd_t gxemul_cmds[] = {
@@ -63,8 +64,15 @@
 int kbd_port_init(void)
 {
+	sysarg_t addr;
+	if (sysinfo_get_value("kbd.address.virtual", &addr) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
 	async_set_interrupt_received(gxemul_irq_handler);
-	gxemul_cmds[0].addr = (void *) sysinfo_value("kbd.address.virtual");
-	ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(),
-	    0, &gxemul_kbd);
+	gxemul_cmds[0].addr = (void *) addr;
+	ipc_register_irq(inr, device_assign_devno(), 0, &gxemul_kbd);
 	return 0;
 }
Index: uspace/srv/hid/kbd/port/msim.c
===================================================================
--- uspace/srv/hid/kbd/port/msim.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hid/kbd/port/msim.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -30,7 +30,7 @@
  * @ingroup  kbd
  * @{
- */ 
+ */
 /** @file
- * @brief	Msim keyboard port driver.
+ * @brief Msim keyboard port driver.
  */
 
@@ -41,4 +41,5 @@
 #include <kbd.h>
 #include <ddi.h>
+#include <errno.h>
 
 irq_cmd_t msim_cmds[] = {
@@ -63,8 +64,16 @@
 int kbd_port_init(void)
 {
+	sysarg_t vaddr;
+	if (sysinfo_get_value("kbd.address.virtual", &vaddr) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
+	msim_cmds[0].addr = (void *) vaddr;
 	async_set_interrupt_received(msim_irq_handler);
-	msim_cmds[0].addr = (void *) sysinfo_value("kbd.address.virtual");
-	ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(),
-	    0, &msim_kbd);
+	ipc_register_irq(inr, device_assign_devno(), 0, &msim_kbd);
+	
 	return 0;
 }
Index: uspace/srv/hid/kbd/port/niagara.c
===================================================================
--- uspace/srv/hid/kbd/port/niagara.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hid/kbd/port/niagara.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -44,6 +44,7 @@
 #include <thread.h>
 #include <bool.h>
+#include <errno.h>
 
-#define POLL_INTERVAL		10000
+#define POLL_INTERVAL  10000
 
 /**
@@ -57,5 +58,6 @@
  * kernel/arch/sparc64/src/drivers/niagara.c.
  */
-#define INPUT_BUFFER_SIZE	((PAGE_SIZE) - 2 * 8)
+#define INPUT_BUFFER_SIZE  ((PAGE_SIZE) - 2 * 8)
+
 typedef volatile struct {
 	uint64_t write_ptr;
@@ -79,24 +81,25 @@
 int kbd_port_init(void)
 {
+	sysarg_t paddr;
+	if (sysinfo_get_value("niagara.inbuf.address", &paddr) != EOK)
+		return -1;
+	
 	input_buffer_addr = (uintptr_t) as_get_mappable_page(PAGE_SIZE);
-	int result = physmem_map(
-		(void *) sysinfo_value("niagara.inbuf.address"),
-		(void *) input_buffer_addr,
-		1, AS_AREA_READ | AS_AREA_WRITE);
-
-	if (result != 0) {
+	int rc = physmem_map((void *) paddr, (void *) input_buffer_addr,
+	    1, AS_AREA_READ | AS_AREA_WRITE);
+	
+	if (rc != 0) {
 		printf("Niagara: uspace driver couldn't map physical memory: %d\n",
-			result);
-	}
-
-	input_buffer = (input_buffer_t) input_buffer_addr;
-
-	thread_id_t tid;
-	int rc;
-
-	rc = thread_create(niagara_thread_impl, NULL, "kbd_poll", &tid);
-	if (rc != 0) {
+		    rc);
 		return rc;
 	}
+	
+	input_buffer = (input_buffer_t) input_buffer_addr;
+	
+	thread_id_t tid;
+	rc = thread_create(niagara_thread_impl, NULL, "kbd_poll", &tid);
+	if (rc != 0)
+		return rc;
+	
 	return 0;
 }
Index: uspace/srv/hid/kbd/port/ns16550.c
===================================================================
--- uspace/srv/hid/kbd/port/ns16550.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hid/kbd/port/ns16550.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -30,7 +30,7 @@
  * @ingroup  kbd
  * @{
- */ 
+ */
 /** @file
- * @brief	NS16550 port driver.
+ * @brief NS16550 port driver.
  */
 
@@ -43,20 +43,21 @@
 #include <sun.h>
 #include <ddi.h>
+#include <errno.h>
 
 /* NS16550 registers */
-#define RBR_REG		0	/** Receiver Buffer Register. */
-#define IER_REG		1	/** Interrupt Enable Register. */
-#define IIR_REG		2	/** Interrupt Ident Register (read). */
-#define FCR_REG		2	/** FIFO control register (write). */
-#define LCR_REG		3	/** Line Control register. */
-#define MCR_REG		4	/** Modem Control Register. */
-#define LSR_REG		5	/** Line Status Register. */
+#define RBR_REG  0  /** Receiver Buffer Register. */
+#define IER_REG  1  /** Interrupt Enable Register. */
+#define IIR_REG  2  /** Interrupt Ident Register (read). */
+#define FCR_REG  2  /** FIFO control register (write). */
+#define LCR_REG  3  /** Line Control register. */
+#define MCR_REG  4  /** Modem Control Register. */
+#define LSR_REG  5  /** Line Status Register. */
 
-#define LSR_DATA_READY	0x01
+#define LSR_DATA_READY  0x01
 
 static irq_cmd_t ns16550_cmds[] = {
 	{
 		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,	/* will be patched in run-time */
+		.addr = (void *) 0,     /* Will be patched in run-time */
 		.dstarg = 1
 	},
@@ -74,5 +75,5 @@
 	{
 		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,	/* will be patched in run-time */
+		.addr = (void *) 0,     /* Will be patched in run-time */
 		.dstarg = 2
 	},
@@ -96,12 +97,20 @@
 	void *vaddr;
 
-	async_set_interrupt_received(ns16550_irq_handler);
-
-	ns16550_physical = sysinfo_value("kbd.address.physical");
-	ns16550_kernel = sysinfo_value("kbd.address.kernel");
+	if (sysinfo_get_value("kbd.address.physical", &ns16550_physical) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("kbd.address.kernel", &ns16550_kernel) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
 	ns16550_kbd.cmds[0].addr = (void *) (ns16550_kernel + LSR_REG);
 	ns16550_kbd.cmds[3].addr = (void *) (ns16550_kernel + RBR_REG);
-	ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(),
-	    sysinfo_value("kbd.inr"), &ns16550_kbd);
+	
+	async_set_interrupt_received(ns16550_irq_handler);
+	ipc_register_irq(inr, device_assign_devno(), inr, &ns16550_kbd);
+	
 	return pio_enable((void *) ns16550_physical, 8, &vaddr);
 }
Index: uspace/srv/hid/kbd/port/pl050.c
===================================================================
--- uspace/srv/hid/kbd/port/pl050.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hid/kbd/port/pl050.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -83,12 +83,17 @@
 int kbd_port_init(void)
 {
-
-	pl050_kbd.cmds[0].addr = (void *) sysinfo_value("kbd.address.status");
-	pl050_kbd.cmds[3].addr = (void *) sysinfo_value("kbd.address.data");
-
+	if (sysinfo_get_value("kbd.address.status", &pl050_kbd.cmds[0].addr) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("kbd.address.data", &pl050_kbd.cmds[3].addr) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
 	async_set_interrupt_received(pl050_irq_handler);
-
-	ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(), 0, &pl050_kbd);
-
+	ipc_register_irq(inr, device_assign_devno(), 0, &pl050_kbd);
+	
 	return 0;
 }
Index: uspace/srv/hid/kbd/port/sgcn.c
===================================================================
--- uspace/srv/hid/kbd/port/sgcn.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hid/kbd/port/sgcn.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -30,7 +30,7 @@
  * @ingroup  kbd
  * @{
- */ 
+ */
 /** @file
- * @brief	SGCN (Serengeti Console) keyboard port driver.
+ * @brief SGCN (Serengeti Console) keyboard port driver.
  */
 
@@ -44,10 +44,11 @@
 #include <thread.h>
 #include <bool.h>
+#include <errno.h>
 
-#define POLL_INTERVAL		10000
+#define POLL_INTERVAL  10000
 
 /**
  * SGCN buffer header. It is placed at the very beginning of the SGCN
- * buffer. 
+ * buffer.
  */
 typedef struct {
@@ -102,22 +103,28 @@
 int kbd_port_init(void)
 {
-	sram_virt_addr = (uintptr_t) as_get_mappable_page(sysinfo_value("sram.area.size"));
-	if (physmem_map((void *) sysinfo_value("sram.address.physical"),
-	    (void *) sram_virt_addr, sysinfo_value("sram.area.size") / PAGE_SIZE,
-	    AS_AREA_READ | AS_AREA_WRITE) != 0) {
+	sysarg_t sram_paddr;
+	if (sysinfo_get_value("sram.address.physical", &sram_paddr) != EOK)
+		return -1;
+	
+	sysarg_t sram_size;
+	if (sysinfo_get_value("sram.area.size", &sram_size) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("sram.buffer.offset", &sram_buffer_offset) != EOK)
+		sram_buffer_offset = 0;
+	
+	sram_virt_addr = (uintptr_t) as_get_mappable_page(sram_size);
+	
+	if (physmem_map((void *) sram_paddr, (void *) sram_virt_addr,
+	    sram_size / PAGE_SIZE, AS_AREA_READ | AS_AREA_WRITE) != 0) {
 		printf("SGCN: uspace driver could not map physical memory.");
 		return -1;
 	}
 	
-	sram_buffer_offset = sysinfo_value("sram.buffer.offset");
-
 	thread_id_t tid;
-	int rc;
-
-	rc = thread_create(sgcn_thread_impl, NULL, "kbd_poll", &tid);
-	if (rc != 0) {
+	int rc = thread_create(sgcn_thread_impl, NULL, "kbd_poll", &tid);
+	if (rc != 0)
 		return rc;
-	}
-
+	
 	return 0;
 }
Index: uspace/srv/hid/kbd/port/sun.c
===================================================================
--- uspace/srv/hid/kbd/port/sun.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hid/kbd/port/sun.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -39,4 +39,6 @@
 #include <sun.h>
 #include <sysinfo.h>
+#include <errno.h>
+#include <bool.h>
 
 /** Sun keyboard virtual port driver.
@@ -50,10 +52,18 @@
 int kbd_port_init(void)
 {
-	if (sysinfo_value("kbd.type.z8530")) {
+	sysarg_t z8530;
+	if (sysinfo_get_value("kbd.type.z8530", &z8530) != EOK)
+		z8530 = false;
+	
+	sysarg_t ns16550;
+	if (sysinfo_get_value("kbd.type.ns16550", &ns16550) != EOK)
+		ns16550 = false;
+	
+	if (z8530) {
 		if (z8530_port_init() == 0)
 			return 0;
 	}
 	
-	if (sysinfo_value("kbd.type.ns16550")) {
+	if (ns16550) {
 		if (ns16550_port_init() == 0)
 			return 0;
Index: uspace/srv/hid/kbd/port/z8530.c
===================================================================
--- uspace/srv/hid/kbd/port/z8530.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hid/kbd/port/z8530.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -30,7 +30,7 @@
  * @ingroup  kbd
  * @{
- */ 
+ */
 /** @file
- * @brief	Z8530 keyboard port driver.
+ * @brief Z8530 keyboard port driver.
  */
 
@@ -44,14 +44,15 @@
 #include <sys/types.h>
 #include <ddi.h>
+#include <errno.h>
 
-#define CHAN_A_STATUS	4
-#define CHAN_A_DATA	6
+#define CHAN_A_STATUS  4
+#define CHAN_A_DATA    6
 
-#define RR0_RCA	1
+#define RR0_RCA  1
 
 static irq_cmd_t z8530_cmds[] = {
 	{
 		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,	/* will be patched in run-time */
+		.addr = (void *) 0,     /* Will be patched in run-time */
 		.dstarg = 1
 	},
@@ -69,5 +70,5 @@
 	{
 		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,	/* will be patched in run-time */
+		.addr = (void *) 0,     /* Will be patched in run-time */
 		.dstarg = 2
 	},
@@ -86,11 +87,18 @@
 int z8530_port_init(void)
 {
+	sysarg_t kaddr;
+	if (sysinfo_get_value("kbd.address.kernel", &kaddr) != EOK)
+		return -1;
+	
+	sysarg_t inr;
+	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
+		return -1;
+	
+	z8530_cmds[0].addr = (void *) kaddr + CHAN_A_STATUS;
+	z8530_cmds[3].addr = (void *) kaddr + CHAN_A_DATA;
+	
 	async_set_interrupt_received(z8530_irq_handler);
-	z8530_cmds[0].addr = (void *) sysinfo_value("kbd.address.kernel") +
-	    CHAN_A_STATUS;
-	z8530_cmds[3].addr = (void *) sysinfo_value("kbd.address.kernel") +
-	    CHAN_A_DATA;
-	ipc_register_irq(sysinfo_value("kbd.inr"), device_assign_devno(),
-	    sysinfo_value("kbd.inr"), &z8530_kbd);
+	ipc_register_irq(inr, device_assign_devno(), inr, &z8530_kbd);
+	
 	return 0;
 }
Index: uspace/srv/hw/bus/cuda_adb/cuda_adb.c
===================================================================
--- uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hw/bus/cuda_adb/cuda_adb.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -254,11 +254,14 @@
 static int cuda_init(void)
 {
+	if (sysinfo_get_value("cuda.address.physical", &(instance->cuda_physical)) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("cuda.address.kernel", &(instance->cuda_kernel)) != EOK)
+		return -1;
+	
 	void *vaddr;
-
-	instance->cuda_physical = sysinfo_value("cuda.address.physical");
-	instance->cuda_kernel = sysinfo_value("cuda.address.kernel");
-
 	if (pio_enable((void *) instance->cuda_physical, sizeof(cuda_t), &vaddr) != 0)
 		return -1;
+	
 	dev = vaddr;
 
Index: uspace/srv/hw/char/i8042/i8042.c
===================================================================
--- uspace/srv/hw/char/i8042/i8042.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hw/char/i8042/i8042.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -164,14 +164,27 @@
 static int i8042_init(void)
 {
+	if (sysinfo_get_value("i8042.address.physical", &i8042_physical) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("i8042.address.kernel", &i8042_kernel) != EOK)
+		return -1;
+	
 	void *vaddr;
-
-	i8042_physical = sysinfo_value("i8042.address.physical");
-	i8042_kernel = sysinfo_value("i8042.address.kernel");
 	if (pio_enable((void *) i8042_physical, sizeof(i8042_t), &vaddr) != 0)
 		return -1;
+	
 	i8042 = vaddr;
-
+	
+	sysarg_t inr_a;
+	sysarg_t inr_b;
+	
+	if (sysinfo_get_value("i8042.inr_a", &inr_a) != EOK)
+		return -1;
+	
+	if (sysinfo_get_value("i8042.inr_b", &inr_b) != EOK)
+		return -1;
+	
 	async_set_interrupt_received(i8042_irq_handler);
-
+	
 	/* Disable kbd and aux */
 	wait_ready();
@@ -186,8 +199,7 @@
 	i8042_kbd.cmds[0].addr = (void *) &((i8042_t *) i8042_kernel)->status;
 	i8042_kbd.cmds[3].addr = (void *) &((i8042_t *) i8042_kernel)->data;
-	ipc_register_irq(sysinfo_value("i8042.inr_a"), device_assign_devno(), 0, &i8042_kbd);
-	ipc_register_irq(sysinfo_value("i8042.inr_b"), device_assign_devno(), 0, &i8042_kbd);
-	printf("i8042: registered for interrupts %d and %d\n",
-	    sysinfo_value("i8042.inr_a"), sysinfo_value("i8042.inr_b"));
+	ipc_register_irq(inr_a, device_assign_devno(), 0, &i8042_kbd);
+	ipc_register_irq(inr_b, device_assign_devno(), 0, &i8042_kbd);
+	printf("%s: registered for interrupts %d and %d\n", NAME, inr_a, inr_b);
 
 	wait_ready();
Index: uspace/srv/hw/cir/fhc/fhc.c
===================================================================
--- uspace/srv/hw/cir/fhc/fhc.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hw/cir/fhc/fhc.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -109,14 +109,13 @@
 static bool fhc_init(void)
 {
-	ipcarg_t phonead;
+	sysarg_t paddr;
 
-	fhc_uart_size = sysinfo_value("fhc.uart.size");
-	fhc_uart_phys = (void *) sysinfo_value("fhc.uart.physical");
-	
-	if (!fhc_uart_size) {
+	if ((sysinfo_get_value("fhc.uart.physical", &paddr) != EOK)
+	    || (sysinfo_get_value("fhc.uart.size", &fhc_uart_size) != EOK)) {
 		printf(NAME ": no FHC UART registers found\n");
 		return false;
 	}
-
+	
+	fhc_uart_phys = (void *) paddr;
 	fhc_uart_virt = as_get_mappable_page(fhc_uart_size);
 	
@@ -132,6 +131,7 @@
 	printf(NAME ": FHC UART registers at %p, %d bytes\n", fhc_uart_phys,
 	    fhc_uart_size);
-
+	
 	async_set_client_connection(fhc_connection);
+	ipcarg_t phonead;
 	ipc_connect_to_me(PHONE_NS, SERVICE_FHC, 0, 0, &phonead);
 	
Index: uspace/srv/hw/cir/obio/obio.c
===================================================================
--- uspace/srv/hw/cir/obio/obio.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/hw/cir/obio/obio.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -112,13 +112,12 @@
 static bool obio_init(void)
 {
-	ipcarg_t phonead;
-
-	base_phys = (void *) sysinfo_value("obio.base.physical");
+	sysarg_t paddr;
 	
-	if (!base_phys) {
+	if (sysinfo_get_value("obio.base.physical", &paddr) != EOK) {
 		printf(NAME ": no OBIO registers found\n");
 		return false;
 	}
-
+	
+	base_phys = (void *) paddr;
 	base_virt = as_get_mappable_page(OBIO_SIZE);
 	
@@ -133,6 +132,7 @@
 	
 	printf(NAME ": OBIO registers with base at %p\n", base_phys);
-
+	
 	async_set_client_connection(obio_connection);
+	ipcarg_t phonead;
 	ipc_connect_to_me(PHONE_NS, SERVICE_OBIO, 0, 0, &phonead);
 	
Index: uspace/srv/net/cfg/ne2k.netif_nil_bundle
===================================================================
--- uspace/srv/net/cfg/ne2k.netif_nil_bundle	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/net/cfg/ne2k.netif_nil_bundle	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -7,5 +7,4 @@
 IL=ip
 
-# sysinfo_value("netif.dp8390.inr")
 IRQ=9
 IO=300
Index: uspace/srv/net/cfg/ne2k.netif_standalone
===================================================================
--- uspace/srv/net/cfg/ne2k.netif_standalone	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/net/cfg/ne2k.netif_standalone	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -7,5 +7,4 @@
 IL=ip
 
-# sysinfo_value("netif.dp8390.inr")
 IRQ=9
 IO=300
Index: uspace/srv/net/netstart/netstart.c
===================================================================
--- uspace/srv/net/netstart/netstart.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/net/netstart/netstart.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -44,4 +44,5 @@
 #include <stdio.h>
 #include <task.h>
+#include <str_error.h>
 #include <ipc/ipc.h>
 #include <ipc/services.h>
@@ -71,6 +72,8 @@
 	argv[1] = NULL;
 	
-	if (task_spawn(path, argv) == 0) {
-		fprintf(stderr, "%s: Error spawning %s\n", NAME, path);
+	int err;
+	if (task_spawn(path, argv, &err) == 0) {
+		fprintf(stderr, "%s: Error spawning %s (%s)\n", NAME, path,
+		    str_error(err));
 		return false;
 	}
Index: uspace/srv/ns/ns.c
===================================================================
--- uspace/srv/ns/ns.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/ns/ns.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -55,8 +55,8 @@
 static void *klogaddr = NULL;
 
-static void get_as_area(ipc_callid_t callid, ipc_call_t *call, void *ph_addr,
+static void get_as_area(ipc_callid_t callid, ipc_call_t *call, void *faddr,
     size_t pages, void **addr)
 {
-	if (ph_addr == NULL) {
+	if ((faddr == NULL) || (pages == 0)) {
 		ipc_answer_0(callid, ENOENT);
 		return;
@@ -71,5 +71,5 @@
 		}
 		
-		if (physmem_map(ph_addr, *addr, pages,
+		if (physmem_map(faddr, *addr, pages,
 		    AS_AREA_READ | AS_AREA_CACHEABLE) != 0) {
 			ipc_answer_0(callid, ENOENT);
@@ -81,4 +81,32 @@
 }
 
+static void setup_clock_area(ipc_callid_t callid, ipc_call_t *call, void **addr)
+{
+	uintptr_t faddr;
+	int err = sysinfo_get_value("clock.faddr", &faddr);
+	
+	if (err != EOK)
+		ipc_answer_0(callid, err);
+	
+	get_as_area(callid, call, (void *) faddr, 1, addr);
+}
+
+static void setup_klog_area(ipc_callid_t callid, ipc_call_t *call, void **addr)
+{
+	uintptr_t faddr;
+	int err = sysinfo_get_value("klog.faddr", &faddr);
+	
+	if (err != EOK)
+		ipc_answer_0(callid, err);
+	
+	size_t pages;
+	err = sysinfo_get_value("klog.pages", &pages);
+	
+	if (err != EOK)
+		ipc_answer_0(callid, err);
+	
+	get_as_area(callid, call, (void *) faddr, pages, addr);
+}
+
 int main(int argc, char **argv)
 {
@@ -97,5 +125,5 @@
 		return rc;
 	
-	printf(NAME ": Accepting connections\n");
+	printf("%s: Accepting connections\n", NAME);
 	
 	while (true) {
@@ -113,12 +141,8 @@
 			switch (IPC_GET_ARG3(call)) {
 			case SERVICE_MEM_REALTIME:
-				get_as_area(callid, &call,
-				    (void *) sysinfo_value("clock.faddr"),
-				    1, &clockaddr);
+				setup_clock_area(callid, &call, &clockaddr);
 				break;
 			case SERVICE_MEM_KLOG:
-				get_as_area(callid, &call,
-				    (void *) sysinfo_value("klog.faddr"),
-				    sysinfo_value("klog.pages"), &klogaddr);
+				setup_klog_area(callid, &call, &klogaddr);
 				break;
 			default:
Index: uspace/srv/taskmon/taskmon.c
===================================================================
--- uspace/srv/taskmon/taskmon.c	(revision 9256ad291d0e010f6b4ac8cec3d9a1b6e2233795)
+++ uspace/srv/taskmon/taskmon.c	(revision d9fae23532028671526d24c90116318f54d92d29)
@@ -44,4 +44,5 @@
 #include <macros.h>
 #include <errno.h>
+#include <str_error.h>
 
 #define NAME  "taskmon"
@@ -96,7 +97,9 @@
 	}
 	putchar('\n');
-
-	if (!task_spawn(fname, argv))
-		printf(NAME ": Error spawning taskdump.\n", fname);
+	
+	int err;
+	if (!task_spawn(fname, argv, &err))
+		printf("%s: Error spawning %s (%s).\n", NAME, fname,
+		    str_error(err));
 }
 
