From 7db454feb82201169fa56cbbbda6b3176663c669 Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Sat, 14 Jan 2017 06:42:05 +0100
Subject: [PATCH 2/4] installer: Add basic UEFI system setup.

GPT partition 0 is a 128MB FAT32 EFI system partition. Microsoft
recommends at least 100MB and FAT32 in [1]. Partition 1 is a
"DragonFly Label64" (aka "dragonfly" in gpt(8)) for the rest of
the disk. It is analogous to slice 1 in our MBR setup, and has the
same name, e.g. /dev/da0s1. The rest of the UEFI setup is identical
to an MBR setup. disklabel64, newfs*, and so forth.

We currently only support installing DragonFly to the whole disk
in UEFI mode, and we don't set any NVRAM EFI variables during
installation, so for now we are copying our stage 1 loader to
\EFI\BOOT\BOOTX64.EFI on the EFI system partition.

[1] https://technet.microsoft.com/en-us/library/hh824839.aspx#DiskPartitionRules
---
 share/installer/cmdnames.conf                 |  2 ++
 usr.sbin/installer/dfuibe_installer/flow.c    | 42 +++++++++++++++++++++++++--
 usr.sbin/installer/dfuibe_installer/flow.h    |  2 ++
 usr.sbin/installer/dfuibe_installer/fn_disk.c | 37 ++++++++++++++++++++---
 usr.sbin/installer/libinstaller/diskutil.h    |  3 ++
 5 files changed, 79 insertions(+), 7 deletions(-)

diff --git a/share/installer/cmdnames.conf b/share/installer/cmdnames.conf
index 1c05c93858..24eea2db55 100644
--- a/share/installer/cmdnames.conf
+++ b/share/installer/cmdnames.conf
@@ -28,11 +28,13 @@ DHCLIENT=sbin/dhclient
 DISKLABEL64=sbin/disklabel64
 DUMPON=sbin/dumpon
 FDISK=sbin/fdisk
+GPT=sbin/gpt
 HAMMER=sbin/hammer
 IFCONFIG=sbin/ifconfig
 MOUNT=sbin/mount
 MOUNTD=sbin/mountd
 MOUNT_HAMMER=sbin/mount_hammer
+MOUNT_MSDOS=sbin/mount_msdos
 MOUNT_NULL=sbin/mount_null
 MOUNT_TMPFS=sbin/mount_tmpfs
 NEWFS=sbin/newfs
diff --git a/usr.sbin/installer/dfuibe_installer/flow.c b/usr.sbin/installer/dfuibe_installer/flow.c
index 0838a70130..2d99d3fcf2 100644
--- a/usr.sbin/installer/dfuibe_installer/flow.c
+++ b/usr.sbin/installer/dfuibe_installer/flow.c
@@ -921,7 +921,7 @@ state_begin_install(struct i_fn_args *a)
 			inform(a->c, _("Errors occurred while probing "
 			    "the system for its storage capabilities."));
 		}
-		state = state_select_disk;
+		state = state_ask_uefi;
 	} else if (strcmp(dfui_response_get_action_id(r), "livecd") == 0) {
 		state = NULL;
 	} else if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
@@ -933,6 +933,38 @@ state_begin_install(struct i_fn_args *a)
 }
 
 /*
+ * state_ask_uefi: ask the user if they want a UEFI installation
+ */
+void
+state_ask_uefi(struct i_fn_args *a)
+{
+	use_uefi = 0;
+
+	switch (dfui_be_present_dialog(a->c, _("UEFI or legacy BIOS?"),
+	    _("UEFI|Legacy BIOS|Return to Begin Installation"),
+	    _("Do you wish to set up %s for a UEFI or legacy BIOS system?"),
+	    OPERATING_SYSTEM_NAME))
+	{
+	case 1:
+		/* UEFI */
+		use_uefi = 1;
+		break;
+	case 2:
+		/* MBR */
+		break;
+	case 3:
+		state = state_begin_install;
+		return;
+		/* NOTREACHED */
+		break;
+	default:
+		abort_backend();
+		break;
+	}
+	state = state_select_disk;
+}
+
+/*
  * state_select_disk: ask the user on which physical disk they wish
  * to install DragonFly.
  */
@@ -1218,8 +1250,12 @@ state_install_os(struct i_fn_args *a)
 		state = state_create_subpartitions;
 	} else {
 		fn_install_os(a);
-		if (a->result)
-			state = state_install_bootstrap;
+		if (a->result) {
+			if (use_uefi)
+				state = state_finish_install;
+			else
+				state = state_install_bootstrap;
+		}
 	}
 
 	dfui_form_free(f);
diff --git a/usr.sbin/installer/dfuibe_installer/flow.h b/usr.sbin/installer/dfuibe_installer/flow.h
index ee93ad48d6..9b5a13a411 100644
--- a/usr.sbin/installer/dfuibe_installer/flow.h
+++ b/usr.sbin/installer/dfuibe_installer/flow.h
@@ -50,6 +50,7 @@
 
 struct i_fn_args;
 int use_hammer;
