Index: kernel/generic/src/syscall/syscall.c
===================================================================
--- kernel/generic/src/syscall/syscall.c	(revision 5869ce0ca5fd1906d3f917cf2a38b5a804b18b9d)
+++ kernel/generic/src/syscall/syscall.c	(revision 0030eef187b4b4a1af1fe738a6c7c95f7c5cc95f)
@@ -184,4 +184,6 @@
 	
 	/* Sysinfo syscalls. */
+	(syshandler_t) sys_sysinfo_get_keys_size,
+	(syshandler_t) sys_sysinfo_get_keys,
 	(syshandler_t) sys_sysinfo_get_val_type,
 	(syshandler_t) sys_sysinfo_get_value,
Index: kernel/generic/src/sysinfo/sysinfo.c
===================================================================
--- kernel/generic/src/sysinfo/sysinfo.c	(revision 5869ce0ca5fd1906d3f917cf2a38b5a804b18b9d)
+++ kernel/generic/src/sysinfo/sysinfo.c	(revision 0030eef187b4b4a1af1fe738a6c7c95f7c5cc95f)
@@ -110,5 +110,5 @@
  * @param subtree Current sysinfo (sub)tree root item.
  * @param ret     If the return value is NULL, this argument
- *                can be either also NULL (i.e. no item was
+ *                can be set either to NULL (i.e. no item was
  *                found and no data was generated) or the
  *                original pointer is used to store the value
@@ -125,5 +125,4 @@
 {
 	ASSERT(subtree != NULL);
-	ASSERT(ret != NULL);
 	
 	sysinfo_item_t *cur = subtree;
@@ -151,10 +150,14 @@
 			case SYSINFO_SUBTREE_FUNCTION:
 				/* Get generated data */
-				**ret = cur->subtree.generator.fn(name + i + 1, dry_run,
-				    cur->subtree.generator.data);
+				if (ret != NULL)
+					**ret = cur->subtree.generator.fn(name + i + 1,
+					    dry_run, cur->subtree.generator.data);
+				
 				return NULL;
 			default:
 				/* Not found, no data generated */
-				*ret = NULL;
+				if (ret != NULL)
+					*ret = NULL;
+				
 				return NULL;
 			}
@@ -165,5 +168,7 @@
 	
 	/* Not found, no data generated */
-	*ret = NULL;
+	if (ret != NULL)
+		*ret = NULL;
+	
 	return NULL;
 }
@@ -653,4 +658,193 @@
 }
 
