Index: uspace/srv/sysman/main.c
===================================================================
--- uspace/srv/sysman/main.c	(revision 8432ae18aee1d16cccf1bad6ce573bf6ae9504ba)
+++ uspace/srv/sysman/main.c	(revision c0e4fc5039e0ff4e03ec378811f135077cecb5ef)
@@ -30,4 +30,7 @@
 #include <errno.h>
 #include <fibril.h>
+#include <ipc/sysman.h>
+#include <macros.h>
+#include <ns.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -35,4 +38,6 @@
 
 #include "configuration.h"
+#include "connection_broker.h"
+#include "connection_ctl.h"
 #include "dep.h"
 #include "job.h"
@@ -43,41 +48,80 @@
 #define NAME "sysman"
 
-static void sysman_connection(ipc_callid_t callid, ipc_call_t *call, void *arg)
-{
-	/* TODO handle client connections */
+#define INITRD_DEVICE       "bd/initrd"
+#define INITRD_MOUNT_POINT  "/"
+#define INITRD_CFG_PATH     "/cfg/sysman"
+
+#define TARGET_INIT     "initrd.tgt"
+#define TARGET_ROOTFS   "rootfs.tgt"
+#define TARGET_DEFAULT  "default.tgt"
+
+#define UNIT_MNT_INITRD "initrd.mnt"
+#define UNIT_CFG_INITRD "init.cfg"
+
+static const char *target_sequence[] = {
+	TARGET_INIT,
+	TARGET_ROOTFS,
+	TARGET_DEFAULT,
+	NULL
+};
+
+/*
+ * Forward declarations
+ */
+static void prepare_and_run_job(const char **target_name_ptr);
+
+/*
+ * Static functions
+ */
+
+static void sysman_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	sysman_interface_t iface = IPC_GET_ARG1(*icall);
+	switch (iface) {
+	case SYSMAN_PORT_BROKER:
+		sysman_connection_broker(iid, icall);
+		break;
+	case SYSMAN_PORT_CTL:
+		sysman_connection_ctl(iid, icall);
+		break;
+	default:
+		/* Unknown interface */
+		async_answer_0(iid, ENOENT);
+	}
 }
 
 /** Build hard coded configuration */
