installer: Add basic UEFI system setup.
authorSascha Wildner <saw@online.de>
Sun, 15 Jan 2017 19:32:06 +0000 (20:32 +0100)
committerSascha Wildner <saw@online.de>
Sun, 15 Jan 2017 19:32:06 +0000 (20:32 +0100)
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.

Also, there isn't any support for Secure Boot.

[1] https://technet.microsoft.com/en-us/library/hh824839.aspx#DiskPartitionRules

share/installer/cmdnames.conf
usr.sbin/installer/dfuibe_installer/flow.c
usr.sbin/installer/dfuibe_installer/flow.h
usr.sbin/installer/dfuibe_installer/fn.h
usr.sbin/installer/dfuibe_installer/fn_disk.c

index 1c05c93..24eea2d 100644 (file)
@@ -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
index 0838a70..f9e5f41 100644 (file)
@@ -781,7 +781,10 @@ state_diskutil_menu(struct i_fn_args *a)
                if (strcmp(dfui_response_get_action_id(r), "format_hdd") == 0) {
                        storage_set_selected_disk(a->s, NULL);
                        storage_set_selected_slice(a->s, NULL);
-                       fn_format_disk(a);
+                       if (use_uefi)
+                               fn_format_disk_uefi(a);
+                       else
+                               fn_format_disk_mbr(a);
                } else if (strcmp(dfui_response_get_action_id(r), "wipe_start_of_disk") == 0) {
                        fn_wipe_start_of_disk(a);
                } else if (strcmp(dfui_response_get_action_id(r), "wipe_start_of_slice") == 0) {
@@ -921,7 +924,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) {
@@ -932,6 +935,38 @@ state_begin_install(struct i_fn_args *a)
        dfui_response_free(r);
 }
 
+/*
+ * 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.
@@ -1017,6 +1052,17 @@ state_ask_fs(struct i_fn_args *a)
 void
 state_format_disk(struct i_fn_args *a)
 {
+
+       if (use_uefi) {
+               fn_format_disk_uefi(a);
+               if (a->result)
+                       state = state_ask_fs;
+               else
+                       state = state_format_disk;
+               return;
+       }
+
+       /* XXX Using part of the disk is only supported for MBR installs */
        switch (dfui_be_present_dialog(a->c, _("How Much Disk?"),
            _("Use Entire Disk|Use Part of Disk|Return to Select Disk"),
            _("Select how much of this disk you want to use for %s.\n\n%s"),
@@ -1032,7 +1078,7 @@ state_format_disk(struct i_fn_args *a)
                        }
                }
 
-               fn_format_disk(a);
+               fn_format_disk_mbr(a);
                if (a->result)
                        state = state_ask_fs;
                else
@@ -1218,8 +1264,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);
index ee93ad4..9b5a13a 100644 (file)
@@ -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 *);
index 6bf3e58..3f3894c 100644 (file)
@@ -86,7 +86,8 @@ char          *fn_select_file(const char *, const char *, const char *,
                                const char *, const char *, const char *,
                                const struct i_fn_args *);
 
-void            fn_format_disk(struct i_fn_args *);
+void            fn_format_disk_mbr(struct i_fn_args *);
+void            fn_format_disk_uefi(struct i_fn_args *);
 void            fn_install_bootblocks(struct i_fn_args *, const char *device);
 void            fn_wipe_start_of_disk(struct i_fn_args *);
 void            fn_wipe_start_of_slice(struct i_fn_args *);
index 1508b9c..9d4d04c 100644 (file)
@@ -181,7 +181,7 @@ fn_select_slice(struct i_fn_args *a)
  * If it was, ss->selected_disk and ss->selected_slice are set to it.
  */
 void
-fn_format_disk(struct i_fn_args *a)
+fn_format_disk_mbr(struct i_fn_args *a)
 {
        struct commands *cmds;
        char *selected_disk_string;
@@ -266,6 +266,108 @@ fn_format_disk(struct i_fn_args *a)
        }
 }
 
+void
+fn_format_disk_uefi(struct i_fn_args *a)
+{
+       struct commands *cmds;
+       char *selected_disk_string;
+
+       if (storage_get_selected_disk(a->s) == NULL) {
+               a->short_desc = _("Select a disk to format.");
+               a->cancel_desc = _("Return to Utilities Menu");
+               fn_select_disk(a);
+               if (!a->result || storage_get_selected_disk(a->s) == NULL) {
+                       a->result = 0;
+                       return;
+               }
+       }
+
+       if (confirm_dangerous_action(a->c,
+           _("WARNING!  ALL data in ALL partitions on the disk\n\n"
+           "%s\n\nwill be IRREVOCABLY ERASED!\n\nAre you ABSOLUTELY "
+           "SURE you wish to take this action?  This is your "
+           "LAST CHANCE to cancel!"), disk_get_desc(storage_get_selected_disk(a->s)))) {
+               cmds = commands_new();
+
+               command_add(cmds,
+                   "%s%s if=/dev/zero of=/dev/%s bs=32k count=16",
+                   a->os_root, cmd_name(a, "DD"),
+                   disk_get_device_name(storage_get_selected_disk(a->s)));
+               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);
+
+               if (!commands_execute(a, cmds)) {
+                       inform(a->c, _("The disk\n\n%s\n\nwas "
+                           "not correctly formatted, and may "
+                           "now be in an inconsistent state. "
+                           "We recommend re-formatting it "
+                           "before attempting to install "
+                           "%s on it."),
+                           disk_get_desc(storage_get_selected_disk(a->s)),
+                           OPERATING_SYSTEM_NAME);
+                       commands_free(cmds);
+                       a->result = 0;
+                       return;
+               }
+               commands_free(cmds);
+
+               /*
+                * Since one of the disks has now changed, we must
+                * refresh our view of them and re-select the disk
+                * since the selected_disk pointer will be invalidated.
+                */
+               selected_disk_string = aura_strdup(
+                   disk_get_device_name(storage_get_selected_disk(a->s)));
+               if (!survey_storage(a)) {
+                       inform(a->c, _("Errors occurred while probing "
+                           "the system for its storage capabilities."));
+               }
+               storage_set_selected_disk(a->s,
+                   disk_find(a->s, selected_disk_string));
+               free(selected_disk_string);
+
+               /*
+                * Note that we formatted this disk and that we want
+                * to use the first (and only) slice of it.
+                */
+               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)));
+
+               inform(a->c, _("The disk\n\n%s\n\nwas formatted."),
+                   disk_get_desc(storage_get_selected_disk(a->s)));
+               a->result = 1;
+       } else {
+               inform(a->c, _("Action cancelled - no disks were formatted."));
+               a->result = 0;
+       }
+}
+
 /*
  * Wipes the start of the selected disk.
  */