Index: boot/Makefile
===================================================================
--- boot/Makefile	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ boot/Makefile	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -70,4 +70,5 @@
 endif
 
+	cp -r -L $(INITRD_CFG_PATH)/* $(DIST_PATH)/cfg
 	for app in $(RD_APPS) ; do \
 		app_dir="`dirname "$$app"`" ; \
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ boot/Makefile.common	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -50,4 +50,7 @@
 TOOLS_PATH = $(ROOT_PATH)/tools
 DRVS_PATH = drv
+INITRD_CFG_PATH = $(USPACE_PATH)/cfg
+# TODO configuration separation may change
+ROOTFS_CFG_PATH = $(USPACE_PATH)/cfg
 
 MKARRAY = $(TOOLS_PATH)/mkarray.py
Index: uspace/cfg/sysman/rootfs.mnt
===================================================================
--- uspace/cfg/sysman/rootfs.mnt	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
+++ uspace/cfg/sysman/rootfs.mnt	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -0,0 +1,4 @@
+What = devices/\hw\pci0\00:01.0\ata-c1\d0
+Where = /root
+Type = fat
+
Index: uspace/srv/sysman/Makefile
===================================================================
--- uspace/srv/sysman/Makefile	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ uspace/srv/sysman/Makefile	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -29,5 +29,6 @@
 
 USPACE_PREFIX = ../..
-EXTRA_CFLAGS = -I. -I./units
+LIBS = $(LIBCONF_PREFIX)/libconf.a
+EXTRA_CFLAGS += -I. -I./units -I$(LIBCONF_PREFIX)/include
 BINARY = sysman
 STATIC_NEEDED = y
@@ -41,6 +42,7 @@
 	unit.c \
 	units/unit_cfg.c \
-	units/unit_mnt.c  \
-	units/unit_tgt.c
+	units/unit_mnt.c \
+	units/unit_tgt.c \
+	util.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/sysman/configuration.c
===================================================================
--- uspace/srv/sysman/configuration.c	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ uspace/srv/sysman/configuration.c	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -1,2 +1,4 @@
+#include <adt/hash.h>
+#include <adt/hash_table.h>
 #include <adt/list.h>
 #include <assert.h>
@@ -5,42 +7,185 @@
 
 #include "configuration.h"
+#include "dep.h"
 #include "log.h"
 
-static list_t units;
-static fibril_mutex_t units_mtx;
+static hash_table_t units;
+static fibril_rwlock_t units_rwl;
+
+/* Hash table functions */
+static size_t units_ht_hash(const ht_link_t *item)
+{
+	unit_t *unit =
+	    hash_table_get_inst(item, unit_t, units);
+	return hash_string(unit->name);
+}
+
+static size_t units_ht_key_hash(void *key)
+{
+	return hash_string((const char *)key);
+}
+
+static bool units_ht_equal(const ht_link_t *item1, const ht_link_t *item2)
+{
+	return str_cmp(
+	    hash_table_get_inst(item1, unit_t, units)->name,
+	    hash_table_get_inst(item2, unit_t, units)->name) == 0;
+}
+
+static bool units_ht_key_equal(void *key, const ht_link_t *item)
+{
+	return str_cmp((const char *)key,
+	    hash_table_get_inst(item, unit_t, units)->name) == 0;
+}
+
+
+static hash_table_ops_t units_ht_ops = {
+	.hash            = &units_ht_hash,
+	.key_hash        = &units_ht_key_hash,
+	.equal           = &units_ht_equal,
+	.key_equal       = &units_ht_key_equal,
+	.remove_callback = NULL // TODO realy unneeded?
+};
+
+/* Configuration functions */
 
 void configuration_init(void)
 {
-	list_initialize(&units);
-	fibril_mutex_initialize(&units_mtx);
+	hash_table_create(&units, 0, 0, &units_ht_ops);
+	fibril_rwlock_initialize(&units_rwl);
 }
 
 int configuration_add_unit(unit_t *unit)
 {
-	sysman_log(LVL_DEBUG2, "%s(%p)", __func__, unit);
 	assert(unit);
 	assert(unit->state == STATE_EMBRYO);
+	assert(unit->name != NULL);
+	assert(fibril_rwlock_is_write_locked(&units_rwl));
+	sysman_log(LVL_DEBUG2, "%s('%s')", __func__, unit_name(unit));
 
-	fibril_mutex_lock(&units_mtx);
-	list_append(&unit->units, &units);
-	
-	// TODO check name uniqueness
-	fibril_mutex_unlock(&units_mtx);
-	return EOK;
+	if (hash_table_insert_unique(&units, &unit->units)) {
+		return EOK;
+	} else {
+		return EEXISTS;
+	}
+}
+
+void configuration_start_update(void) {
+	assert(!fibril_rwlock_is_write_locked(&units_rwl));
+	sysman_log(LVL_DEBUG2, "%s", __func__);
+	fibril_rwlock_write_lock(&units_rwl);
+}
+
+static bool configuration_commit_unit(ht_link_t *ht_link, void *arg)
+{
+	unit_t *unit = hash_table_get_inst(ht_link, unit_t, units);
+	// TODO state locking?
+	if (unit->state == STATE_EMBRYO) {
+		unit->state = STATE_STOPPED;
+	}
+
+	list_foreach(unit->dependencies, dependencies, unit_dependency_t, dep) {
+		if (dep->state == DEP_EMBRYO) {
+			dep->state = DEP_VALID;
+		}
+	}
+	return true;
 }
 
 /** Marks newly added units as usable (via state change) */