+int use_uefi;
 int during_install;
 /*** PROTOTYPES ***/
 
@@ -71,6 +72,7 @@ void 		 state_diskutil_menu(struct i_fn_args *);
 
 void		 state_begin_install(struct i_fn_args *);
 void		 state_begin_upgrade(struct i_fn_args *);
+void		 state_ask_uefi(struct i_fn_args *);
 void		 state_select_disk(struct i_fn_args *);
 void		 state_ask_fs(struct i_fn_args *);
 void		 state_format_disk(struct i_fn_args *);
diff --git a/usr.sbin/installer/dfuibe_installer/fn_disk.c b/usr.sbin/installer/dfuibe_installer/fn_disk.c
index 1508b9c4ad..4df8e7ff42 100644
--- a/usr.sbin/installer/dfuibe_installer/fn_disk.c
+++ b/usr.sbin/installer/dfuibe_installer/fn_disk.c
@@ -203,9 +203,38 @@ fn_format_disk(struct i_fn_args *a)
 	    "LAST CHANCE to cancel!"), disk_get_desc(storage_get_selected_disk(a->s)))) {
 		cmds = commands_new();
 
-		command_add(cmds, "%s%s -BI %s",
-		    a->os_root, cmd_name(a, "FDISK"),
-		    disk_get_device_name(storage_get_selected_disk(a->s)));
+		if (use_uefi) {
+			command_add(cmds, "%s%s destroy %s",
+			    a->os_root, cmd_name(a, "GPT"),
+			    disk_get_device_name(storage_get_selected_disk(a->s)));
+			command_add(cmds, "%s%s create -f %s",
+			    a->os_root, cmd_name(a, "GPT"),
+			    disk_get_device_name(storage_get_selected_disk(a->s)));
+			command_add(cmds, "%s%s add -i 0 -s 262144 -t efi %s",
+			    a->os_root, cmd_name(a, "GPT"),
+			    disk_get_device_name(storage_get_selected_disk(a->s)));
+			command_add(cmds, "%s%s add -i 1 -t dragonfly %s",
+			    a->os_root, cmd_name(a, "GPT"),
+			    disk_get_device_name(storage_get_selected_disk(a->s)));
+			command_add(cmds, "%s%s -F 32 -c 2 -L EFI -m 0xf8 %ss0",
+			    a->os_root, cmd_name(a, "NEWFS_MSDOS"),
+			    disk_get_device_name(storage_get_selected_disk(a->s)));
+			command_add(cmds, "%s%s /dev/%ss0 %smnt",
+			    a->os_root, cmd_name(a, "MOUNT_MSDOS"),
+			    disk_get_device_name(storage_get_selected_disk(a->s)),
+			    a->os_root);
+			command_add(cmds, "%s%s -p %smnt/EFI/BOOT",
+			    a->os_root, cmd_name(a, "MKDIR"), a->os_root);
+			command_add(cmds, "%s%s %s/boot/boot1.efi %smnt/EFI/BOOT/BOOTX64.EFI",
+			    a->os_root, cmd_name(a, "CP"),
+			    a->os_root, a->os_root);
+			command_add(cmds, "%s%s %smnt",
+			    a->os_root, cmd_name(a, "UMOUNT"), a->os_root);
+		} else {
+			command_add(cmds, "%s%s -BI %s",
+			    a->os_root, cmd_name(a, "FDISK"),
+			    disk_get_device_name(storage_get_selected_disk(a->s)));
+		}
 
 		if (!commands_execute(a, cmds)) {
 			inform(a->c, _("The disk\n\n%s\n\nwas "
@@ -243,7 +272,7 @@ fn_format_disk(struct i_fn_args *a)
 		disk_set_formatted(storage_get_selected_disk(a->s), 1);
 		storage_set_selected_slice(a->s, disk_slice_first(storage_get_selected_disk(a->s)));
 
-		if (!format_slice(a)) {
+		if (!use_uefi && !format_slice(a)) {
 			inform(a->c, _("The sole primary partition of "
 			    "the disk\n\n%s\n\nwas "
 			    "not correctly formatted, and may "
diff --git a/usr.sbin/installer/libinstaller/diskutil.h b/usr.sbin/installer/libinstaller/diskutil.h
index c77f2dada6..db9fa6d839 100644
--- a/usr.sbin/installer/libinstaller/diskutil.h
+++ b/usr.sbin/installer/libinstaller/diskutil.h
@@ -43,6 +43,9 @@
 
 #include "functions.h"
 
+/*** GLOBALS ***/
+extern int	use_uefi;
+
 /*** TYPES ***/
 
 struct storage;
-- 
2.11.0

