From 7b1aa074fcd99442a1345fb8a695b62d01d9c7fd Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Sun, 15 Jan 2017 20:32:06 +0100 Subject: [PATCH] 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. Also, there isn't any support for Secure Boot. [1] https://technet.microsoft.com/en-us/library/hh824839.aspx#DiskPartitionRules --- share/installer/cmdnames.conf | 2 + usr.sbin/installer/dfuibe_installer/flow.c | 60 +++++++++++++-- usr.sbin/installer/dfuibe_installer/flow.h | 2 + usr.sbin/installer/dfuibe_installer/fn.h | 3 +- usr.sbin/installer/dfuibe_installer/fn_disk.c | 104 +++++++++++++++++++++++++- 5 files changed, 164 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..f9e5f41d02 100644 --- a/usr.sbin/installer/dfuibe_installer/flow.c +++ b/usr.sbin/installer/dfuibe_installer/flow.c @@ -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) { @@ -933,6 +936,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. */ @@ -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); 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.h b/usr.sbin/installer/dfuibe_installer/fn.h index 6bf3e582d0..3f3894ce46 100644 --- a/usr.sbin/installer/dfuibe_installer/fn.h +++ b/usr.sbin/installer/dfuibe_installer/fn.h @@ -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 *); diff --git a/usr.sbin/installer/dfuibe_installer/fn_disk.c b/usr.sbin/installer/dfuibe_installer/fn_disk.c index 1508b9c4ad..9d4d04c152 100644 --- a/usr.sbin/installer/dfuibe_installer/fn_disk.c +++ b/usr.sbin/installer/dfuibe_installer/fn_disk.c @@ -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. */ -- 2.11.4.GIT