-int configuration_commit(void)
+void configuration_commit(void)
 {
+	assert(fibril_rwlock_is_write_locked(&units_rwl));
 	sysman_log(LVL_DEBUG2, "%s", __func__);
 
-	fibril_mutex_lock(&units_mtx);
-	list_foreach(units, units, unit_t, u) {
-		if (u->state == STATE_EMBRYO) {
-			u->state = STATE_STOPPED;
+	/*
+	 * Apply commit to all units, each commited unit commits its outgoing
+	 * deps, thus eventually commiting all embryo deps as well.
+	 */
+	hash_table_apply(&units, &configuration_commit_unit, NULL);
+	fibril_rwlock_write_unlock(&units_rwl);
+}
+
+static bool configuration_rollback_unit(ht_link_t *ht_link, void *arg)
+{
+	unit_t *unit = hash_table_get_inst(ht_link, unit_t, units);
+
+	list_foreach_safe(unit->dependencies, cur_link, next_link) {
+		unit_dependency_t *dep =
+		    list_get_instance(cur_link, unit_dependency_t, dependencies);
+		if (dep->state == DEP_EMBRYO) {
+			dep_remove_dependency(&dep);
 		}
 	}
-	fibril_mutex_unlock(&units_mtx);
 
-	return EOK;
+	if (unit->state == STATE_EMBRYO) {
+		hash_table_remove_item(&units, ht_link);
+		unit_destroy(&unit);
+	}
+
+	return true;
 }
+
+void configuration_rollback(void)
+{
+	assert(fibril_rwlock_is_write_locked(&units_rwl));
+	sysman_log(LVL_DEBUG2, "%s", __func__);
+
+	hash_table_apply(&units, &configuration_rollback_unit, NULL);
+	fibril_rwlock_write_unlock(&units_rwl);
+}
+
+static bool configuration_resolve_unit(ht_link_t *ht_link, void *arg)
+{
+	bool *has_error_ptr = arg;
+	unit_t *unit = hash_table_get_inst(ht_link, unit_t, units);
+
+	list_foreach(unit->dependencies, dependencies, unit_dependency_t, dep) {
+		assert(dep->dependant == unit);
+		assert((dep->dependency != NULL) != (dep->dependency_name != NULL));
+		if (dep->dependency) {
+			continue;
+		}
+
+		unit_t *dependency =
+		    configuration_find_unit_by_name(dep->dependency_name);
+		if (dependency == NULL) {
+			sysman_log(LVL_ERROR,
+			    "Cannot resolve dependency of '%s' to unit '%s'",
+			    unit_name(unit), dep->dependency_name);
+			*has_error_ptr = true;
+			// TODO should we just leave the sprout untouched?
+		} else {
+			dep_resolve_dependency(dep, dependency);
+		}
+	}
+
+	return true;
+}
+
+/** Resolve unresolved dependencies between any pair of units
+ *
+ * @return EOK      on success
+ * @return ENONENT  when one or more resolution fails, information is logged
+ */
+int configuration_resolve_dependecies(void)
+{
+	assert(fibril_rwlock_is_write_locked(&units_rwl));
+	sysman_log(LVL_DEBUG2, "%s", __func__);
+
+	bool has_error = false;
+	hash_table_apply(&units, &configuration_resolve_unit, &has_error);
+
+	return has_error ? ENOENT : EOK;
+}
+
+unit_t *configuration_find_unit_by_name(const char *name)
+{
+	ht_link_t *ht_link = hash_table_find(&units, (void *)name);
+	if (ht_link != NULL) {
+		return hash_table_get_inst(ht_link, unit_t, units);
+	} else {
+		return NULL;
+	}
+}
+
Index: uspace/srv/sysman/configuration.h
===================================================================
--- uspace/srv/sysman/configuration.h	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ uspace/srv/sysman/configuration.h	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -8,5 +8,14 @@
 extern int configuration_add_unit(unit_t *);
 
-extern int configuration_commit(void);
+extern void configuration_start_update(void);
+
+extern void configuration_commit(void);
+
+extern void configuration_rollback(void);
+
+extern int configuration_resolve_dependecies(void);
+
+extern unit_t *configuration_find_unit_by_name(const char *);
+
 
 #endif
Index: uspace/srv/sysman/dep.c
===================================================================
--- uspace/srv/sysman/dep.c	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ uspace/srv/sysman/dep.c	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -1,6 +1,82 @@
+#include <assert.h>
 #include <errno.h>
 #include <stdlib.h>
+#include <str.h>
 
 #include "dep.h"
+
+static void dep_dependency_init(unit_dependency_t *dep)
+{
+	link_initialize(&dep->dependants);
+	link_initialize(&dep->dependencies);
+
+	dep->dependency_name = NULL;
+	dep->state = DEP_EMBRYO;
+}
+
+unit_dependency_t *dep_dependency_create(void)
+{
+	unit_dependency_t *dep = malloc(sizeof(unit_dependency_t));
+	if (dep) {
+		dep_dependency_init(dep);
+	}
+	return dep;
+}
+
+void dep_dependency_destroy(unit_dependency_t **dep_ptr)
+{
+	unit_dependency_t *dep = *dep_ptr;
+	if (dep == NULL) {
+		return;
+	}
+
+	list_remove(&dep->dependencies);
+	list_remove(&dep->dependants);
+
+	free(dep->dependency_name);
+	free(dep);
+
+	*dep_ptr = NULL;
+}
+
+int dep_sprout_dependency(unit_t *dependant, const char *dependency_name)
+{
+	unit_dependency_t *dep = dep_dependency_create();
+	int rc;
+
+	if (dep == NULL) {
+		rc = ENOMEM;
+		goto finish;
+	}
+
+	dep->dependency_name = str_dup(dependency_name);
+	if (dep->dependency_name == NULL) {
+		rc = ENOMEM;
+		goto finish;
+	}
+
+	list_append(&dep->dependencies, &dependant->dependencies);
+	dep->dependant = dependant;
+
+	rc = EOK;
+
+finish:
+	if (rc != EOK) {
+		dep_dependency_destroy(&dep);
+	}
+	return rc;
+}
+
+void dep_resolve_dependency(unit_dependency_t *dep, unit_t *unit)
+{
+	assert(dep->dependency == NULL);
+	assert(dep->dependency_name != NULL);
+
+	// TODO add to other side dependants list
+	dep->dependency = unit;
+	free(dep->dependency_name);
+	dep->dependency_name = NULL;
+}
+
 
 /**
@@ -10,19 +86,28 @@
 int dep_add_dependency(unit_t *dependant, unit_t *dependency)
 {
-	unit_dependency_t *edge = malloc(sizeof(unit_dependency_t));
-	if (edge == NULL) {
+	unit_dependency_t *dep = dep_dependency_create();
+	if (dep == NULL) {
 		return ENOMEM;
 	}
-	link_initialize(&edge->dependants);
-	link_initialize(&edge->dependencies);
 
-	// TODO check existence of the edge
+	// TODO check existence of the dep
 	// TODO locking
 	// TODO check types and states of connected units
-	list_append(&edge->dependants, &dependency->dependants);
-	list_append(&edge->dependencies, &dependant->dependencies);
+	list_append(&dep->dependants, &dependency->dependants);
+	list_append(&dep->dependencies, &dependant->dependencies);
 
-	edge->dependant = dependant;
-	edge->dependency = dependency;
+	dep->dependant = dependant;
+	dep->dependency = dependency;
 	return EOK;
 }
+
+/** Remove dependency from dependency graph
+ *
+ * Given dependency is removed from graph and unallocated.
+ */
+void dep_remove_dependency(unit_dependency_t **dep_ptr)
+{
+	// TODO here should be some checks, othewise replace this wrapper with
+	//      direct destroy
+	dep_dependency_destroy(dep_ptr);
+}
Index: uspace/srv/sysman/dep.h
===================================================================
--- uspace/srv/sysman/dep.h	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ uspace/srv/sysman/dep.h	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -6,16 +6,47 @@
 #include "unit.h"
 
-/** Dependency edge between unit in dependency graph */
+typedef enum {
+	DEP_EMBRYO,
+	DEP_VALID
+} dependency_state_t;
+
+/** Dependency edge between unit in dependency graph
+ *
+ * @code
+ * dependant ---> dependency
+ * @endcode
+ *
+ */
 typedef struct {
+	/** Link to dependants list */
 	link_t dependants;
+	/** Link to dependencies list */
 	link_t dependencies;
+
+	dependency_state_t state;
 
 	/** Unit that depends on another */
 	unit_t *dependant;
+
 	/** Unit that is dependency for another */
 	unit_t *dependency;
+
+	/** Name of the dependency unit, for resolved dependencies it's NULL
+	 *
+	 * @note Either dependency or dependency_name is set. Never both nor
+	 *       none.
+	 */
+	char *dependency_name;
 } unit_dependency_t;
 
+extern unit_dependency_t *dep_dependency_create(void);
+extern void dep_dependency_destroy(unit_dependency_t **);
+
+extern int dep_sprout_dependency(unit_t *, const char *);
+extern void dep_resolve_dependency(unit_dependency_t *, unit_t *);
+
 extern int dep_add_dependency(unit_t *, unit_t *);
+extern void dep_remove_dependency(unit_dependency_t **);
+
 
 #endif
Index: uspace/srv/sysman/job.c
===================================================================
--- uspace/srv/sysman/job.c	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ uspace/srv/sysman/job.c	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -137,5 +137,5 @@
 
 	/* Enqueue jobs */
-	list_foreach_safe(*jobs, cur_link, next_lin) {
+	list_foreach_safe(*jobs, cur_link, next_link) {
 		list_remove(cur_link);
 		list_append(cur_link, &job_queue);
Index: uspace/srv/sysman/main.c
===================================================================
--- uspace/srv/sysman/main.c	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ uspace/srv/sysman/main.c	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -36,8 +36,9 @@
 		goto fail;
 	}
+	mnt_initrd->name                 = str_dup("initrd.mnt");
 	// TODO Use RDFMT
-	mnt_initrd->data.mnt.type       = str_dup("ext4fs");
-	mnt_initrd->data.mnt.mountpoint = str_dup("/");
-	mnt_initrd->data.mnt.device     = str_dup("bd/initrd");
+	CAST_MNT(mnt_initrd)->type       = str_dup("ext4fs");
+	CAST_MNT(mnt_initrd)->mountpoint = str_dup("/");
+	CAST_MNT(mnt_initrd)->device     = str_dup("bd/initrd");
 
 	cfg_init = unit_create(UNIT_CONFIGURATION);
@@ -46,5 +47,6 @@
 		goto fail;
 	}
-	cfg_init->data.cfg.path = str_dup("/cfg/");
+	cfg_init->name           = str_dup("init.cfg");
+	CAST_CFG(cfg_init)->path = str_dup("/cfg/sysman");
 	
 	tgt_default = unit_create(UNIT_TARGET);
@@ -53,4 +55,5 @@
 		goto fail;
 	}
+	tgt_default->name = str_dup("default.tgt");
 	
 
@@ -58,4 +61,6 @@
 	 * Add units to configuration and start the default target.
 	 */
+	configuration_start_update();
+
 	configuration_add_unit(mnt_initrd);
 	configuration_add_unit(cfg_init);
Index: uspace/srv/sysman/sysman.c
===================================================================
--- uspace/srv/sysman/sysman.c	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ uspace/srv/sysman/sysman.c	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -22,7 +22,7 @@
 	job->unit = unit;
 
-	list_foreach(unit->dependencies, dependencies, unit_dependency_t, edge) {
+	list_foreach(unit->dependencies, dependencies, unit_dependency_t, dep) {
 		job_t *blocking_job = NULL;
-		rc = sysman_create_closure_jobs(edge->dependency, &blocking_job,
+		rc = sysman_create_closure_jobs(dep->dependency, &blocking_job,
 		    accumulator, type);
 		if (rc != EOK) {
@@ -55,4 +55,5 @@
 
 	job_t *job = NULL;
+	// TODO shouldn't be here read-lock on configuration?
 	int rc = sysman_create_closure_jobs(unit, &job, &new_jobs, JOB_START);
 	if (rc != EOK) {
Index: uspace/srv/sysman/unit.c
===================================================================
--- uspace/srv/sysman/unit.c	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ uspace/srv/sysman/unit.c	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -2,13 +2,18 @@
 #include <errno.h>
 #include <fibril_synch.h>
+#include <conf/configuration.h>
+#include <conf/ini.h>
 #include <mem.h>
+#include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <str.h>
 
+#include "dep.h"
 #include "log.h"
 #include "unit.h"
 
 /** Virtual method table for each unit type */
-static unit_ops_t *unit_type_vmts[] = {
+unit_vmt_t *unit_type_vmts[] = {
 	[UNIT_TARGET]        = &unit_tgt_ops,
 	[UNIT_MOUNT]         = &unit_mnt_ops,
@@ -16,12 +21,22 @@
 };
 
+static const char *section_name = "Unit";
+
+static config_item_t unit_configuration[] = {
+	{"After", &unit_parse_unit_list, 0, ""},
+	CONFIGURATION_ITEM_SENTINEL
+};
+
+
 static void unit_init(unit_t *unit, unit_type_t type)
 {
 	assert(unit);
 
+	// TODO is this necessary?
 	memset(unit, 0, sizeof(unit_t));
-	link_initialize(&unit->units);
 	
 	unit->type = type;
+	unit->name = NULL;
+
 	unit->state = STATE_EMBRYO;
 	fibril_mutex_initialize(&unit->state_mtx);
@@ -31,10 +46,11 @@
 	list_initialize(&unit->dependencies);
 
-	unit_type_vmts[unit->type]->init(unit);
+	UNIT_VMT(unit)->init(unit);
 }
 
 unit_t *unit_create(unit_type_t type)
 {
-	unit_t *unit = malloc(sizeof(unit_t));
+	size_t size = unit_type_vmts[type]->size;
+	unit_t *unit = malloc(size);
 	if (unit != NULL) {
 		unit_init(unit, type);
@@ -50,5 +66,5 @@
 		return;
 
-	unit_type_vmts[unit->type]->destroy(unit);
+	UNIT_VMT(unit)->destroy(unit);
 	/* TODO:
 	 * 	edges,
@@ -56,4 +72,5 @@
 	 * 	other resources to come
 	 */
+	free(unit->name);
 	free(unit);
 	unit_ptr = NULL;
@@ -75,5 +92,77 @@
 int unit_start(unit_t *unit)
 {
-	sysman_log(LVL_DEBUG, "%s(%p)", __func__, unit);
-	return unit_type_vmts[unit->type]->start(unit);
+	sysman_log(LVL_DEBUG, "%s('%s')", __func__, unit_name(unit));
+	return UNIT_VMT(unit)->start(unit);
 }
+
+int unit_load(unit_t *unit, ini_configuration_t *ini_conf,
+    text_parse_t *text_parse)
+{
+	sysman_log(LVL_DEBUG, "%s('%s')", __func__, unit_name(unit));
+
+	int rc = EOK;
+	ini_section_t *unit_section = ini_get_section(ini_conf, section_name);
+	if (unit_section) {
+		rc = config_load_ini_section(unit_configuration,
+		    unit_section, unit, text_parse);
+	}
+				
+	if (rc != EOK) {
+		return rc;
+	} else {
+		return UNIT_VMT(unit)->load(unit, ini_conf, text_parse);
+	}
+}
+
+unit_type_t unit_type_name_to_type(const char *type_name)
+{
+	if (str_cmp(type_name, "cfg") == 0)
+		return UNIT_CONFIGURATION;
+
+	else if (str_cmp(type_name, "mnt") == 0)
+		return UNIT_MOUNT;
+
+	else if (str_cmp(type_name, "tgt") == 0)
+		return UNIT_TARGET;
+
+	else
+		return UNIT_TYPE_INVALID;
+}
+
+/** Format unit name to be presented to user */
+const char *unit_name(const unit_t *unit)
+{
+	return unit->name ? unit->name : "";
+}
+
+
+
+
+bool unit_parse_unit_list(const char *value, void *dst, text_parse_t *parse,
+    size_t lineno)
+{
+	unit_t *unit = dst;
+	bool result;
+	char *my_value = str_dup(value);
+
+	if (!my_value) {
+		result = false;
+		goto finish;
+	}
+
+	char *to_split = my_value;
+	char *cur_tok;
+
+	while ((cur_tok = str_tok(to_split, " ", &to_split))) {
+		if (dep_sprout_dependency(unit, cur_tok) != EOK) {
+			result = false;
+			goto finish;
+		}
+	}
+
+	result = true;
+
+finish:
+	free(my_value);
+	return result;
+}
Index: uspace/srv/sysman/unit.h
===================================================================
--- uspace/srv/sysman/unit.h	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ uspace/srv/sysman/unit.h	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -1,17 +1,35 @@
+/*
+ * Unit terminology and OOP based on systemd.
+ */
 #ifndef SYSMAN_UNIT_H
 #define SYSMAN_UNIT_H
 
+#include <adt/hash_table.h>
 #include <adt/list.h>
+#include <conf/configuration.h>
+#include <conf/ini.h>
+#include <conf/text_parse.h>
 #include <fibril_synch.h>
 
-#include "unit_mnt.h"
-#include "unit_cfg.h"
-#include "unit_tgt.h"
-#include "unit_types.h"
+typedef enum {
+	UNIT_TYPE_INVALID = -1,
+	UNIT_TARGET = 0,
+	UNIT_MOUNT,
+	UNIT_CONFIGURATION,
+} unit_type_t;
 
-struct unit {
-	link_t units;
+typedef enum {
+	STATE_EMBRYO = 0,
+	STATE_STARTING,
+	STATE_STARTED,
+	STATE_STOPPED,
+	STATE_FAILED
+} unit_state_t;
+
+typedef struct {
+	ht_link_t units;
 
 	unit_type_t type;
+	char *name;
 
 	unit_state_t state;
@@ -21,11 +39,50 @@
 	list_t dependencies;
 	list_t dependants;
+} unit_t;
 
-	union {
-		unit_mnt_t mnt;
-		unit_cfg_t cfg;
-	} data;
+typedef struct unit_vmt unit_vmt_t;
+struct unit_vmt;
+
+#include "unit_cfg.h"
+#include "unit_mnt.h"
+#include "unit_tgt.h"
+
+#define DEFINE_CAST(NAME, TYPE, ENUM_TYPE)                           \
+	static inline TYPE *CAST_##NAME(unit_t *u)                   \
+	{                                                            \
+		if (u->type == ENUM_TYPE)                            \
+			return (TYPE *)u;                            \
+		else                                                 \
+			return NULL;                                 \
+	}                                                            \
+
+DEFINE_CAST(CFG, unit_cfg_t, UNIT_CONFIGURATION)
+DEFINE_CAST(MNT, unit_mnt_t, UNIT_MOUNT)
+DEFINE_CAST(TGT, unit_tgt_t, UNIT_TARGET)
+
+struct unit_vmt {
+	size_t size;
+
+	void (*init)(unit_t *);
+
+	void (*destroy)(unit_t *);
+
+	int (*load)(unit_t *, ini_configuration_t *, text_parse_t *);
+
+	int (*start)(unit_t *);
 };
 
+extern unit_vmt_t *unit_type_vmts[];
+
+#define DEFINE_UNIT_VMT(PREFIX)                                      \
+	unit_vmt_t PREFIX##_ops = {                                  \
+		.size    = sizeof(PREFIX##_t),                       \
+		.init    = &PREFIX##_init,                           \
+		.load    = &PREFIX##_load,                           \
+		.destroy = &PREFIX##_destroy,                        \
+		.start   = &PREFIX##_start                           \
+	};
+
+#define UNIT_VMT(UNIT) unit_type_vmts[(UNIT)->type]
 
 extern unit_t *unit_create(unit_type_t);
@@ -35,5 +92,12 @@
 extern void unit_set_state(unit_t *, unit_state_t);
 
+extern int unit_load(unit_t *, ini_configuration_t *, text_parse_t *);
 extern int unit_start(unit_t *);
 
+extern unit_type_t unit_type_name_to_type(const char *);
+
+extern const char *unit_name(const unit_t *);
+
+extern bool unit_parse_unit_list(const char *, void *, text_parse_t *, size_t);
+
 #endif
Index: pace/srv/sysman/unit_types.h
===================================================================
--- uspace/srv/sysman/unit_types.h	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#ifndef SYSMAN_UNIT_TYPES_H
-#define SYSMAN_UNIT_TYPES_H
-
-struct unit;
-typedef struct unit unit_t;
-
-typedef enum {
-	UNIT_TARGET = 0,
-	UNIT_MOUNT,
-	UNIT_CONFIGURATION
-} unit_type_t;
-
-typedef enum {
-	STATE_EMBRYO = 0,
-	STATE_STARTING,
-	STATE_STARTED,
-	STATE_STOPPED,
-	STATE_FAILED
-} unit_state_t;
-
-typedef struct {
-	void (*init)(unit_t *);
-
-	int (*start)(unit_t *);
-
-	void (*destroy)(unit_t *);
-
-} unit_ops_t;
-
-#define DEFINE_UNIT_OPS(PREFIX)                                      \
-	unit_ops_t PREFIX##_ops = {                                  \
-		.init    = &PREFIX##_init,                           \
-		.start   = &PREFIX##_start,                          \
-		.destroy = &PREFIX##_destroy                         \
-	};
-
-#endif
Index: uspace/srv/sysman/units/unit_cfg.c
===================================================================
--- uspace/srv/sysman/units/unit_cfg.c	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ uspace/srv/sysman/units/unit_cfg.c	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -1,23 +1,225 @@
+#include <adt/list.h>
+#include <assert.h>
+#include <conf/configuration.h>
+#include <conf/ini.h>
+#include <conf/text_parse.h>
+#include <dirent.h>
 #include <errno.h>
-
-#include "unit_cfg.h"
+#include <stdlib.h>
+#include <str.h>
+
+#include "configuration.h"
+#include "log.h"
+#include "unit.h"
+#include "util.h"
+
+static const char *section_name = "Configuration";
+
+static config_item_t unit_configuration[] = {
+	{"Path", &config_parse_string, offsetof(unit_cfg_t, path), NULL},
+	CONFIGURATION_ITEM_SENTINEL
+};
+
+/**
+ * TODO refactor path handling and rename to 'load from file'
+ *
+ * @param[out]  unit_ptr   Unit loaded from the file. Undefined when function fails.
+ */
+static int cfg_parse_file(const char *dirname, const char *filename,
+    unit_t **unit_ptr)
+{
+	int rc = EOK;
+	unit_t *new_unit = NULL;
+	char *fn = NULL;
+	ini_configuration_t ini_conf;
+	text_parse_t text_parse;
+
+	ini_configuration_init(&ini_conf);
+	text_parse_init(&text_parse);
+
+	const char *last_dot = str_rchr(filename, '.');
+	if (last_dot == NULL) {
+		rc = EINVAL;
+		goto finish;
+	}
+
+	const char *unit_name = filename;
+	const char *unit_type_name = last_dot + 1;
+
+	unit_type_t unit_type = unit_type_name_to_type(unit_type_name);
+	if (unit_type == UNIT_TYPE_INVALID) {
+		rc = EINVAL;
+		goto finish;
+	}
+	
+	unit_t *u = configuration_find_unit_by_name(unit_name);
+	if (u != NULL) {
+		// TODO allow updating configuration of existing unit
+		rc = EEXISTS;
+		goto finish;
+	} else {
+		new_unit = u = unit_create(unit_type);
+		new_unit->name = str_dup(unit_name);
+		if (new_unit->name == NULL) {
+			rc = ENOMEM;
+			goto finish;
+		}
+	}
+	if (u == NULL) {
+		rc = ENOMEM;
+		goto finish;
+	}
+	assert(u->type == unit_type);
+
+	fn = compose_path(dirname, filename);
+	if (fn == NULL) {
+		rc = ENOMEM;
+		goto finish;
+	}
+
+	/* Parse INI file to ini_conf structure */
+	rc = ini_parse_file(fn, &ini_conf, &text_parse);
+	switch (rc) {
+	case EOK:
+		/* This is fine */
+		break;
+	case EINVAL:
+		goto dump_parse;
+		break;
+	default:
+		sysman_log(LVL_WARN,
+		    "Cannot parse '%s' (%i).", fn, rc);
+		goto finish;
+	}
+
+	/* Parse ini structure */
+	rc = unit_load(u, &ini_conf, &text_parse);
+	*unit_ptr = u;
+
+	/*
+	 * Here we just continue undisturbed by errors, they'll be returned in
+	 * 'finish' block and potential parse errors (or none) will be logged
+	 * in 'dump_parse' block.
+	 */
+
+dump_parse:
+	list_foreach(text_parse.errors, link, text_parse_error_t, err) {
+		sysman_log(LVL_WARN,
+		    "Error (%i) when parsing '%s' on line %i.",
+		    err->parse_errno, fn, err->lineno);
+	}
+
+finish:
+	free(fn);
+	ini_configuration_deinit(&ini_conf);
+	text_parse_deinit(&text_parse);
+	if (rc != EOK) {
+		unit_destroy(&new_unit);
+	}
+
+	return rc;
+}
+
+static int cfg_load_configuration(const char *path)
+{
+	DIR *dir;
+	struct dirent *de;
+
+	dir = opendir(path);
+	if (dir == NULL) {
+		sysman_log(LVL_ERROR,
+		    "Cannot open configuration directory '%s'", path);
+		return EIO;
+	}
+
+	configuration_start_update();
+
+	while ((de = readdir(dir))) {
+		unit_t *unit = NULL;
+		int rc = cfg_parse_file(path, de->d_name, &unit);
+		if (rc != EOK) {
+			sysman_log(LVL_WARN, "Cannot load unit from file %s/%s",
+			    path, de->d_name);
+			/*
+			 * Ignore error for now, we'll fail only when we're
+			 * unable to resolve dependency names.
+			 */
+			continue;
+		}
+
+		assert(unit->state = STATE_EMBRYO);
+		configuration_add_unit(unit);
+	}
+	closedir(dir);
+
+	int rc = configuration_resolve_dependecies();
+	if (rc != EOK) {
+		configuration_rollback();
+		return rc;
+	}
+
+	configuration_commit();
+	return EOK;
+}
 
 static void unit_cfg_init(unit_t *unit)
 {
-	// TODO
+	unit_cfg_t *u_cfg = CAST_CFG(unit);
+	assert(u_cfg);
+
+	u_cfg->path = NULL;
+}
+
+
+
+static void unit_cfg_destroy(unit_t *unit)
+{
+	unit_cfg_t *u_cfg = CAST_CFG(unit);
+	assert(u_cfg);
+
+	free(u_cfg->path);
+}
+
+static int unit_cfg_load(unit_t *unit, ini_configuration_t *ini_conf,
+    text_parse_t *text_parse)
+{
+	unit_cfg_t *u_cfg = CAST_CFG(unit);
+	assert(u_cfg);
+
+	ini_section_t *section = ini_get_section(ini_conf, section_name);
+	if (section == NULL) {
+		sysman_log(LVL_ERROR,
+		    "Expected section '%s' in configuration of unit '%s'",
+		    section_name, unit_name(unit));
+		return ENOENT;
+	}
+
+	return config_load_ini_section(unit_configuration, section, u_cfg,
+	    text_parse);
 }
 
 static int unit_cfg_start(unit_t *unit)
 {
-	//TODO
-	return EOK;
-}
-
-static void unit_cfg_destroy(unit_t *unit)
-{
-	//TODO
-}
-
-
-DEFINE_UNIT_OPS(unit_cfg)
-
+	unit_cfg_t *u_cfg = CAST_CFG(unit);
+	assert(u_cfg);
+
+	/*
+	 * Skip starting state and hold state lock during whole configuration
+	 * load.
+	 */
+	fibril_mutex_lock(&unit->state_mtx);
+	int rc = cfg_load_configuration(u_cfg->path);
+	
+	if (rc == EOK) {
+		unit->state = STATE_STARTED;
+	} else {
+		unit->state = STATE_FAILED;
+	}
+	fibril_condvar_broadcast(&unit->state_cv);
+	fibril_mutex_unlock(&unit->state_mtx);
+
+	return rc;
+}
+
+DEFINE_UNIT_VMT(unit_cfg)
+
Index: uspace/srv/sysman/units/unit_cfg.h
===================================================================
--- uspace/srv/sysman/units/unit_cfg.h	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ uspace/srv/sysman/units/unit_cfg.h	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -2,11 +2,13 @@
 #define SYSMAN_UNIT_CFG_H
 
-#include "unit_types.h"
+#include "unit.h"
 
 typedef struct {
-	const char *path;
+	unit_t unit;
+
+	char *path;
 } unit_cfg_t;
 
-extern unit_ops_t unit_cfg_ops;
+extern unit_vmt_t unit_cfg_ops;
 
 #endif
Index: uspace/srv/sysman/units/unit_mnt.c
===================================================================
--- uspace/srv/sysman/units/unit_mnt.c	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ uspace/srv/sysman/units/unit_mnt.c	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -7,15 +7,59 @@
 #include "log.h"
 #include "unit.h"
-#include "unit_mnt.h"
+
+static const char *section_name = "Mount";
+
+static config_item_t unit_configuration[] = {
+	{"What",  &config_parse_string, offsetof(unit_mnt_t, device),     NULL},
+	{"Where", &config_parse_string, offsetof(unit_mnt_t, mountpoint), NULL},
+	{"Type",  &config_parse_string, offsetof(unit_mnt_t, type),       NULL},
+	CONFIGURATION_ITEM_SENTINEL
+};
 
 static void unit_mnt_init(unit_t *unit)
 {
-	assert(unit->data.mnt.type == NULL);
-	assert(unit->data.mnt.mountpoint == NULL);
-	assert(unit->data.mnt.device == NULL);
+	unit_mnt_t *u_mnt = CAST_MNT(unit);
+	assert(u_mnt);
+
+	u_mnt->type = NULL;
+	u_mnt->mountpoint = NULL;
+	u_mnt->device = NULL;
+}
+
+static void unit_mnt_destroy(unit_t *unit)
+{
+	assert(unit->type == UNIT_MOUNT);
+	unit_mnt_t *u_mnt = CAST_MNT(unit);
+
+	sysman_log(LVL_DEBUG2, "%s, %p, %p, %p", __func__,
+	    u_mnt->type, u_mnt->mountpoint, u_mnt->device);
+	free(u_mnt->type);
+	free(u_mnt->mountpoint);
+	free(u_mnt->device);
+}
+
+static int unit_mnt_load(unit_t *unit, ini_configuration_t *ini_conf,
+    text_parse_t *text_parse)
+{
+	unit_mnt_t *u_mnt = CAST_MNT(unit);
+	assert(u_mnt);
+
+	ini_section_t *section = ini_get_section(ini_conf, section_name);
+	if (section == NULL) {
+		sysman_log(LVL_ERROR,
+		    "Expected section '%s' in configuration of unit '%s'",
+		    section_name, unit_name(unit));
+		return ENOENT;
+	}
+
+	return config_load_ini_section(unit_configuration, section, u_mnt,
+	    text_parse);
 }
 
 static int unit_mnt_start(unit_t *unit)
 {
+	unit_mnt_t *u_mnt = CAST_MNT(unit);
+	assert(u_mnt);
+
 	fibril_mutex_lock(&unit->state_mtx);
 	
@@ -28,15 +72,14 @@
 
 
-	unit_mnt_t *data = &unit->data.mnt;
-
 	// TODO use other mount parameters
-	int rc = mount(data->type, data->mountpoint, data->device, "",
+	int rc = mount(u_mnt->type, u_mnt->mountpoint, u_mnt->device, "",
 	    IPC_FLAG_BLOCKING, 0);
 
 	if (rc == EOK) {
-		sysman_log(LVL_NOTE, "Mount (%p) mounted", unit);
+		sysman_log(LVL_NOTE, "Mount ('%s') mounted", unit_name(unit));
 		unit_set_state(unit, STATE_STARTED);
 	} else {
-		sysman_log(LVL_ERROR, "Mount (%p) failed (%i)", unit, rc);
+		sysman_log(LVL_ERROR, "Mount ('%s') failed (%i)",
+		    unit_name(unit), rc);
 		unit_set_state(unit, STATE_FAILED);
 	}
@@ -45,12 +88,4 @@
 }
 
-static void unit_mnt_destroy(unit_t *unit)
-{
-	free(unit->data.mnt.type);
-	free(unit->data.mnt.mountpoint);
-	free(unit->data.mnt.device);
-}
+DEFINE_UNIT_VMT(unit_mnt)
 
-
-DEFINE_UNIT_OPS(unit_mnt)
-
Index: uspace/srv/sysman/units/unit_mnt.h
===================================================================
--- uspace/srv/sysman/units/unit_mnt.h	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ uspace/srv/sysman/units/unit_mnt.h	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -2,14 +2,15 @@
 #define SYSMAN_UNIT_MNT_H
 
-#include "unit_types.h"
+#include "unit.h"
 
 typedef struct {
-	const char *type;
-	const char *mountpoint;
-	const char *device;
+	unit_t unit;
+
+	char *type;
+	char *mountpoint;
+	char *device;
 } unit_mnt_t;
 
-extern unit_ops_t unit_mnt_ops;
-
+extern unit_vmt_t unit_mnt_ops;
 
 #endif
Index: uspace/srv/sysman/units/unit_tgt.c
===================================================================
--- uspace/srv/sysman/units/unit_tgt.c	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ uspace/srv/sysman/units/unit_tgt.c	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -1,23 +1,37 @@
 #include <errno.h>
 
-#include "unit_tgt.h"
+#include "unit.h"
 
 static void unit_tgt_init(unit_t *unit)
 {
-	// TODO
+	unit_tgt_t *u_tgt = CAST_TGT(unit);
+	assert(u_tgt);
+	/* Nothing more to do */
+}
+
+static void unit_tgt_destroy(unit_t *unit)
+{
+	unit_tgt_t *u_tgt = CAST_TGT(unit);
+	assert(u_tgt);
+	/* Nothing more to do */
+}
+
+static int unit_tgt_load(unit_t *unit, ini_configuration_t *ini_conf,
+    text_parse_t *text_parse)
+{
+	unit_tgt_t *u_tgt = CAST_TGT(unit);
+	assert(u_tgt);
+
+	return EOK;
 }
 
 static int unit_tgt_start(unit_t *unit)
 {
-	//TODO
+	unit_tgt_t *u_tgt = CAST_TGT(unit);
+	assert(u_tgt);
+
 	return EOK;
 }
 
-static void unit_tgt_destroy(unit_t *unit)
-{
-	//TODO
-}
+DEFINE_UNIT_VMT(unit_tgt)
 
-
-DEFINE_UNIT_OPS(unit_tgt)
-
Index: uspace/srv/sysman/units/unit_tgt.h
===================================================================
--- uspace/srv/sysman/units/unit_tgt.h	(revision 6006f3541de68a50b69585c7cdc86b6cec4269d9)
+++ uspace/srv/sysman/units/unit_tgt.h	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -2,7 +2,11 @@
 #define SYSMAN_UNIT_TGT_H
 
-#include "unit_types.h"
+#include "unit.h"
 
-extern unit_ops_t unit_tgt_ops;
+typedef struct {
+	unit_t unit;
+} unit_tgt_t;
+
+extern unit_vmt_t unit_tgt_ops;
 
 #endif
Index: uspace/srv/sysman/util.c
===================================================================
--- uspace/srv/sysman/util.c	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
+++ uspace/srv/sysman/util.c	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -0,0 +1,24 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <str.h>
+
+#include "util.h"
+
+/** Compose path to file inside a directory.
+ *
+ * @return	pointer to newly allocated string
+ * @return	NULL on error
+ */
+char *compose_path(const char *dirname, const char *filename)
+{
+	size_t size = str_size(dirname) + str_size(filename) + 2;
+	char *result = malloc(sizeof(char) * size);
+
+	if (result == NULL) {
+		return NULL;
+	}
+	if (snprintf(result, size, "%s/%s", dirname, filename) < 0) {
+		return NULL;
+	}
+	return result;
+}
Index: uspace/srv/sysman/util.h
===================================================================
--- uspace/srv/sysman/util.h	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
+++ uspace/srv/sysman/util.h	(revision bb154c64b6e4b7d6a2a8e19760b6ae60156847b4)
@@ -0,0 +1,6 @@
+#ifndef SYSMAN_UTIL_H
+#define SYSMAN_UTIL_H
+
+extern char *compose_path(const char *, const char *);
+
+#endif