+/** Return sysinfo keys determined by name
+ *
+ * Should be called with sysinfo_lock held.
+ *
+ * @param name    Sysinfo path.
+ * @param root    Root item of the sysinfo (sub)tree.
+ *                If it is NULL then consider the global
+ *                sysinfo tree.
+ * @param dry_run Do not actually get any generated
+ *                binary data, just calculate the size.
+ *
+ * @return Item value (constant or generated).
+ *
+ */
+NO_TRACE static sysinfo_return_t sysinfo_get_keys(const char *name,
+    sysinfo_item_t **root, bool dry_run)
+{
+	if (root == NULL)
+		root = &global_root;
+	
+	/* Try to find the item */
+	sysinfo_item_t *item = sysinfo_find_item(name, *root, NULL,
+	    dry_run);
+	
+	sysinfo_return_t ret;
+	
+	if ((item != NULL) && (item->subtree_type == SYSINFO_SUBTREE_TABLE)) {
+		/*
+		 * Subtree found in the fixed sysinfo tree.
+		 * Calculate the size of subkeys.
+		 */
+		size_t size = 0;
+		for (sysinfo_item_t *cur = item->subtree.table; cur;
+		    cur = cur->next)
+			size += str_size(cur->name) + 1;
+		
+		if (dry_run) {
+			ret.tag = SYSINFO_VAL_FUNCTION_DATA;
+			ret.data.data = NULL;
+			ret.data.size = size;
+		} else {
+			/* Allocate buffer for subkeys */
+			char *names = (char *) malloc(size, FRAME_ATOMIC);
+			if (names == NULL)
+				return ret;
+			
+			size_t pos = 0;
+			for (sysinfo_item_t *cur = item->subtree.table; cur;
+			    cur = cur->next) {
+				str_cpy(names + pos, size - pos, cur->name);
+				pos += str_size(cur->name) + 1;
+			}
+			
+			/* Correct return value */
+			ret.tag = SYSINFO_VAL_FUNCTION_DATA;
+			ret.data.data = (void *) names;
+			ret.data.size = size;
+		}
+	} else {
+		/* No item in the fixed sysinfo tree */
+		ret.tag = SYSINFO_VAL_UNDEFINED;
+	}
+	
+	return ret;
+}
+
+/** Return sysinfo keys determined by name from user space
+ *
+ * The path string passed from the user space has to be properly
+ * null-terminated (the last passed character must be null).
+ *
+ * @param ptr     Sysinfo path in the user address space.
+ * @param size    Size of the path string.
+ * @param dry_run Do not actually get any generated
+ *                binary data, just calculate the size.
+ *
+ */
+NO_TRACE static sysinfo_return_t sysinfo_get_keys_uspace(void *ptr, size_t size,
+    bool dry_run)
+{
+	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)) {
+		/*
+		 * Prevent other functions from messing with sysinfo while we
+		 * are reading it.
+		 */
+		mutex_lock(&sysinfo_lock);
+		ret = sysinfo_get_keys(path, NULL, dry_run);
+		mutex_unlock(&sysinfo_lock);
+	}
+	
+	free(path);
+	return ret;
+}
+
+/** Get the sysinfo keys size (syscall)
+ *
+ * The path string passed from the user space has
+ * to be properly null-terminated (the last passed
+ * character must be null).
+ *
+ * @param path_ptr  Sysinfo path in the user address space.
+ * @param path_size Size of the path string.
+ * @param size_ptr  User space pointer where to store the
+ *                  keys size.
+ *
+ * @return Error code (EOK in case of no error).
+ *
+ */
+sysarg_t sys_sysinfo_get_keys_size(void *path_ptr, size_t path_size,
+    void *size_ptr)
+{
+	int rc;
+	
+	/*
+	 * Get the keys.
+	 *
+	 * N.B.: There is no need to free any potential keys
+	 * since we request a dry run.
+	 */
+	sysinfo_return_t ret =
+	    sysinfo_get_keys_uspace(path_ptr, path_size, true);
+	
+	/* Check return data tag */
+	if (ret.tag == SYSINFO_VAL_DATA)
+		rc = copy_to_uspace(size_ptr, &ret.data.size,
+		    sizeof(ret.data.size));
+	else
+		rc = EINVAL;
+	
+	return (sysarg_t) rc;
+}
+
+/** Get the sysinfo keys (syscall)
+ *
+ * The path string passed from the user space has
+ * to be properly null-terminated (the last passed
+ * character must be null).
+ *
+ * If the user space buffer size does not equal
+ * the actual size of the returned data, the data
+ * is truncated.
+ *
+ * The actual size of data returned is stored to
+ * size_ptr.
+ *
+ * @param path_ptr    Sysinfo path in the user address space.
+ * @param path_size   Size of the path string.
+ * @param buffer_ptr  User space pointer to the buffer where
+ *                    to store the binary data.
+ * @param buffer_size User space buffer size.
+ * @param size_ptr    User space pointer where to store the
+ *                    binary data size.
+ *
+ * @return Error code (EOK in case of no error).
+ *
+ */
+sysarg_t sys_sysinfo_get_keys(void *path_ptr, size_t path_size,
+    void *buffer_ptr, size_t buffer_size, size_t *size_ptr)
+{
+	int rc;
+	
+	/* Get the keys */
+	sysinfo_return_t ret = sysinfo_get_keys_uspace(path_ptr, path_size,
+	    false);
+	
+	/* Check return data tag */
+	if (ret.tag == SYSINFO_VAL_DATA) {
+		size_t size = min(ret.data.size, buffer_size);
+		rc = copy_to_uspace(buffer_ptr, ret.data.data, size);
+		if (rc == EOK)
+			rc = copy_to_uspace(size_ptr, &size, sizeof(size));
+		
+		free(ret.data.data);
+	} else
+		rc = EINVAL;
+	
+	return (sysarg_t) rc;
+}
+
 /** Get the sysinfo value type (syscall)
  *
