diff --git a/distrib/utils/sysinst/Makefile.inc b/distrib/utils/sysinst/Makefile.inc
index ec9252e..6353721 100644
--- a/distrib/utils/sysinst/Makefile.inc
+++ b/distrib/utils/sysinst/Makefile.inc
@@ -45,7 +45,7 @@ CPPFLAGS+=	-I. -I${.CURDIR}/../.. -I${.CURDIR} \
 		-DMACH_${MACHINE} -DARCH_${MACHINE_ARCH}
 
 .if (defined(DEBUG))
-CPPFLAGS+=-DDEBUG
+CPPFLAGS+=-DDEBUG -g -O0
 .endif
 
 .if (!defined(SMALLPROG) || defined(SMALLPROG_INET6)) && (${USE_INET6} != "no")
diff --git a/distrib/utils/sysinst/arch/sgimips/md.c b/distrib/utils/sysinst/arch/sgimips/md.c
index bece141..9b47c69 100644
--- a/distrib/utils/sysinst/arch/sgimips/md.c
+++ b/distrib/utils/sysinst/arch/sgimips/md.c
@@ -157,7 +157,7 @@ int
 md_post_disklabel(void)
 {
 	set_swap(diskdev, bsdlabel);
-        if (strstr(instsys.version, "(INSTALL32_IP3x)"))
+    if (strstr(instsys.version, "(INSTALL32_IP3x)"))
 		return run_program(RUN_DISPLAY,
 		    "%s %s", "/usr/mdec/sgivol -f -w boot /usr/mdec/ip3xboot",
 		    diskdev);
diff --git a/distrib/utils/sysinst/bsddisklabel.c b/distrib/utils/sysinst/bsddisklabel.c
index 6916792..6d15932 100644
--- a/distrib/utils/sysinst/bsddisklabel.c
+++ b/distrib/utils/sysinst/bsddisklabel.c
@@ -337,6 +337,7 @@ set_ptn_size(menudesc *m, void *arg)
 	return 0;
 }
 