-static job_t *create_entry_configuration(void) {
-	int result = EOK;
+static int create_entry_configuration(void) {
+	int rc;
 	unit_t *mnt_initrd = NULL;
 	unit_t *cfg_init = NULL;
-	unit_t *tgt_default = NULL;
+	unit_t *tgt_init = NULL;
 
 	mnt_initrd = unit_create(UNIT_MOUNT);
 	if (mnt_initrd == NULL) {
-		result = ENOMEM;
+		rc = ENOMEM;
 		goto fail;
 	}
-	mnt_initrd->name                 = str_dup("initrd.mnt");
-	// TODO Use RDFMT
-	CAST_MNT(mnt_initrd)->type       = str_dup("ext4fs");
-	CAST_MNT(mnt_initrd)->mountpoint = str_dup("/");
-	CAST_MNT(mnt_initrd)->device     = str_dup("bd/initrd");
+	mnt_initrd->name                 = str_dup(UNIT_MNT_INITRD);
+	CAST_MNT(mnt_initrd)->type       = str_dup(STRING(RDFMT));
+	CAST_MNT(mnt_initrd)->mountpoint = str_dup(INITRD_MOUNT_POINT);
+	CAST_MNT(mnt_initrd)->device     = str_dup(INITRD_DEVICE);
+	CAST_MNT(mnt_initrd)->autostart  = false;
+	CAST_MNT(mnt_initrd)->blocking   = true;
 
 	cfg_init = unit_create(UNIT_CONFIGURATION);
 	if (cfg_init == NULL) {
-		result = ENOMEM;
+		rc = ENOMEM;
 		goto fail;
 	}
-	cfg_init->name           = str_dup("init.cfg");
-	CAST_CFG(cfg_init)->path = str_dup("/cfg/sysman");
+	cfg_init->name           = str_dup(UNIT_CFG_INITRD);
+	CAST_CFG(cfg_init)->path = str_dup(INITRD_CFG_PATH);
 	
-	tgt_default = unit_create(UNIT_TARGET);
-	if (tgt_default == NULL) {
-		result = ENOMEM;
+	tgt_init = unit_create(UNIT_TARGET);
+	if (tgt_init == NULL) {
+		rc = ENOMEM;
 		goto fail;
 	}
-	tgt_default->name = str_dup("default.tgt");
+	tgt_init->name = str_dup(TARGET_INIT);
 	
 
@@ -89,37 +133,69 @@
 	configuration_add_unit(mnt_initrd);
 	configuration_add_unit(cfg_init);
-	configuration_add_unit(tgt_default);
-
-	result = dep_add_dependency(tgt_default, cfg_init);
-	if (result != EOK) {
-		goto fail;
-	}
-
-	result = dep_add_dependency(cfg_init, mnt_initrd);
-	if (result != EOK) {
-		goto fail;
+	configuration_add_unit(tgt_init);
+
+	rc = dep_add_dependency(tgt_init, cfg_init);
+	if (rc != EOK) {
+		goto rollback;
+	}
+
+	rc = dep_add_dependency(cfg_init, mnt_initrd);
+	if (rc != EOK) {
+		goto rollback;
 	}
 
 	configuration_commit();
 
-	job_t *first_job = job_create(tgt_default, STATE_STARTED);
-	if (first_job == NULL) {
-		goto fail;
-	}
-	return first_job;
+	return EOK;
 
 fail:
-	// TODO cannot destroy units after they're added to configuration
-	unit_destroy(&tgt_default);
+	unit_destroy(&tgt_init);
 	unit_destroy(&cfg_init);
 	unit_destroy(&mnt_initrd);
-	return NULL;
-}
-
-static void first_job_handler(void *object, void *unused)
+	return rc;
+
+rollback:
+	configuration_rollback();
+	return rc;
+}
+
+static void sequence_job_handler(void *object, void *arg)
 {
 	job_t *job = object;
-	sysman_log(LVL_DEBUG, "First job retval: %i.", job->retval);
+	if (job->retval == JOB_FAILED) {
+		sysman_log(LVL_ERROR, "Failed to start '%s'.", unit_name(job->unit));
+		job_del_ref(&job);
+		return;
+	}
 	job_del_ref(&job);
+	
+	const char **target_name_ptr = arg;
+	prepare_and_run_job(target_name_ptr + 1);
+}
+
+static void prepare_and_run_job(const char **target_name_ptr)
+{
+	const char *target_name = *target_name_ptr;
+
+	if (target_name == NULL) {
+		sysman_log(LVL_NOTE, "All initial units started.");
+		return;
+	}
+
+	/* Previous targets should have loaded new units */
+	unit_t *tgt = configuration_find_unit_by_name(target_name);
+	if (tgt == NULL) {
+		sysman_log(LVL_ERROR,
+		    "Expected unit '%s' not found in configuration.",
+		    target_name);
+		return;
+	}
+
+	int rc = sysman_queue_job(tgt, STATE_STARTED, &sequence_job_handler,
+	    target_name_ptr);
+
+	if (rc != EOK) {
+		sysman_log(LVL_FATAL, "Cannot create job for '%s'.", target_name);
+	}
 }
 
@@ -136,8 +212,12 @@
 
 	/*
-	 * Create initial configuration while we are in a single fibril, keep
-	 * the job and run it when event loop is running.
-	 */
-	job_t *first_job = create_entry_configuration();
+	 * Create initial configuration while we are in a single fibril
+	 */
+	int rc = create_entry_configuration();
+	if (rc != EOK) {
+		sysman_log(LVL_FATAL,
+		    "Could not create initial configuration (%i).", rc);
+		return rc;
+	}
 
 	/*
@@ -148,15 +228,14 @@
 	fibril_add_ready(event_loop_fibril);
 
-	/* Queue first job for processing */
-	job_add_ref(first_job);
-	sysman_object_observer(first_job, &first_job_handler, NULL);
-	job_add_ref(first_job);
-	sysman_raise_event(&sysman_event_job_process, first_job);
-	
-	/*
-	 * Releasing our own reference (could be merged with previous add_ref,
-	 * this is more explicit though.
-	 */
-	job_del_ref(&first_job);
+	/* Queue first job from sequence */
+	prepare_and_run_job(&target_sequence[0]);
+
+	/* We're service too */
+	rc = service_register(SERVICE_SYSMAN);
+	if (rc != EOK) {
+		sysman_log(LVL_FATAL,
+		    "Cannot register at naming service (%i).", rc);
+		return rc;
+	}
 
 	/* Start sysman server */