+/* Menu to change sizes of /, /usr, /home and etc. partitions */
 void
 get_ptn_sizes(daddr_t part_start, daddr_t sectors, int no_swap)
 {
@@ -346,7 +347,7 @@ get_ptn_sizes(daddr_t part_start, daddr_t sectors, int no_swap)
 	struct ptn_size *p;
 	daddr_t size;
 
-	static struct ptn_info pi = { -1, {
+	struct ptn_info pi = { -1, {
 #define PI_ROOT 0
 		{ PART_ROOT,	{ '/', '\0' },
 		  DEFROOTSIZE,	DEFROOTSIZE , 0, 0},
@@ -472,7 +473,6 @@ get_ptn_sizes(daddr_t part_start, daddr_t sectors, int no_swap)
 
 		pi.menu_no = new_menu(0, pi.ptn_menus, nelem(pi.ptn_menus),
 			3, -1, 12, 70,
-			MC_NOSHORTCUT |
 			MC_ALWAYS_SCROLL | MC_NOBOX | MC_NOCLEAR,
 			NULL, set_ptn_titles, NULL,
 			"help", pi.exit_msg);
@@ -706,7 +706,7 @@ make_bsd_partitions(void)
 		msg_display(MSG_abort);
 		return 0;
 	}
-	if (check_partitions() == 0)
+	if (partman_go == 0 && check_partitions() == 0)
 		goto edit_check;
 
 	/* Disk name */
diff --git a/distrib/utils/sysinst/configmenu.c b/distrib/utils/sysinst/configmenu.c
index d8eedde..5593d02 100644
--- a/distrib/utils/sysinst/configmenu.c
+++ b/distrib/utils/sysinst/configmenu.c
@@ -94,7 +94,7 @@ configinfo config_list[] = {
 	{MSG_enable_mdnsd, CONFIGOPT_MDNSD, "mdnsd", toggle_rcvar, NULL},
 	{"Enable XDM", CONFIGOPT_XDM, "xdm", toggle_rcvar, NULL},
 	{NULL,		CONFIGOPT_LAST,	NULL, NULL, NULL}
-}; //TODO XDM
+}; // TODO: XDM
 
 static void
 config_list_init(void)
@@ -413,6 +413,7 @@ do_configmenu()
 
 	/* if the target isn't mounted already, figure it out. */
 	if (target_mounted() == 0) {
+		partman_go = 1;
 		if (find_disks(msg_string(MSG_configure_prior)) < 0)
 			return;
 
diff --git a/distrib/utils/sysinst/defs.h b/distrib/utils/sysinst/defs.h
index 14630fb..6824a10 100644
--- a/distrib/utils/sysinst/defs.h
+++ b/distrib/utils/sysinst/defs.h
@@ -51,6 +51,7 @@ deconst(const void *p)
 
 #include "msg_defs.h"
 #include "menu_defs.h"
+#include "mbr.h"
 
 #define min(a,b)	((a) < (b) ? (a) : (b))
 #define max(a,b)	((a) > (b) ? (a) : (b))
@@ -208,6 +209,8 @@ typedef struct _partinfo {
 #define PIF_LOG		0x0800		/* mount -o log */
 #define PIF_MOUNT_OPTS	0x0ff0		/* all above mount flags */
 #define PIF_RESET	0x1000		/* internal - restore previous values */
+    const char *mnt_opts;
+    const char *fsname;
 } partinfo;	/* Single partition from a disklabel */
 
 struct ptn_info {
@@ -241,14 +244,16 @@ pid_t ttysig_forward;
 int layoutkind;
 int sizemult;
 const char *multname;
+int partman_go;   /* run partition manager */
 
-/* loging variables */
+/* logging variables */
 
 FILE *logfp;
 FILE *script;
 
 /* Actual name of the disk. */
 char diskdev[SSTRSIZE];
+char diskdev_descr[STRSIZE];
 int no_mbr;				/* set for raid (etc) */
 int rootpart;				/* partition we install into */
 const char *disktype;		/* ST506, SCSI, ... */
@@ -277,6 +282,35 @@ daddr_t tmp_ramdisk_size;
 char bsddiskname[DISKNAME_SIZE];
 const char *doessf;
 
+/* Information for extended partition manager */
+typedef struct pm_devs_t {
+    char id[SSTRSIZE];
+    char desc[STRSIZE];
+    char id_dk[SSTRSIZE];
+    int bootable;
+    char bsddiskname[DISKNAME_SIZE];
+    partinfo oldlabel[MAXPARTITIONS];
+    partinfo bsdlabel[MAXPARTITIONS];
+    mbr_info_t mbr;
+    int no_mbr;
+    int use_gpt;
+    int sectorsize, dlcyl, dlhead, dlsec, dlcylsize, current_cylsize;
+    daddr_t dlsize;
+    daddr_t ptstart, ptsize;
+    int bootstart, bootsize;
+    struct pm_devs_t *next;
+} pm_devs_t;
+pm_devs_t *pm_devs; /* Pointer to head of list with all devices */
+pm_devs_t *pm_found; /* Pointer to selected in find_disks device
+                        (when extended partition manager isn't used) */
+pm_devs_t *pm; /* Pointer to currend device with which we work */
+#define AAAAA 100
+
+struct {
+    const char *diskdev, *mnt_opts, *fsname;
+    char *pi_mount;
+} mnts[AAAAA];
+
 /* Relative file name for storing a distribution. */
 char xfer_dir[STRSIZE];
 int  clean_xfer_dir;
@@ -390,7 +424,15 @@ int	mount_disks(void);
 int	set_swap(const char *, partinfo *);
 int	check_swap(const char *, int);
 char	*bootxx_name(void);
-int	partitioning(void);
+int	partman(void);
+int partman_adddisk(menudesc *, void *);
+int partman_addvnd(menudesc *, void *);
+int partman_deldev(menudesc *, void *);
+int partman_commit(menudesc *, void *);
+int partman_mountall(void);
+void partman_menufmt(menudesc *, int, void *);
+void partman_restoredev(pm_devs_t *);
+void partman_savedev(pm_devs_t *);
 
 /* from disks_lfs.c */
 int	fs_is_lfs(void *);
diff --git a/distrib/utils/sysinst/disks.c b/distrib/utils/sysinst/disks.c
index f7c41e9..0a015ba 100644
--- a/distrib/utils/sysinst/disks.c
+++ b/distrib/utils/sysinst/disks.c
@@ -360,7 +360,7 @@ int
 find_disks(const char *doingwhat)
 {
 	struct disk_desc disks[MAX_DISKS];
-	menu_ent dsk_menu[nelem(disks)];
+	menu_ent dsk_menu[nelem(disks) + !partman_go];
 	struct disk_desc *disk;
 	int i;
 	int numdisks;
@@ -390,8 +390,15 @@ find_disks(const char *doingwhat)
 			dsk_menu[i].opt_flags = OPT_EXIT;
 			dsk_menu[i].opt_action = set_dsk_select;
 		}
+		if (partman_go == 0) {
+			dsk_menu[i].opt_name = "Extended partitioning"; // TODO: localize
+			dsk_menu[i].opt_menu = OPT_NOMENU;
+			dsk_menu[i].opt_flags = OPT_EXIT;
+			dsk_menu[i].opt_action = set_dsk_select;
+		}
+
 		menu_no = new_menu(MSG_Available_disks,
-			dsk_menu, numdisks, -1, 4, 0, 0,
+			dsk_menu, numdisks + !partman_go, -1, 4, 0, 0,
 			MC_SCROLL,
 			NULL, NULL, NULL, NULL, NULL);
 		if (menu_no == -1)
@@ -403,12 +410,18 @@ find_disks(const char *doingwhat)
 
 	if (selected_disk == -1)
 	    return -1;
+	if (selected_disk == numdisks) {
+		partman_go = 1;
+	    return -2;
+	}
 
 	disk = disks + selected_disk;
+	pm = pm_found;
 	strlcpy(diskdev, disk->dd_name, sizeof diskdev);
+	strlcpy(diskdev_descr, disk->dd_descr, sizeof diskdev_descr);
 
 	/* Use as a default disk if the user has the sets on a local disk */
-	strlcpy(localfs_dev, disk->dd_name, sizeof localfs_dev);
+	strlcpy(localfs_dev, disk->dd_name, sizeof localfs_dev); // TODO: sss
 
 	sectorsize = disk->dd_secsize;
 	dlcyl = disk->dd_cyl;
@@ -522,8 +535,6 @@ make_filesystems(void)
 	int error = 0;
 	unsigned int maxpart = getmaxpartitions();
 	char *newfs;
-	const char *mnt_opts;
-	const char *fsname;
 	partinfo *lbl;
 
 	if (maxpart > nelem(bsdlabel))
@@ -553,14 +564,14 @@ make_filesystems(void)
 			continue;
 
 		newfs = NULL;
-		mnt_opts = NULL;
-		fsname = NULL;
+		lbl->mnt_opts = NULL;
+		lbl->fsname = NULL;
 		switch (lbl->pi_fstype) {
 		case FS_APPLEUFS:
 			asprintf(&newfs, "/sbin/newfs %s%.0d",
 				lbl->pi_isize != 0 ? "-i" : "", lbl->pi_isize);
-			mnt_opts = "-tffs -o async";
-			fsname = "ffs";
+			lbl->mnt_opts = "-tffs -o async";
+			lbl->fsname = "ffs";
 			break;
 		case FS_BSDFFS:
 			asprintf(&newfs,
@@ -569,36 +580,36 @@ make_filesystems(void)
 			    lbl->pi_fsize * lbl->pi_frag, lbl->pi_fsize,
 			    lbl->pi_isize != 0 ? " -i " : "", lbl->pi_isize);
 			if (lbl->pi_flags & PIF_LOG)
-				mnt_opts = "-tffs -o log";
+				lbl->mnt_opts = "-tffs -o log";
 			else
-				mnt_opts = "-tffs -o async";
-			fsname = "ffs";
+				lbl->mnt_opts = "-tffs -o async";
+			lbl->fsname = "ffs";
 			break;
 		case FS_BSDLFS:
 			asprintf(&newfs, "/sbin/newfs_lfs -b %d",
 				lbl->pi_fsize * lbl->pi_frag);
-			mnt_opts = "-tlfs";
-			fsname = "lfs";
+			lbl->mnt_opts = "-tlfs";
+			lbl->fsname = "lfs";
 			break;
 		case FS_MSDOS:
 #ifdef USE_NEWFS_MSDOS
 			asprintf(&newfs, "/sbin/newfs_msdos");
 #endif
-			mnt_opts = "-tmsdos";
-			fsname = "msdos";
+			lbl->mnt_opts = "-tmsdos";
+			lbl->fsname = "msdos";
 			break;
 #ifdef USE_SYSVBFS
 		case FS_SYSVBFS:
 			asprintf(&newfs, "/sbin/newfs_sysvbfs");
-			mnt_opts = "-tsysvbfs";
-			fsname = "sysvbfs";
+			lbl->mnt_opts = "-tsysvbfs";
+			lbl->fsname = "sysvbfs";
 			break;
 #endif
 #ifdef USE_EXT2FS
 		case FS_EX2FS:
 			asprintf(&newfs, "/sbin/newfs_ext2fs");
-			mnt_opts = "-text2fs";
-			fsname = "ext2fs";
+			lbl->mnt_opts = "-text2fs";
+			lbl->fsname = "ext2fs";
 			break;
 #endif
 		}
@@ -624,7 +635,7 @@ make_filesystems(void)
 			    "%s /dev/r%s%c", newfs, diskdev, 'a' + ptn);
 		} else {
 			/* We'd better check it isn't dirty */
-			error = fsck_preen(diskdev, ptn, fsname);
+			error = fsck_preen(diskdev, ptn, lbl->fsname);
 		}
 		free(newfs);
 		if (error != 0)
@@ -632,9 +643,10 @@ make_filesystems(void)
 
 		md_pre_mount();
 
-		if (lbl->pi_flags & PIF_MOUNT && mnt_opts != NULL) {
+		if (partman_go == 0 && lbl->pi_flags & PIF_MOUNT &&
+				lbl->mnt_opts != NULL) {
 			make_target_dir(lbl->pi_mount);
-			error = target_mount(mnt_opts, diskdev, ptn,
+			error = target_mount(lbl->mnt_opts, diskdev, ptn,
 					    lbl->pi_mount);
 			if (error) {
 				msg_display(MSG_mountfail,
@@ -653,29 +665,35 @@ make_fstab(void)
 	FILE *f;
 	int i, swap_dev = -1;
 	const char *dump_dev;
+	static int fstab_prepared = 0;
 
 	/* Create the fstab. */
-	make_target_dir("/etc");
-	f = target_fopen("/etc/fstab", "w");
+	if (fstab_prepared == 0) {
+		make_target_dir("/etc");
+		f = target_fopen("/etc/fstab", "w");
+		scripting_fprintf(NULL, "cat <<EOF >%s/etc/fstab\n", target_prefix());
+	} else {
+		f = target_fopen("/etc/fstab", "a");
+		scripting_fprintf(NULL, "cat <<EOF >>%s/etc/fstab\n", target_prefix());
+	}
 	if (logfp)
 		(void)fprintf(logfp,
-		    "Creating %s/etc/fstab.\n", target_prefix());
-	scripting_fprintf(NULL, "cat <<EOF >%s/etc/fstab\n", target_prefix());
-
+		    "Making %s/etc/fstab (%s).\n", target_prefix(), diskdev);
+	
 	if (f == NULL) {
-#ifndef DEBUG
 		msg_display(MSG_createfstab);
 		if (logfp)
 			(void)fprintf(logfp, "Failed to make /etc/fstab!\n");
 		process_menu(MENU_ok, NULL);
+#ifndef DEBUG
 		return 1;
 #else
 		f = stdout;
 #endif
 	}
-
-	scripting_fprintf(f, "# NetBSD %s/etc/fstab\n# See /usr/share/examples/"
-		"fstab/ for more examples.\n", target_prefix());
+	if (!fstab_prepared)
+		scripting_fprintf(f, "# NetBSD %s/etc/fstab\n# See /usr/share/examples/"
+			"fstab/ for more examples.\n", target_prefix());
 	for (i = 0; i < getmaxpartitions(); i++) {
 		const char *s = "";
 		const char *mp = bsdlabel[i].pi_mount;
@@ -748,36 +766,37 @@ make_fstab(void)
 		   bsdlabel[i].pi_flags & PIF_NOSUID ? ",nosuid" : "",
 		   dump_freq, fsck_pass);
 	}
-
-	if (tmp_ramdisk_size != 0) {
+	if (!fstab_prepared) {
+		if (tmp_ramdisk_size != 0) {
 #ifdef HAVE_TMPFS
-		scripting_fprintf(f, "tmpfs\t\t/tmp\ttmpfs\trw,-m=1777,-s=%"
-		    PRIi64 "\n",
-		    tmp_ramdisk_size * 512);
-#else
-		if (swap_dev != -1)
-			scripting_fprintf(f, "/dev/%s%c\t\t/tmp\tmfs\trw,-s=%"
+			scripting_fprintf(f, "tmpfs\t\t/tmp\ttmpfs\trw,-m=1777,-s=%"
 			    PRIi64 "\n",
-			    diskdev, 'a' + swap_dev, tmp_ramdisk_size);
-		else
-			scripting_fprintf(f, "swap\t\t/tmp\tmfs\trw,-s=%"
-			    PRIi64 "\n",
-			    tmp_ramdisk_size);
+			    tmp_ramdisk_size * 512);
+#else
+			if (swap_dev != -1)
+				scripting_fprintf(f, "/dev/%s%c\t\t/tmp\tmfs\trw,-s=%"
+				    PRIi64 "\n",
+				    diskdev, 'a' + swap_dev, tmp_ramdisk_size);
+			else
+				scripting_fprintf(f, "swap\t\t/tmp\tmfs\trw,-s=%"
+				    PRIi64 "\n",
+				    tmp_ramdisk_size);
 #endif
-	}
-
-	/* Add /kern, /proc and /dev/pts to fstab and make mountpoint. */
-	scripting_fprintf(f, "kernfs\t\t/kern\tkernfs\trw\n");
-	scripting_fprintf(f, "ptyfs\t\t/dev/pts\tptyfs\trw\n");
-	scripting_fprintf(f, "procfs\t\t/proc\tprocfs\trw\n");
-	scripting_fprintf(f, "/dev/" CD_NAME "\t\t/cdrom\tcd9660\tro,noauto\n");
-	make_target_dir("/kern");
-	make_target_dir("/proc");
-	make_target_dir("/dev/pts");
-	make_target_dir("/cdrom");
+		}
 
+		/* Add /kern, /proc and /dev/pts to fstab and make mountpoint. */
+		scripting_fprintf(f, "kernfs\t\t/kern\tkernfs\trw\n");
+		scripting_fprintf(f, "ptyfs\t\t/dev/pts\tptyfs\trw\n");
+		scripting_fprintf(f, "procfs\t\t/proc\tprocfs\trw\n");
+		scripting_fprintf(f, "/dev/" CD_NAME "\t\t/cdrom\tcd9660\tro,noauto\n");
+		make_target_dir("/kern");
+		make_target_dir("/proc");
+		make_target_dir("/dev/pts");
+		make_target_dir("/cdrom");
+	}
 	scripting_fprintf(NULL, "EOF\n");
 
+	fstab_prepared = 1;
 #ifndef DEBUG
 	fclose(f);
 	fflush(NULL);
@@ -1110,12 +1129,119 @@ bootxx_name(void)
 }
 #endif
 
-// TODO: write new partition tool there
+
+
+void
+partman_restoredev(pm_devs_t *pm_devs_in)
+{
+	pm = pm_devs_in;
+	if (logfp)
+		(void)fprintf(logfp,"Partman device: %s\n", diskdev);
+	no_mbr = pm_devs_in->no_mbr;
+	strlcpy(diskdev, pm_devs_in->id, sizeof diskdev);
+	strlcpy(bsddiskname, pm_devs_in->bsddiskname, sizeof bsddiskname);
+	memcpy(oldlabel, pm_devs_in->oldlabel, sizeof oldlabel);
+	memcpy(bsdlabel, pm_devs_in->bsdlabel, sizeof bsdlabel);
+	memcpy(&mbr, &(pm_devs_in->mbr), sizeof mbr);
+	//*oldlabel = *(pm_devs_in->oldlabel);
+	//*bsdlabel = *(pm_devs_in->bsdlabel);
+	//mbr = pm_devs_in->mbr;
+	sectorsize = pm_devs_in->sectorsize;
+	dlcyl = pm_devs_in->dlcyl;
+	dlhead = pm_devs_in->dlhead;
+	dlsec = pm_devs_in->dlsec;
+	dlcylsize = pm_devs_in->dlcylsize;
+	current_cylsize = pm_devs_in->current_cylsize;
+	dlsize = pm_devs_in->dlsize;
+	ptstart = pm_devs_in->ptstart;
+	ptsize = pm_devs_in->ptsize;
+	bootstart = pm_devs_in->bootstart;
+	bootsize = pm_devs_in->bootsize;
+	return;
+}
+
+void
+partman_savedev(pm_devs_t *pm_devs_in)
+{
+	pm_devs_in->no_mbr = no_mbr;
+	strlcpy(pm_devs_in->bsddiskname, bsddiskname,
+				sizeof pm_devs_in->bsddiskname);
+	memcpy(pm_devs_in->oldlabel, oldlabel, sizeof pm_devs_in->oldlabel);
+	memcpy(pm_devs_in->bsdlabel, bsdlabel, sizeof pm_devs_in->bsdlabel);
+	memcpy(&(pm_devs_in->mbr), &mbr, sizeof pm_devs_in->mbr);
+	//*(pm_devs_in->oldlabel) = *oldlabel;
+	//*(pm_devs_in->bsdlabel) = *bsdlabel;
+	//pm_devs_in->mbr = mbr;
+	pm_devs_in->sectorsize = sectorsize;
+	pm_devs_in->dlcyl = dlcyl;
+	pm_devs_in->dlhead = dlhead;
+	pm_devs_in->dlsec = dlsec;
+	pm_devs_in->dlcylsize = dlcylsize;
+	pm_devs_in->current_cylsize = current_cylsize;
+	pm_devs_in->dlsize = dlsize;
+	pm_devs_in->ptstart = ptstart;
+	pm_devs_in->ptsize = ptsize;
+	pm_devs_in->bootstart = bootstart;
+	pm_devs_in->bootsize = bootsize;
+	return;
+}
+
+// TODO: mount order
+static int
+partman_mountall_sort(const void *a, const void *b)
+{
+	return strcmp(mnts[*(const int *)a].pi_mount,
+		      mnts[*(const int *)b].pi_mount);
+}
+
 int
-partitioning(void)
+partman_mountall(void)
 {
+	pm_devs_t *pm_devs_i;
+	int num_devs = 0;
+	int i, error;
+
+	int mnts_order[AAAAA];
+	for (pm_devs_i = pm_devs->next, num_devs = 0; pm_devs_i != NULL;
+			pm_devs_i = pm_devs_i->next) {
+		fprintf(logfp,"::%s\n",pm_devs_i->id); fflush(logfp);
+		for (i = 0; i < MAXPARTITIONS; i++) {
+			if (pm_devs_i->bsdlabel[i].pi_flags & PIF_MOUNT &&
+					pm_devs_i->bsdlabel[i].mnt_opts != NULL) {
+				mnts[num_devs].diskdev = pm_devs_i->id;
+				mnts[num_devs].mnt_opts = pm_devs_i->bsdlabel[i].mnt_opts;
+				mnts[num_devs].fsname = pm_devs_i->bsdlabel[i].fsname;
+				mnts[num_devs].pi_mount = pm_devs_i->bsdlabel[i].pi_mount;
+				num_devs++;
+				fprintf(logfp,":::%s\n",mnts[num_devs].pi_mount); fflush(logfp);
+			}
+		}
+	}
+	for (i = 0; i < num_devs; i++)
+		mnts_order[i] = i;
+	qsort(mnts_order, num_devs, sizeof mnts_order[0], partman_mountall_sort);
+
+	for (i = 0; i < num_devs; i++) {
+		make_target_dir(mnts[i].pi_mount);
+		error = target_mount(mnts[i].mnt_opts, diskdev, i, mnts[i].pi_mount);
+		if (error) {
+			msg_display(MSG_mountfail, diskdev, 'a' + i, mnts[i].pi_mount);
+			process_menu(MENU_ok, NULL);
+			return error;
+		}
+	}
+	return 0;
+}
+
+int
+partman_adddisk(menudesc *m, void *arg)
+{
+	*(int *)arg = m->cursel + 1;
+	pm_devs_t *pm_devs_new, *pm_devs_tmp;
+
 	if (find_disks(msg_string(MSG_install)) < 0)
 		return -1;
+
 	clear();
 	refresh();
 
@@ -1125,40 +1251,216 @@ partitioning(void)
 		if (check_swap(diskdev, 1) < 0) {
 			msg_display(MSG_swapdelfailed);
 			process_menu(MENU_ok, NULL);
-			if (!debug)
-				return -1;
+			return -1;
 		}
 	}
 
-	if (md_get_info() == 0)
-		return -1;
-	if (md_make_bsd_partitions() == 0)
-		return -1;
+	for (pm_devs_tmp = pm_devs; pm_devs_tmp->next != NULL;
+			pm_devs_tmp = pm_devs_tmp->next)
+		if (strcmp(pm_devs_tmp->next->id, diskdev) == 0)
+			return 0;
+	
+	pm_devs_new = malloc(sizeof (pm_devs_t));
+	pm_devs_new->next = NULL;
+	partman_savedev(pm_devs_new);
+	strlcpy(pm_devs_new->id, diskdev, sizeof pm_devs_new->id);
+	strlcpy(pm_devs_new->desc, diskdev_descr, sizeof pm_devs_new->desc);
+	pm_devs_new->bootable = 0;
+	pm_devs_new->no_mbr = 1;
+	pm_devs_tmp->next = pm_devs_new;
+	
+	return 0;
+}
 
-	/* Last chance ... do you really want to do this? */
-	clear();
-	refresh();
-	msg_display(MSG_lastchance, diskdev);
-	process_menu(MENU_noyes, NULL);
-	if (!yesno)
-		return -1;
+int
+partman_addvnd(menudesc *m, void *arg)
+{
+	*(int *)arg = m->cursel + 1;
+	return 0;
+}
 
-	if (md_pre_disklabel() != 0)
-		return -1;
+int
+partman_deldev(menudesc *m, void *arg)
+{
+	pm_devs_t *pm_devs_tmp, *pm_devs_swap;
+	*(int *)arg = m->cursel + 1;
+
+	for (pm_devs_tmp = pm_devs; pm_devs_tmp->next != NULL;
+			pm_devs_tmp = pm_devs_tmp->next)
+		if (pm_devs_tmp->next == pm) {
+			if (pm_devs_tmp->next->next == NULL) {
+				free(pm_devs_tmp->next);
+				pm_devs_tmp->next = NULL;
+			} else {
+				pm_devs_swap = pm_devs_tmp->next->next;
+				free(pm_devs_tmp->next);
+				pm_devs_tmp->next = pm_devs_swap;
+			}
+			return 0;
+		}
+	return -1;
+}
 
-	if (write_disklabel() != 0)
-		return -1;
+int
+partman_commit(menudesc *m, void *arg)
+{
+	pm_devs_t *pm_devs_i;
+	*(int *)arg = m->cursel + 1;
+
+	for (pm_devs_i = pm_devs->next; pm_devs_i != NULL;
+			pm_devs_i = pm_devs_i->next) {
+		partman_restoredev(pm_devs_i);
+		if (
+				md_pre_disklabel() != 0  || /* Write partition table */
+				write_disklabel() != 0   || /* Write slices table (disklabel) */
+				md_post_disklabel() != 0 || /* Enable swap and check badblock */
+				make_filesystems()          /* Create filesystems by newfs */
+			) { /* If something fails... */
+			return -1;
+		}
+		/* Write bootsector if needed */
+		if (pm_devs_i->bootable && md_post_newfs() != 0) {
+			return -1;
+		}
+	}
+    return 0;
+}
 
-	if (md_post_disklabel() != 0)
+static int
+partman_submenu(menudesc *m, void *arg)
+{
+	pm_devs_t *pm_devs_i;
+	int retvalue;
+	int ok = 0;
+	int i;
+	*(int *)arg = m->cursel + 1;
+
+	/* write selected disk to diskdev variable */
+	for (pm_devs_i = pm_devs->next, i = 0; !ok && pm_devs_i != NULL;
+			pm_devs_i = pm_devs_i->next, i++)
+		if (i == m->cursel) {
+			partman_restoredev(pm_devs_i);
+			ok = 1;
+			break;
+		}
+	if (!ok)
 		return -1;
 
-	if (make_filesystems())
-		return -1;
+	process_menu(MENU_pmentry, &retvalue);
+	partman_savedev(pm);
+	return 0;
+}
 
-	if (make_fstab() != 0)
-		return -1;
+void
+partman_menufmt(menudesc *m, int ptn, void *arg)
+{
+	pm_devs_t *pm_devs_i;
+	int i;
+	unsigned int maxpart;
+	char *dev_mounts = malloc(STRSIZE * sizeof(char));
+	dev_mounts[0] = '\0';
+
+	for (pm_devs_i = pm_devs->next, i = 0;
+			i != ptn && pm_devs_i != NULL;
+			pm_devs_i = pm_devs_i->next, i++);
+	if (i != ptn || pm_devs_i == NULL) 
+		return;
 
-	if (md_post_newfs() != 0)
-		return -1;
-    return 0;
+	maxpart = ((unsigned int)getmaxpartitions() > nelem(pm_devs_i->bsdlabel))?
+				nelem(pm_devs_i->bsdlabel) : (unsigned int)getmaxpartitions();
+	for (i = 0; (unsigned int)i < maxpart; i++) {
+		if (pm_devs_i->bsdlabel[i].pi_mount != 0 &&
+				pm_devs_i->bsdlabel[i].pi_fstype != FS_UNUSED) {
+			strcat(dev_mounts, pm_devs_i->bsdlabel[i].pi_mount);
+			strcat(dev_mounts, " ");
+		}
+	}
+
+	wprintw(m->mw,"%-25s %-20s %4s", pm_devs_i->desc, dev_mounts,
+			(pm_devs_i->bootable)?"BOOT":"" );
+	return;
+}
+
+// TODO: switch to langfiles
+// TODO: resolve case with 2 same bsddisknames
+int
+partman(void)
+{
+	menu_ent part_menu[MAX_DISKS];
+	int menu_pm;
+	int i, ii;
+	int retvalue = 0;
+	pm_devs_t *pm_devs_i;
+
+	do {
+		clear();
+		refresh();
+		for (pm_devs_i = pm_devs->next, i = 0; pm_devs_i != NULL;
+				pm_devs_i = pm_devs_i->next, i++) {
+			part_menu[i].opt_name = NULL;
+			part_menu[i].opt_action = partman_submenu;
+		}
+
+		part_menu[i] = (struct menu_ent) {
+			.opt_name = "Add disk",
+			.opt_action = partman_adddisk,
+		};
+		part_menu[++i] = (struct menu_ent) {
+			.opt_name = "Create CGD",
+			.opt_action = partman_addvnd,
+		};
+		part_menu[++i] = (struct menu_ent) {
+			.opt_name = "Create VND disk",
+			.opt_action = partman_addvnd,
+		};
+		part_menu[++i] = (struct menu_ent) {
+			.opt_name = "Create LVM VG",
+			.opt_action = partman_addvnd,
+		};
+		part_menu[++i] = (struct menu_ent) {
+			.opt_name = "Create RAIFframe",
+			.opt_action = partman_addvnd,
+		};
+		part_menu[++i] = (struct menu_ent) {
+			.opt_name = "Commit changes",
+			.opt_action = partman_commit,
+		};
+
+		for (ii = 0; ii <= i; ii++) {
+			part_menu[ii].opt_menu = OPT_NOMENU;
+			part_menu[ii].opt_flags = OPT_EXIT;
+		}
+
+		menu_pm = new_menu("Disk editor. All disks, partitions, LVM, RAID displayed there.\nAt first add drive, then prepare partitions and go.",
+			part_menu, i+1,	1, 1, 0, 0, MC_ALWAYS_SCROLL | MC_NOBOX | MC_NOCLEAR,
+			NULL, partman_menufmt, NULL, NULL, NULL);
+		retvalue = 0;
+		if (menu_pm == -1)
+			retvalue = -1;
+		else {
+			process_menu(menu_pm, &retvalue);
+			free_menu(menu_pm);
+		}
+
+		if (logfp)
+			(void)fprintf(logfp, "partman retvalue is %d\n", retvalue);
+	} while (retvalue > 0);
+	
+	// TODO: check_partitions()
+	/* Check that fstab on target device is readable - if so then we can go */
+	if (retvalue == 0) {
+		if (partman_mountall() != 0 ||
+			make_fstab() != 0)
+			retvalue = -1;
+		else {
+			FILE *file_tmp = fopen(concat_paths(targetroot_mnt, "/etc/fstab"), "r");
+			if (file_tmp == NULL)
+				retvalue = -1;
+			else
+				fclose(file_tmp);
+		}
+	}
+
+	/* retvalue <0 - error, retvalue ==0 - user quits, retvalue >0 - all ok */
+	return (retvalue >= 0)?0:-1;
 }
diff --git a/distrib/utils/sysinst/install.c b/distrib/utils/sysinst/install.c
index 077c75a..1b4a200 100644
--- a/distrib/utils/sysinst/install.c
+++ b/distrib/utils/sysinst/install.c
@@ -45,23 +45,69 @@
 void
 do_install(void)
 {
+	int find_disks_ret;
+	int retcode = 0;
+	partman_go = 0;
 
+#ifndef DEBUG
 	msg_display(MSG_installusure);
 	process_menu(MENU_noyes, NULL);
 	if (!yesno)
 		return;
+#endif
 
 	get_ramsize();
 
 	/* Create and mount partitions */
-	if (!partitioning() < 0) {
-		msg_display(MSG_abort);
-		process_menu(MENU_ok, NULL);
+	find_disks_ret = find_disks(msg_string(MSG_install));
+	if (partman_go == 1) {
+		if (partman() < 0) {
+			msg_display(MSG_abort);
+			process_menu(MENU_ok, NULL);
+			return;
+		}		
+	} else if (find_disks_ret < 0)
 		return;
+	else {
+	/* Classical partitioning wizard */
+		clear();
+		refresh();
+
+		if (check_swap(diskdev, 0) > 0) {
+			msg_display(MSG_swapactive);
+			process_menu(MENU_ok, NULL);
+			if (check_swap(diskdev, 1) < 0) {
+				msg_display(MSG_swapdelfailed);
+				process_menu(MENU_ok, NULL);
+				if (!debug)
+					return;
+			}
+		}
+
+		if (!md_get_info() || md_make_bsd_partitions() == 0) {
+			msg_display(MSG_abort);
+			process_menu(MENU_ok, NULL);
+			return;
+		}
+
+		/* Last chance ... do you really want to do this? */
+		clear();
+		refresh();
+		msg_display(MSG_lastchance, diskdev);
+		process_menu(MENU_noyes, NULL);
+		if (!yesno)
+			return;
+
+		if (md_pre_disklabel() != 0 || write_disklabel() != 0 ||
+			md_post_disklabel() != 0 ||make_filesystems() ||
+			make_fstab() != 0 || md_post_newfs() != 0)
+			return;
 	}
 
 	/* Unpack the distribution. */
-	process_menu(MENU_distset, NULL);
+	process_menu(MENU_distset, &retcode);
+	if (retcode == 0)
+		return;
 	if (get_and_unpack_sets(0, MSG_disksetupdone,
 	    MSG_extractcomplete, MSG_abortinst) != 0)
 		return;
diff --git a/distrib/utils/sysinst/label.c b/distrib/utils/sysinst/label.c
index f6d96ae..1b4bea6 100644
--- a/distrib/utils/sysinst/label.c
+++ b/distrib/utils/sysinst/label.c
@@ -639,7 +639,7 @@ edit_and_check_label(partinfo *lp, int nparts, int rawpart, int bsdpart)
 
 		/* User thinks the label is OK. */
 		/* check we have a single root fs */
-		if (check_one_root(lp, nparts) == 0)
+		if (check_one_root(lp, nparts) == 0 && partman_go == 0)
 			msg_display(MSG_must_be_one_root);
 		else 
 			/* Check for overlaps */
diff --git a/distrib/utils/sysinst/main.c b/distrib/utils/sysinst/main.c
index b4ca0df..ea7bf2e 100644
--- a/distrib/utils/sysinst/main.c
+++ b/distrib/utils/sysinst/main.c
@@ -62,7 +62,6 @@ static void process_f_flag(char *);
 static int exit_cleanly = 0;	/* Did we finish nicely? */
 FILE *logfp;			/* log file */
 FILE *script;			/* script file */
-int part_mode;			/* run partition editor */
 
 #ifdef DEBUG
 extern int log_flip(void);
@@ -136,6 +135,11 @@ init(void)
 	mnt2_mounted = 0;
 	fd_type = "msdos";
 
+	pm_devs = malloc (sizeof (pm_devs_t));
+	pm_devs->next = NULL;
+	pm_found = malloc (sizeof (pm_devs_t));
+	pm_found->next = NULL;
+
 	for (arg = fflagopts; arg->name != NULL; arg++)
 		strlcpy(arg->var, arg->dflt, arg->size);
 	pkg.xfer_type = pkgsrc.xfer_type = "http";
@@ -183,7 +187,7 @@ main(int argc, char **argv)
 			break;
 		case 'p':
 			/* Partition tool */
-			part_mode = 1;
+			partman_go = 1;
 			break;
 		case '?':
 		default:
@@ -231,8 +235,8 @@ main(int argc, char **argv)
 	get_kb_encoding();
 
 	/* Menu processing */
-	if (part_mode)
-		partitioning();
+	if (partman_go)
+		partman();
 	else
 		process_menu(MENU_netbsd, NULL);
 
diff --git a/distrib/utils/sysinst/menus.mi b/distrib/utils/sysinst/menus.mi
index 36e88e5..01620c5 100644
--- a/distrib/utils/sysinst/menus.mi
+++ b/distrib/utils/sysinst/menus.mi
@@ -177,7 +177,7 @@ menu utility, title MSG_NetBSD_VERSION_Utilities, exit,
 			network_up = 0;
 			config_network();
 		};
-	option MSG_Partition_a_disk, action { partitioning(); };
+	option MSG_Partition_a_disk, action { partman(); };
 	option MSG_Logging_functions, action { do_logging(); };
 	option MSG_Color_scheme, sub menu colors;
 	option MSG_Halt_the_system, exit,
@@ -241,12 +241,12 @@ menu distmedium, title MSG_Select_medium, y=-5;
 	option MSG_Skip_group,exit, action { *(int *)arg = SET_SKIP_GROUP; };
 	option MSG_Abandon,   exit, action { *(int *)arg = SET_ABANDON; };
 
-menu distset, title MSG_Select_your_distribution;
+menu distset, title MSG_Select_your_distribution, exit;
 	display action { msg_display (MSG_distset); };
-	option MSG_Full_installation, exit, action { init_set_status(0);  };
-	option MSG_Full_installation_nox, exit, action { init_set_status(SFLAG_NOX); };
-	option MSG_Minimal_installation, exit, action { init_set_status(SFLAG_MINIMAL); };
-	option MSG_Custom_installation, exit, action { init_set_status(SFLAG_MINIMAL); customise_sets(); };
+	option MSG_Full_installation, exit, action { *(int *)arg = 1; init_set_status(0);  };
+	option MSG_Full_installation_nox, exit, action { *(int *)arg = 1; init_set_status(SFLAG_NOX); };
+	option MSG_Minimal_installation, exit, action { *(int *)arg = 1; init_set_status(SFLAG_MINIMAL); };
+	option MSG_Custom_installation, exit, action { *(int *)arg = 1; init_set_status(SFLAG_MINIMAL); customise_sets(); };
 
 menu ftpsource, y=-4, x=0, w=70, no box, no clear,
 	    exitstring MSG_Get_Distribution;
@@ -505,3 +505,12 @@ menu pkgsrc, y=-4, x=0, w=70, no box, no clear,
 			config_network();
 		};
 	option MSG_quit_install, exit, action { yesno = SET_SKIP; };
+
+menu pmentry, x=50, y=5, sub menu, exit, default exit, title diskdev;
+	option "Prepare",			exit, action { md_get_info(); };
+	option "Prepare GPT",		exit, action { md_get_info(); };
+	option "Commit prepare",	exit, action { md_pre_disklabel(); };
+	option "Disk label",		exit, action { md_make_bsd_partitions(); };
+	option "Commit label",		exit, action { write_disklabel(); md_post_disklabel(); };
+	option "Toggle bootable",   exit, action { pm->bootable = !pm->bootable; };
+	option "Remove",			exit, action { partman_deldev(m, arg); };
diff --git a/distrib/utils/sysinst/savenewlabel.c b/distrib/utils/sysinst/savenewlabel.c
index b8567a9..3fc83b0 100644
--- a/distrib/utils/sysinst/savenewlabel.c
+++ b/distrib/utils/sysinst/savenewlabel.c
@@ -58,8 +58,12 @@ int
 savenewlabel(partinfo *lp, int nparts)
 {
 	FILE *f;
+	char *f_name = malloc(STRSIZE * sizeof(char));
 	int i;
 
+	strlcpy(f_name, "/tmp/disktab.", STRSIZE);
+	strlcat(f_name, bsddiskname, STRSIZE);
+
 	/*
 	  N.B. disklabels only support up to 2TB (32-bit field for sectors).
 	  This function explicitly narrows from daddr_t (64-bit unsigned) to
@@ -67,16 +71,17 @@ savenewlabel(partinfo *lp, int nparts)
 	 */
 
 	/* Create /etc/disktab */
-	f = fopen("/tmp/disktab", "w");
+
+	f = fopen(f_name, "w");
 	if (logfp)
-		(void)fprintf(logfp, "Creating disklabel %s\n", bsddiskname);
+		(void)fprintf(logfp, "Creating disklabel %s in %s\n", bsddiskname,
+						f_name);
 	scripting_fprintf(NULL, "cat <<EOF >>/etc/disktab\n");
 	if (f == NULL) {
 		endwin();
-		(void)fprintf(stderr, "Could not open /etc/disktab");
+		(void)fprintf(stderr, "Could not open %s for writing\n", f_name);
 		if (logfp)
-			(void)fprintf(logfp,
-			    "Failed to open /etc/disktab for appending.\n");
+			(void)fprintf(logfp, "Could not open %s for writing\n", f_name);
 		exit (1);
 	}
 	scripting_fprintf(f, "%s|NetBSD installation generated:\\\n", bsddiskname);
@@ -110,5 +115,6 @@ savenewlabel(partinfo *lp, int nparts)
 	fclose (f);
 	scripting_fprintf(NULL, "EOF\n");
 	fflush(NULL);
+	run_program(0, "sh -c 'cat /tmp/disktab.* >/tmp/disktab'");
 	return(0);
 }
diff --git a/distrib/utils/sysinst/upgrade.c b/distrib/utils/sysinst/upgrade.c
index 4969412..ba8a862 100644
--- a/distrib/utils/sysinst/upgrade.c
+++ b/distrib/utils/sysinst/upgrade.c
@@ -54,6 +54,7 @@ static int merge_X(const char *);
 void
 do_upgrade(void)
 {
+	int retcode = 0;
 
 	msg_display(MSG_upgradeusure);
 	process_menu(MENU_noyes, NULL);
@@ -94,7 +95,9 @@ do_upgrade(void)
 	wrefresh(stdscr);
 
 	/* Done with disks. Ready to get and unpack tarballs. */
-	process_menu(MENU_distset, NULL);
+	process_menu(MENU_distset, &retcode);
+	if (retcode == 0)
+		return;
 	if (get_and_unpack_sets(1, MSG_disksetupdoneupdate,
 	    MSG_upgrcomplete, MSG_abortupgr) != 0)
 		return;
@@ -171,6 +174,7 @@ merge_X(const char *xroot)
 void
 do_reinstall_sets(void)
 {
+	int retcode = 0;
 
 	unwind_mounts();
 	msg_display(MSG_reinstallusure);
@@ -185,7 +189,9 @@ do_reinstall_sets(void)
 		return;
 
 	/* Unpack the distribution. */
-	process_menu(MENU_distset, NULL);
+	process_menu(MENU_distset, &retcode);
+	if (retcode == 0)
+		return;
 	if (get_and_unpack_sets(0, NULL, MSG_unpackcomplete, MSG_abortunpack) != 0)
 		return;
 
