xref: /dflybsd-src/usr.sbin/installer/dfuibe_installer/fn_disk.c (revision a096577d7d6db4aaa199cf083e70a11e7c496267)
121c1c48aSSascha Wildner /*
221c1c48aSSascha Wildner  * Copyright (c)2004 The DragonFly Project.  All rights reserved.
321c1c48aSSascha Wildner  *
421c1c48aSSascha Wildner  * Redistribution and use in source and binary forms, with or without
521c1c48aSSascha Wildner  * modification, are permitted provided that the following conditions
621c1c48aSSascha Wildner  * are met:
721c1c48aSSascha Wildner  *
821c1c48aSSascha Wildner  *   Redistributions of source code must retain the above copyright
921c1c48aSSascha Wildner  *   notice, this list of conditions and the following disclaimer.
1021c1c48aSSascha Wildner  *
1121c1c48aSSascha Wildner  *   Redistributions in binary form must reproduce the above copyright
1221c1c48aSSascha Wildner  *   notice, this list of conditions and the following disclaimer in
1321c1c48aSSascha Wildner  *   the documentation and/or other materials provided with the
1421c1c48aSSascha Wildner  *   distribution.
1521c1c48aSSascha Wildner  *
1621c1c48aSSascha Wildner  *   Neither the name of the DragonFly Project nor the names of its
1721c1c48aSSascha Wildner  *   contributors may be used to endorse or promote products derived
1821c1c48aSSascha Wildner  *   from this software without specific prior written permission.
1921c1c48aSSascha Wildner  *
2021c1c48aSSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2121c1c48aSSascha Wildner  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2221c1c48aSSascha Wildner  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2321c1c48aSSascha Wildner  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2421c1c48aSSascha Wildner  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
2521c1c48aSSascha Wildner  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2621c1c48aSSascha Wildner  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2721c1c48aSSascha Wildner  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2821c1c48aSSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2921c1c48aSSascha Wildner  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3021c1c48aSSascha Wildner  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
3121c1c48aSSascha Wildner  * OF THE POSSIBILITY OF SUCH DAMAGE.
3221c1c48aSSascha Wildner  */
3321c1c48aSSascha Wildner 
3421c1c48aSSascha Wildner /*
3521c1c48aSSascha Wildner  * fn_disk.c
3621c1c48aSSascha Wildner  * Disk functions for installer.
3721c1c48aSSascha Wildner  * $Id: fn_disk.c,v 1.40 2005/03/13 01:53:58 cpressey Exp $
3821c1c48aSSascha Wildner  */
3921c1c48aSSascha Wildner 
4021c1c48aSSascha Wildner #include <stdlib.h>
4121c1c48aSSascha Wildner #include <string.h>
4221c1c48aSSascha Wildner 
4321c1c48aSSascha Wildner #ifdef ENABLE_NLS
4421c1c48aSSascha Wildner #include <libintl.h>
4521c1c48aSSascha Wildner #define _(String) gettext (String)
4621c1c48aSSascha Wildner #else
4721c1c48aSSascha Wildner #define _(String) (String)
4821c1c48aSSascha Wildner #endif
4921c1c48aSSascha Wildner 
5021c1c48aSSascha Wildner #include "libaura/mem.h"
5121c1c48aSSascha Wildner #include "libaura/fspred.h"
5221c1c48aSSascha Wildner 
5321c1c48aSSascha Wildner #include "libdfui/dfui.h"
5421c1c48aSSascha Wildner #include "libdfui/system.h"
5521c1c48aSSascha Wildner 
5621c1c48aSSascha Wildner #include "libinstaller/commands.h"
5721c1c48aSSascha Wildner #include "libinstaller/diskutil.h"
5821c1c48aSSascha Wildner #include "libinstaller/functions.h"
5921c1c48aSSascha Wildner #include "libinstaller/uiutil.h"
6021c1c48aSSascha Wildner 
6121c1c48aSSascha Wildner #include "fn.h"
6221c1c48aSSascha Wildner #include "pathnames.h"
6321c1c48aSSascha Wildner 
6421c1c48aSSascha Wildner /*** DISK-RELATED FUNCTIONS ***/
6521c1c48aSSascha Wildner 
6621c1c48aSSascha Wildner /*
6721c1c48aSSascha Wildner  * Ask the user which physical disk they want.
6821c1c48aSSascha Wildner  * Changes ss->selected_disk if successful.
6921c1c48aSSascha Wildner  */
7021c1c48aSSascha Wildner void
7121c1c48aSSascha Wildner fn_select_disk(struct i_fn_args *a)
7221c1c48aSSascha Wildner {
7321c1c48aSSascha Wildner 	struct dfui_form *f;
7421c1c48aSSascha Wildner 	struct dfui_action *k;
7521c1c48aSSascha Wildner 	struct dfui_response *r;
7621c1c48aSSascha Wildner 	struct disk *d;
7721c1c48aSSascha Wildner 
7821c1c48aSSascha Wildner 	f = dfui_form_create(
7921c1c48aSSascha Wildner 	    "select_disk",
8021c1c48aSSascha Wildner 	    _("Select Disk"),
8121c1c48aSSascha Wildner 	    a->short_desc,
8221c1c48aSSascha Wildner 	    "",
8321c1c48aSSascha Wildner 
8421c1c48aSSascha Wildner 	    "p", "role",  "menu",
8521c1c48aSSascha Wildner 	    "p", "special", "dfinstaller_select_disk",
8621c1c48aSSascha Wildner 
8721c1c48aSSascha Wildner 	    NULL
8821c1c48aSSascha Wildner 	);
8921c1c48aSSascha Wildner 
9021c1c48aSSascha Wildner 	for (d = storage_disk_first(a->s); d != NULL; d = disk_next(d)) {
9121c1c48aSSascha Wildner 		dfui_form_action_add(f, disk_get_device_name(d),
9221c1c48aSSascha Wildner 		    dfui_info_new(disk_get_desc(d), "", ""));
9321c1c48aSSascha Wildner 	}
9421c1c48aSSascha Wildner 
9521c1c48aSSascha Wildner 	k = dfui_form_action_add(f, "cancel",
9621c1c48aSSascha Wildner 	    dfui_info_new(a->cancel_desc, "", ""));
9721c1c48aSSascha Wildner 	dfui_action_property_set(k, "accelerator", "ESC");
9821c1c48aSSascha Wildner 
9921c1c48aSSascha Wildner 	if (!dfui_be_present(a->c, f, &r))
10021c1c48aSSascha Wildner 		abort_backend();
10121c1c48aSSascha Wildner 
10221c1c48aSSascha Wildner 	if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
10321c1c48aSSascha Wildner 		a->result = 0;
10421c1c48aSSascha Wildner 	} else {
10521c1c48aSSascha Wildner 		d = disk_find(a->s, dfui_response_get_action_id(r));
10621c1c48aSSascha Wildner 		if (d == NULL) {
10721c1c48aSSascha Wildner 			inform(a->c, _("Internal error - response from frontend "
10821c1c48aSSascha Wildner 			    "should be a valid device name."));
10921c1c48aSSascha Wildner 			a->result = 0;
11021c1c48aSSascha Wildner 		} else {
11121c1c48aSSascha Wildner 			storage_set_selected_disk(a->s, d);
11221c1c48aSSascha Wildner 			a->result = 1;
11321c1c48aSSascha Wildner 		}
11421c1c48aSSascha Wildner 	}
11521c1c48aSSascha Wildner 
11621c1c48aSSascha Wildner 	dfui_form_free(f);
11721c1c48aSSascha Wildner 	dfui_response_free(r);
11821c1c48aSSascha Wildner }
11921c1c48aSSascha Wildner 
12021c1c48aSSascha Wildner /*
12121c1c48aSSascha Wildner  * Ask the user which slice on a the selected disk they want.
12221c1c48aSSascha Wildner  * Changes ss->selected_slice.
12321c1c48aSSascha Wildner  */
12421c1c48aSSascha Wildner void
12521c1c48aSSascha Wildner fn_select_slice(struct i_fn_args *a)
12621c1c48aSSascha Wildner {
12721c1c48aSSascha Wildner 	struct dfui_form *f;
12821c1c48aSSascha Wildner 	struct dfui_action *k;
12921c1c48aSSascha Wildner 	struct dfui_response *r;
13021c1c48aSSascha Wildner 	struct slice *s;
13121c1c48aSSascha Wildner 	char string[16];
13221c1c48aSSascha Wildner 
13321c1c48aSSascha Wildner 	f = dfui_form_create(
13421c1c48aSSascha Wildner 	    "select_slice",
13521c1c48aSSascha Wildner 	    _("Select Primary Partition"),
13621c1c48aSSascha Wildner 	    a->short_desc,
13721c1c48aSSascha Wildner 	    "",
13821c1c48aSSascha Wildner 
13921c1c48aSSascha Wildner 	    "p", "role", "menu",
14021c1c48aSSascha Wildner 	    "p", "special", "dfinstaller_select_slice",
14121c1c48aSSascha Wildner 
14221c1c48aSSascha Wildner 	    NULL
14321c1c48aSSascha Wildner 	);
14421c1c48aSSascha Wildner 
14521c1c48aSSascha Wildner 	for (s = disk_slice_first(storage_get_selected_disk(a->s));
14621c1c48aSSascha Wildner 	     s != NULL; s = slice_next(s)) {
14721c1c48aSSascha Wildner 		snprintf(string, 16, "%d", slice_get_number(s));
14821c1c48aSSascha Wildner 		dfui_form_action_add(f, string,
14921c1c48aSSascha Wildner 		    dfui_info_new(slice_get_desc(s), "", ""));
15021c1c48aSSascha Wildner 	}
15121c1c48aSSascha Wildner 
15221c1c48aSSascha Wildner 	k = dfui_form_action_add(f, "cancel",
15321c1c48aSSascha Wildner 	    dfui_info_new(a->cancel_desc, "", ""));
15421c1c48aSSascha Wildner 	dfui_action_property_set(k, "accelerator", "ESC");
15521c1c48aSSascha Wildner 
15621c1c48aSSascha Wildner 	if (!dfui_be_present(a->c, f, &r))
15721c1c48aSSascha Wildner 		abort_backend();
15821c1c48aSSascha Wildner 
15921c1c48aSSascha Wildner 	if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) {
16021c1c48aSSascha Wildner 		a->result = 0;
16121c1c48aSSascha Wildner 	} else {
16221c1c48aSSascha Wildner 		s = slice_find(storage_get_selected_disk(a->s),
16321c1c48aSSascha Wildner 		    atoi(dfui_response_get_action_id(r)));
16421c1c48aSSascha Wildner 		if (s == NULL) {
16521c1c48aSSascha Wildner 			inform(a->c, _("Internal error - response from frontend "
16621c1c48aSSascha Wildner 			    "should be a valid slice number."));
16721c1c48aSSascha Wildner 			a->result = 0;
16821c1c48aSSascha Wildner 		} else {
16921c1c48aSSascha Wildner 			storage_set_selected_slice(a->s, s);
17021c1c48aSSascha Wildner 			a->result = 1;
17121c1c48aSSascha Wildner 		}
17221c1c48aSSascha Wildner 	}
17321c1c48aSSascha Wildner 
17421c1c48aSSascha Wildner 	dfui_form_free(f);
17521c1c48aSSascha Wildner 	dfui_response_free(r);
17621c1c48aSSascha Wildner }
17721c1c48aSSascha Wildner 
17821c1c48aSSascha Wildner /*
17921c1c48aSSascha Wildner  * If ss->selected_disk == NULL, user will be asked for which disk.
18021c1c48aSSascha Wildner  * Returns 1 if disk was formatted, 0 if it wasn't.
18121c1c48aSSascha Wildner  * If it was, ss->selected_disk and ss->selected_slice are set to it.
18221c1c48aSSascha Wildner  */
18321c1c48aSSascha Wildner void
18421c1c48aSSascha Wildner fn_format_disk(struct i_fn_args *a)
18521c1c48aSSascha Wildner {
18621c1c48aSSascha Wildner 	struct commands *cmds;
18721c1c48aSSascha Wildner 	char *selected_disk_string;
18821c1c48aSSascha Wildner 
18921c1c48aSSascha Wildner 	if (storage_get_selected_disk(a->s) == NULL) {
19021c1c48aSSascha Wildner 		a->short_desc = _("Select a disk to format.");
19121c1c48aSSascha Wildner 		a->cancel_desc = _("Return to Utilities Menu");
19221c1c48aSSascha Wildner 		fn_select_disk(a);
19321c1c48aSSascha Wildner 		if (!a->result || storage_get_selected_disk(a->s) == NULL) {
19421c1c48aSSascha Wildner 			a->result = 0;
19521c1c48aSSascha Wildner 			return;
19621c1c48aSSascha Wildner 		}
19721c1c48aSSascha Wildner 	}
19821c1c48aSSascha Wildner 
19921c1c48aSSascha Wildner 	if (confirm_dangerous_action(a->c,
20021c1c48aSSascha Wildner 	    _("WARNING!  ALL data in ALL partitions on the disk\n\n"
20121c1c48aSSascha Wildner 	    "%s\n\nwill be IRREVOCABLY ERASED!\n\nAre you ABSOLUTELY "
20221c1c48aSSascha Wildner 	    "SURE you wish to take this action?  This is your "
20321c1c48aSSascha Wildner 	    "LAST CHANCE to cancel!"), disk_get_desc(storage_get_selected_disk(a->s)))) {
20421c1c48aSSascha Wildner 		cmds = commands_new();
20521c1c48aSSascha Wildner 
20621c1c48aSSascha Wildner 		command_add(cmds, "%s%s -BI %s",
20721c1c48aSSascha Wildner 		    a->os_root, cmd_name(a, "FDISK"),
208f59b7dfaSSascha Wildner 		    disk_get_device_name(storage_get_selected_disk(a->s)));
20921c1c48aSSascha Wildner 
21021c1c48aSSascha Wildner 		if (!commands_execute(a, cmds)) {
21121c1c48aSSascha Wildner 			inform(a->c, _("The disk\n\n%s\n\nwas "
21221c1c48aSSascha Wildner 			    "not correctly formatted, and may "
21321c1c48aSSascha Wildner 			    "now be in an inconsistent state. "
21421c1c48aSSascha Wildner 			    "We recommend re-formatting it "
21521c1c48aSSascha Wildner 			    "before attempting to install "
21621c1c48aSSascha Wildner 			    "%s on it."),
21721c1c48aSSascha Wildner 			    disk_get_desc(storage_get_selected_disk(a->s)),
21821c1c48aSSascha Wildner 			    OPERATING_SYSTEM_NAME);
21921c1c48aSSascha Wildner 			commands_free(cmds);
22021c1c48aSSascha Wildner 			a->result = 0;
22121c1c48aSSascha Wildner 			return;
22221c1c48aSSascha Wildner 		}
22321c1c48aSSascha Wildner 		commands_free(cmds);
22421c1c48aSSascha Wildner 
22521c1c48aSSascha Wildner 		/*
22621c1c48aSSascha Wildner 		 * Since one of the disks has now changed, we must
22721c1c48aSSascha Wildner 		 * refresh our view of them and re-select the disk
22821c1c48aSSascha Wildner 		 * since the selected_disk pointer will be invalidated.
22921c1c48aSSascha Wildner 		 */
23021c1c48aSSascha Wildner 		selected_disk_string = aura_strdup(
23121c1c48aSSascha Wildner 		    disk_get_device_name(storage_get_selected_disk(a->s)));
23221c1c48aSSascha Wildner 		if (!survey_storage(a)) {
23321c1c48aSSascha Wildner 			inform(a->c, _("Errors occurred while probing "
23421c1c48aSSascha Wildner 			    "the system for its storage capabilities."));
23521c1c48aSSascha Wildner 		}
23621c1c48aSSascha Wildner 		storage_set_selected_disk(a->s, disk_find(a->s, selected_disk_string));
23721c1c48aSSascha Wildner 		free(selected_disk_string);
23821c1c48aSSascha Wildner 
23921c1c48aSSascha Wildner 		/*
24021c1c48aSSascha Wildner 		 * Note that we formatted this disk and that we want
24121c1c48aSSascha Wildner 		 * to use the first (and only) slice of it.
24221c1c48aSSascha Wildner 		 */
24321c1c48aSSascha Wildner 		disk_set_formatted(storage_get_selected_disk(a->s), 1);
24421c1c48aSSascha Wildner 		storage_set_selected_slice(a->s, disk_slice_first(storage_get_selected_disk(a->s)));
24521c1c48aSSascha Wildner 
24621c1c48aSSascha Wildner 		if (!format_slice(a)) {
24721c1c48aSSascha Wildner 			inform(a->c, _("The sole primary partition of "
24821c1c48aSSascha Wildner 			    "the disk\n\n%s\n\nwas "
24921c1c48aSSascha Wildner 			    "not correctly formatted, and may "
25021c1c48aSSascha Wildner 			    "now be in an inconsistent state. "
25121c1c48aSSascha Wildner 			    "We recommend re-formatting the "
25221c1c48aSSascha Wildner 			    "disk before attempting to install "
25321c1c48aSSascha Wildner 			    "%s on it."),
25421c1c48aSSascha Wildner 			    disk_get_desc(storage_get_selected_disk(a->s)),
25521c1c48aSSascha Wildner 			    OPERATING_SYSTEM_NAME);
25621c1c48aSSascha Wildner 			a->result = 0;
25721c1c48aSSascha Wildner 			return;
25821c1c48aSSascha Wildner 		}
25921c1c48aSSascha Wildner 
26021c1c48aSSascha Wildner 		inform(a->c, _("The disk\n\n%s\n\nwas formatted."),
26121c1c48aSSascha Wildner 		    disk_get_desc(storage_get_selected_disk(a->s)));
26221c1c48aSSascha Wildner 		a->result = 1;
26321c1c48aSSascha Wildner 	} else {
26421c1c48aSSascha Wildner 		inform(a->c, _("Action cancelled - no disks were formatted."));
26521c1c48aSSascha Wildner 		a->result = 0;
26621c1c48aSSascha Wildner 	}
26721c1c48aSSascha Wildner }
26821c1c48aSSascha Wildner 
26921c1c48aSSascha Wildner /*
27021c1c48aSSascha Wildner  * Wipes the start of the selected disk.
27121c1c48aSSascha Wildner  */
27221c1c48aSSascha Wildner void
27321c1c48aSSascha Wildner fn_wipe_start_of_disk(struct i_fn_args *a)
27421c1c48aSSascha Wildner {
27521c1c48aSSascha Wildner 	struct commands *cmds;
27621c1c48aSSascha Wildner 
27721c1c48aSSascha Wildner 	a->short_desc = _("If you are having problems formatting a disk, "
27821c1c48aSSascha Wildner 	    "it may be because of junk that has accumulated "
27921c1c48aSSascha Wildner 	    "in the boot block and the partition table. "
28021c1c48aSSascha Wildner 	    "A cure for this is to wipe out everything on "
28121c1c48aSSascha Wildner 	    "the first few sectors of the disk.  However, this "
28221c1c48aSSascha Wildner 	    "is a rather drastic action to take, so it is not "
28321c1c48aSSascha Wildner 	    "recommended unless you are otherwise "
28421c1c48aSSascha Wildner 	    "encountering problems.");
28521c1c48aSSascha Wildner 	a->cancel_desc = _("Return to Utilities Menu");
28621c1c48aSSascha Wildner 	fn_select_disk(a);
28721c1c48aSSascha Wildner 	if (!a->result)
28821c1c48aSSascha Wildner 		return;
28921c1c48aSSascha Wildner 
29021c1c48aSSascha Wildner 	/* XXX check to make sure no slices on this disk are mounted first? */
29121c1c48aSSascha Wildner 	if (storage_get_selected_disk(a->s) != NULL && confirm_dangerous_action(a->c,
29221c1c48aSSascha Wildner 	    _("WARNING!  ALL data in ALL partitions on the disk\n\n"
29321c1c48aSSascha Wildner 	    "%s\n\nwill be IRREVOCABLY ERASED!\n\nAre you ABSOLUTELY "
29421c1c48aSSascha Wildner 	    "SURE you wish to take this action?  This is your "
29521c1c48aSSascha Wildner 	    "LAST CHANCE to cancel!"), disk_get_desc(storage_get_selected_disk(a->s)))) {
29621c1c48aSSascha Wildner 		cmds = commands_new();
29721c1c48aSSascha Wildner 		command_add(cmds,
29821c1c48aSSascha Wildner 		    "%s%s if=%sdev/zero of=%sdev/%s bs=32k count=16",
29921c1c48aSSascha Wildner 		    a->os_root, cmd_name(a, "DD"),
30021c1c48aSSascha Wildner 		    a->os_root, a->os_root,
301f59b7dfaSSascha Wildner 		    disk_get_device_name(storage_get_selected_disk(a->s)));
30221c1c48aSSascha Wildner 		if (commands_execute(a, cmds)) {
30321c1c48aSSascha Wildner 			inform(a->c, _("Start of disk was successfully wiped."));
30421c1c48aSSascha Wildner 		} else {
30521c1c48aSSascha Wildner 			inform(a->c, _("Some errors occurred. "
30621c1c48aSSascha Wildner 			    "Start of disk was not successfully wiped."));
30721c1c48aSSascha Wildner 		}
30821c1c48aSSascha Wildner 		commands_free(cmds);
30921c1c48aSSascha Wildner 	}
31021c1c48aSSascha Wildner }
31121c1c48aSSascha Wildner 
31221c1c48aSSascha Wildner /*
31321c1c48aSSascha Wildner  * Wipes the start of the selected slice.
31421c1c48aSSascha Wildner  */
31521c1c48aSSascha Wildner void
31621c1c48aSSascha Wildner fn_wipe_start_of_slice(struct i_fn_args *a)
31721c1c48aSSascha Wildner {
31821c1c48aSSascha Wildner 	struct commands *cmds;
31921c1c48aSSascha Wildner 
32021c1c48aSSascha Wildner 	a->short_desc =
32121c1c48aSSascha Wildner 	  _("If you are having problems formatting a primary partition, "
32221c1c48aSSascha Wildner 	    "it may be because of junk that has accumulated in the "
32321c1c48aSSascha Wildner 	    "partition's `disklabel'. A cure for this is to wipe out "
32421c1c48aSSascha Wildner 	    "everything on the first few sectors of the primary partition. "
32521c1c48aSSascha Wildner 	    "However, this is a rather drastic action to take, so it is not "
32621c1c48aSSascha Wildner 	    "recommended unless you are otherwise encountering problems.");
32721c1c48aSSascha Wildner 	a->cancel_desc = _("Return to Utilities Menu");
32821c1c48aSSascha Wildner 	fn_select_slice(a);
32921c1c48aSSascha Wildner 	if (!a->result)
33021c1c48aSSascha Wildner 		return;
33121c1c48aSSascha Wildner 
33221c1c48aSSascha Wildner 	if (confirm_dangerous_action(a->c,
33321c1c48aSSascha Wildner 	    _("WARNING!  ALL data in primary partition #%d,\n\n%s\n\non the "
33421c1c48aSSascha Wildner 	    "disk\n\n%s\n\n will be IRREVOCABLY ERASED!\n\nAre you "
33521c1c48aSSascha Wildner 	    "ABSOLUTELY SURE you wish to take this action?  This is "
33621c1c48aSSascha Wildner 	    "your LAST CHANCE to cancel!"),
33721c1c48aSSascha Wildner 	    slice_get_number(storage_get_selected_slice(a->s)),
33821c1c48aSSascha Wildner 	    slice_get_desc(storage_get_selected_slice(a->s)),
33921c1c48aSSascha Wildner 	    disk_get_desc(storage_get_selected_disk(a->s)))) {
34021c1c48aSSascha Wildner 		/* XXX check to make sure this slice is not mounted first */
34121c1c48aSSascha Wildner 		cmds = commands_new();
34221c1c48aSSascha Wildner 		command_add(cmds, "%s%s if=%sdev/zero of=%sdev/%s bs=32k count=16",
34321c1c48aSSascha Wildner 		    a->os_root, cmd_name(a, "DD"),
34421c1c48aSSascha Wildner 		    a->os_root, a->os_root,
345f59b7dfaSSascha Wildner 		    slice_get_device_name(storage_get_selected_slice(a->s)));
34621c1c48aSSascha Wildner 		if (commands_execute(a, cmds)) {
34721c1c48aSSascha Wildner 			inform(a->c, _("Start of primary partition was successfully wiped."));
34821c1c48aSSascha Wildner 		} else {
34921c1c48aSSascha Wildner 			inform(a->c, _("Some errors occurred. "
35021c1c48aSSascha Wildner 			    "Start of primary partition was not successfully wiped."));
35121c1c48aSSascha Wildner 		}
35221c1c48aSSascha Wildner 		commands_free(cmds);
35321c1c48aSSascha Wildner 	}
35421c1c48aSSascha Wildner }
35521c1c48aSSascha Wildner 
35621c1c48aSSascha Wildner static void
35721c1c48aSSascha Wildner ask_to_wipe_boot_sector(struct i_fn_args *a, struct commands *fcmds)
35821c1c48aSSascha Wildner {
35921c1c48aSSascha Wildner 	struct commands *cmds;
36021c1c48aSSascha Wildner 	struct command *cmd;
36121c1c48aSSascha Wildner 	char *disk;
36221c1c48aSSascha Wildner 
36321c1c48aSSascha Wildner 	for (cmd = command_get_first(fcmds); cmd != NULL;
36421c1c48aSSascha Wildner 	     cmd = command_get_next(cmd)) {
36521c1c48aSSascha Wildner 		disk = command_get_tag(cmd);
36621c1c48aSSascha Wildner 		if (disk != NULL &&
36721c1c48aSSascha Wildner 		    command_get_result(cmd) > 0 &&
36821c1c48aSSascha Wildner 		    command_get_result(cmd) < 256) {
36921c1c48aSSascha Wildner 			switch (dfui_be_present_dialog(a->c,
37021c1c48aSSascha Wildner 			    _("Bootblock Install Failed"),
37121c1c48aSSascha Wildner 			    _("Re-Initialize Bootblock|Cancel"),
37221c1c48aSSascha Wildner 			    _("Warning: bootblocks were not successfully "
37321c1c48aSSascha Wildner 			    "installed on the disk `%s'. This may be "
37421c1c48aSSascha Wildner 			    "because the disk is new and not yet "
37521c1c48aSSascha Wildner 			    "formatted. If this is the case, it might "
37621c1c48aSSascha Wildner 			    "help to re-initialize the boot sector, "
37721c1c48aSSascha Wildner 			    "then try installing the bootblock again. "
37821c1c48aSSascha Wildner 			    "Note that this should not affect the "
37921c1c48aSSascha Wildner 			    "partition table of the disk."),
38059b733d3SSascha Wildner 			    disk)) {
38121c1c48aSSascha Wildner 			case 1:
38221c1c48aSSascha Wildner 				cmds = commands_new();
38321c1c48aSSascha Wildner 				command_add(cmds,
38421c1c48aSSascha Wildner 				    "%s%s | %s%s -B %sdev/%s",
38521c1c48aSSascha Wildner 				    a->os_root, cmd_name(a, "YES"),
38621c1c48aSSascha Wildner 				    a->os_root, cmd_name(a, "FDISK"),
38721c1c48aSSascha Wildner 				    a->os_root, disk);
38821c1c48aSSascha Wildner 				if (commands_execute(a, cmds)) {
38921c1c48aSSascha Wildner 					inform(a->c, _("Boot sector successfully initialized."));
39021c1c48aSSascha Wildner 				} else {
39121c1c48aSSascha Wildner 					inform(a->c, _("Some errors occurred. "
39221c1c48aSSascha Wildner 					    "Boot sector was not successfully initialized."));
39321c1c48aSSascha Wildner 				}
39421c1c48aSSascha Wildner 				commands_free(cmds);
39521c1c48aSSascha Wildner 				break;
39621c1c48aSSascha Wildner 			default:
39721c1c48aSSascha Wildner 				break;
39821c1c48aSSascha Wildner 			}
39921c1c48aSSascha Wildner 		}
40021c1c48aSSascha Wildner 	}
40121c1c48aSSascha Wildner }
40221c1c48aSSascha Wildner 
40321c1c48aSSascha Wildner void
404e75c9034SSascha Wildner fn_install_bootblocks(struct i_fn_args *a, const char *device)
40521c1c48aSSascha Wildner {
40621c1c48aSSascha Wildner 	struct dfui_form *f;
40721c1c48aSSascha Wildner 	struct dfui_response *r;
40821c1c48aSSascha Wildner 	struct dfui_dataset *ds;
40921c1c48aSSascha Wildner 	struct disk *d;
41021c1c48aSSascha Wildner 	struct commands *cmds;
41121c1c48aSSascha Wildner 	struct command *cmd;
41221c1c48aSSascha Wildner 	char disk[64], boot0cfg[32], packet[32];
41321c1c48aSSascha Wildner 	char msg_buf[1][1024];
41421c1c48aSSascha Wildner 
41521c1c48aSSascha Wildner 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
41621c1c48aSSascha Wildner 	    "'Packet Mode' refers to using newer BIOS calls to boot "
41721c1c48aSSascha Wildner 	    "from a partition of the disk.  It is generally not "
41821c1c48aSSascha Wildner 	    "required unless:\n\n"
41921c1c48aSSascha Wildner 	    "- your BIOS does not support legacy mode; or\n"
42021c1c48aSSascha Wildner 	    "- your %s primary partition resides on a "
42121c1c48aSSascha Wildner 	    "cylinder of the disk beyond cylinder 1024; or\n"
42221c1c48aSSascha Wildner 	    "- you just can't get it to boot without it.",
42321c1c48aSSascha Wildner 	    OPERATING_SYSTEM_NAME);
42421c1c48aSSascha Wildner 
42521c1c48aSSascha Wildner 	f = dfui_form_create(
42621c1c48aSSascha Wildner 	    "install_bootstrap",
42721c1c48aSSascha Wildner 	    _("Install Bootblock(s)"),
42821c1c48aSSascha Wildner 	    a->short_desc,
42921c1c48aSSascha Wildner 
43021c1c48aSSascha Wildner 	    msg_buf[0],
43121c1c48aSSascha Wildner 
43221c1c48aSSascha Wildner 	    "p", "special", "dfinstaller_install_bootstrap",
43321c1c48aSSascha Wildner 
43421c1c48aSSascha Wildner 	    "f", "disk", _("Disk Drive"),
43521c1c48aSSascha Wildner 	    _("The disk on which you wish to install a bootblock"), "",
43621c1c48aSSascha Wildner 	    "p", "editable", "false",
43721c1c48aSSascha Wildner 	    "f", "boot0cfg", _("Install Bootblock?"),
43821c1c48aSSascha Wildner 	    _("Install a bootblock on this disk"), "",
43921c1c48aSSascha Wildner 	    "p", "control", "checkbox",
44021c1c48aSSascha Wildner 	    "f", "packet", _("Packet Mode?"),
44121c1c48aSSascha Wildner 	    _("Select this to use 'packet mode' to boot the disk"), "",
44221c1c48aSSascha Wildner 	    "p", "control", "checkbox",
44321c1c48aSSascha Wildner 
44421c1c48aSSascha Wildner 	    "a", "ok", _("Accept and Install Bootblocks"), "", "",
44521c1c48aSSascha Wildner 	    "a", "cancel", a->cancel_desc, "", "",
44621c1c48aSSascha Wildner 	    "p", "accelerator", "ESC",
44721c1c48aSSascha Wildner 
44821c1c48aSSascha Wildner 	    NULL
44921c1c48aSSascha Wildner 	);
45021c1c48aSSascha Wildner 
45121c1c48aSSascha Wildner 	dfui_form_set_multiple(f, 1);
45221c1c48aSSascha Wildner 
453e75c9034SSascha Wildner 	if (device != NULL) {
45421c1c48aSSascha Wildner 		ds = dfui_dataset_new();
455e75c9034SSascha Wildner 		dfui_dataset_celldata_add(ds, "disk", device);
45621c1c48aSSascha Wildner 		dfui_dataset_celldata_add(ds, "boot0cfg", "Y");
45721c1c48aSSascha Wildner 		dfui_dataset_celldata_add(ds, "packet", "Y");
45821c1c48aSSascha Wildner 		dfui_form_dataset_add(f, ds);
459e75c9034SSascha Wildner 	} else {
460e75c9034SSascha Wildner 		for (d = storage_disk_first(a->s); d != NULL; d = disk_next(d)) {
461e75c9034SSascha Wildner 			ds = dfui_dataset_new();
462e75c9034SSascha Wildner 			dfui_dataset_celldata_add(ds, "disk",
463e75c9034SSascha Wildner 			    disk_get_device_name(d));
464e75c9034SSascha Wildner 			dfui_dataset_celldata_add(ds, "boot0cfg", "Y");
465e75c9034SSascha Wildner 			dfui_dataset_celldata_add(ds, "packet", "Y");
466e75c9034SSascha Wildner 			dfui_form_dataset_add(f, ds);
467e75c9034SSascha Wildner 		}
46821c1c48aSSascha Wildner 	}
46921c1c48aSSascha Wildner 
47021c1c48aSSascha Wildner 	if (!dfui_be_present(a->c, f, &r))
47121c1c48aSSascha Wildner 		abort_backend();
47221c1c48aSSascha Wildner 
47321c1c48aSSascha Wildner 	a->result = 0;
47421c1c48aSSascha Wildner 	if (strcmp(dfui_response_get_action_id(r), "ok") == 0) {
47521c1c48aSSascha Wildner 		cmds = commands_new();
47621c1c48aSSascha Wildner 
47721c1c48aSSascha Wildner 		for (ds = dfui_response_dataset_get_first(r); ds != NULL;
47821c1c48aSSascha Wildner 		     ds = dfui_dataset_get_next(ds)) {
47921c1c48aSSascha Wildner 			strlcpy(disk, dfui_dataset_get_value(ds, "disk"), 64);
48021c1c48aSSascha Wildner 			strlcpy(boot0cfg, dfui_dataset_get_value(ds, "boot0cfg"), 32);
48121c1c48aSSascha Wildner 			strlcpy(packet, dfui_dataset_get_value(ds, "packet"), 32);
48221c1c48aSSascha Wildner 
48321c1c48aSSascha Wildner 			if (strcasecmp(boot0cfg, "Y") == 0) {
48421c1c48aSSascha Wildner 				cmd = command_add(cmds, "%s%s -B -o %spacket %s",
48521c1c48aSSascha Wildner 				    a->os_root, cmd_name(a, "BOOT0CFG"),
48621c1c48aSSascha Wildner 				    strcasecmp(packet, "Y") == 0 ? "" : "no",
48721c1c48aSSascha Wildner 				    disk);
48821c1c48aSSascha Wildner 				command_set_failure_mode(cmd, COMMAND_FAILURE_WARN);
48921c1c48aSSascha Wildner 				command_set_tag(cmd, disk);
49021c1c48aSSascha Wildner 				cmd = command_add(cmds, "%s%s -v %s",
49121c1c48aSSascha Wildner 				    a->os_root, cmd_name(a, "BOOT0CFG"),
49221c1c48aSSascha Wildner 				    disk);
49321c1c48aSSascha Wildner 				command_set_failure_mode(cmd, COMMAND_FAILURE_WARN);
49421c1c48aSSascha Wildner 				command_set_tag(cmd, disk);
49521c1c48aSSascha Wildner 			}
49621c1c48aSSascha Wildner 		}
49721c1c48aSSascha Wildner 
49821c1c48aSSascha Wildner 		if (!commands_execute(a, cmds)) {
49921c1c48aSSascha Wildner 			ask_to_wipe_boot_sector(a, cmds);
50021c1c48aSSascha Wildner 		} else {
50121c1c48aSSascha Wildner 			inform(a->c, _("Bootblocks were successfully installed!"));
50221c1c48aSSascha Wildner 			a->result = 1;
50321c1c48aSSascha Wildner 		}
50421c1c48aSSascha Wildner 		commands_free(cmds);
50521c1c48aSSascha Wildner 	}
50621c1c48aSSascha Wildner 
50721c1c48aSSascha Wildner 	dfui_form_free(f);
50821c1c48aSSascha Wildner 	dfui_response_free(r);
50921c1c48aSSascha Wildner }
51021c1c48aSSascha Wildner 
51121c1c48aSSascha Wildner void
51221c1c48aSSascha Wildner fn_format_msdos_floppy(struct i_fn_args *a)
51321c1c48aSSascha Wildner {
51421c1c48aSSascha Wildner 	struct commands *cmds;
51521c1c48aSSascha Wildner 
51621c1c48aSSascha Wildner 	switch (dfui_be_present_dialog(a->c, _("Format MSDOS Floppy"),
51721c1c48aSSascha Wildner 	    _("Format Floppy|Return to Utilities Menu"),
51821c1c48aSSascha Wildner 	    _("Please insert the floppy to be formatted "
51921c1c48aSSascha Wildner 	    "in unit 0 (``drive A:'')."))) {
52021c1c48aSSascha Wildner 	case 1:
52121c1c48aSSascha Wildner 		cmds = commands_new();
52221c1c48aSSascha Wildner 		command_add(cmds, "%s%s -y -f 1440 /dev/fd0",
52321c1c48aSSascha Wildner 		    a->os_root, cmd_name(a, "FDFORMAT"));
52421c1c48aSSascha Wildner 		command_add(cmds, "%s%s -f 1440 fd0",
52521c1c48aSSascha Wildner 		    a->os_root, cmd_name(a, "NEWFS_MSDOS"));
52621c1c48aSSascha Wildner 		if (commands_execute(a, cmds))
52721c1c48aSSascha Wildner 			inform(a->c, _("Floppy successfully formatted!"));
52821c1c48aSSascha Wildner 		else
52921c1c48aSSascha Wildner 			inform(a->c, _("Floppy was not successfully formatted."));
53021c1c48aSSascha Wildner 		break;
53121c1c48aSSascha Wildner 	case 2:
53221c1c48aSSascha Wildner 		return;
53321c1c48aSSascha Wildner 	default:
53421c1c48aSSascha Wildner 		abort_backend();
53521c1c48aSSascha Wildner 	}
53621c1c48aSSascha Wildner }
53721c1c48aSSascha Wildner 
53821c1c48aSSascha Wildner void
53921c1c48aSSascha Wildner fn_create_cdboot_floppy(struct i_fn_args *a)
54021c1c48aSSascha Wildner {
54121c1c48aSSascha Wildner 	struct commands *cmds;
54221c1c48aSSascha Wildner 	char msg_buf[1][1024];
54321c1c48aSSascha Wildner 
54421c1c48aSSascha Wildner 	snprintf(msg_buf[0], sizeof(msg_buf[0]),
54521c1c48aSSascha Wildner 	    "%s cannot be installed from a floppy; "
54621c1c48aSSascha Wildner 	    "it must be installed from a booted CD-ROM. "
54721c1c48aSSascha Wildner 	    "However, many older systems do not support booting "
54821c1c48aSSascha Wildner 	    "from a CD-ROM. For these systems, a boot disk can be "
54921c1c48aSSascha Wildner 	    "created. This boot disk contains the Smart Boot "
55021c1c48aSSascha Wildner 	    "Manager program, which can boot a CD-ROM even "
55121c1c48aSSascha Wildner 	    "on systems with BIOSes which do not support booting "
55221c1c48aSSascha Wildner 	    "from the CD-ROM.\n\n"
55321c1c48aSSascha Wildner 	    "Smart Boot Manager is not a part of %s; "
55421c1c48aSSascha Wildner 	    "the Smart Boot Manager project can be found here:\n\n"
55521c1c48aSSascha Wildner 	    "http://btmgr.sourceforge.net/\n\n"
55621c1c48aSSascha Wildner 	    "To create a CDBoot floppy, insert a blank floppy "
55721c1c48aSSascha Wildner 	    "in unit 0 (``drive A:'') before proceeding."
55821c1c48aSSascha Wildner 	    "",
55921c1c48aSSascha Wildner 	    OPERATING_SYSTEM_NAME, OPERATING_SYSTEM_NAME);
56021c1c48aSSascha Wildner 
56121c1c48aSSascha Wildner 	switch (dfui_be_present_dialog(a->c, _("Create CDBoot Floppy"),
56221c1c48aSSascha Wildner 	    _("Create CDBoot Floppy|Return to Utilities Menu"),
56321c1c48aSSascha Wildner 	    msg_buf[0])) {
56421c1c48aSSascha Wildner 	case 1:
56521c1c48aSSascha Wildner 		cmds = commands_new();
56621c1c48aSSascha Wildner 		command_add(cmds, "%s%s -c %sboot/cdboot.flp.bz2 | "
56721c1c48aSSascha Wildner 		    "%s%s of=%sdev/fd0 bs=32k",
56821c1c48aSSascha Wildner 		    a->os_root, cmd_name(a, "BUNZIP2"),
56921c1c48aSSascha Wildner 		    a->os_root,
57021c1c48aSSascha Wildner 		    a->os_root, cmd_name(a, "DD"),
57121c1c48aSSascha Wildner 		    a->os_root);
57221c1c48aSSascha Wildner 		if (commands_execute(a, cmds))
57321c1c48aSSascha Wildner 			inform(a->c, _("CDBoot floppy successfully created!"));
57421c1c48aSSascha Wildner 		else
57521c1c48aSSascha Wildner 			inform(a->c, _("CDBoot floppy was not successfully created."));
57621c1c48aSSascha Wildner 		break;
57721c1c48aSSascha Wildner 	case 2:
57821c1c48aSSascha Wildner 		return;
57921c1c48aSSascha Wildner 	default:
58021c1c48aSSascha Wildner 		abort_backend();
58121c1c48aSSascha Wildner 	}
58221c1c48aSSascha Wildner }
58321c1c48aSSascha Wildner 
58421c1c48aSSascha Wildner /**** NON-fn_ FUNCTIONS ***/
58521c1c48aSSascha Wildner 
58621c1c48aSSascha Wildner int
58721c1c48aSSascha Wildner format_slice(struct i_fn_args *a)
58821c1c48aSSascha Wildner {
58921c1c48aSSascha Wildner 	struct commands *cmds;
590*a096577dSSascha Wildner 	struct command *cmd;
59121c1c48aSSascha Wildner 	int result;
59221c1c48aSSascha Wildner 	int cyl, hd, sec;
59321c1c48aSSascha Wildner 
59421c1c48aSSascha Wildner 	cmds = commands_new();
59521c1c48aSSascha Wildner 
59621c1c48aSSascha Wildner 	/*
59721c1c48aSSascha Wildner 	 * The information in a->s NEEDS to be accurate here!
59821c1c48aSSascha Wildner 	 * Presumably we just did a survey_storage() recently.
59921c1c48aSSascha Wildner 	 * XXX should we do another one here anyway just to be paranoid?
60021c1c48aSSascha Wildner 	 */
60121c1c48aSSascha Wildner 
60221c1c48aSSascha Wildner 	/*
60321c1c48aSSascha Wildner 	 * Set the slice's sysid to 165.
60421c1c48aSSascha Wildner 	 */
60521c1c48aSSascha Wildner 	disk_get_geometry(storage_get_selected_disk(a->s), &cyl, &hd, &sec);
60621c1c48aSSascha Wildner 	command_add(cmds, "%s%s 'g c%d h%d s%d' >%snew.fdisk",
60721c1c48aSSascha Wildner 	    a->os_root, cmd_name(a, "ECHO"),
60821c1c48aSSascha Wildner 	    cyl, hd, sec,
60921c1c48aSSascha Wildner 	    a->tmp);
61021c1c48aSSascha Wildner 	command_add(cmds, "%s%s 'p %d %d %lu %lu' >>%snew.fdisk",
61121c1c48aSSascha Wildner 	    a->os_root, cmd_name(a, "ECHO"),
61221c1c48aSSascha Wildner 	    slice_get_number(storage_get_selected_slice(a->s)),
61321c1c48aSSascha Wildner 	    165,
61421c1c48aSSascha Wildner 	    slice_get_start(storage_get_selected_slice(a->s)),
61521c1c48aSSascha Wildner 	    slice_get_size(storage_get_selected_slice(a->s)),
61621c1c48aSSascha Wildner 	    a->tmp);
61721c1c48aSSascha Wildner 	if (slice_get_flags(storage_get_selected_slice(a->s)) & 0x80) {
61821c1c48aSSascha Wildner 		command_add(cmds, "%s%s 'a %d' >>%snew.fdisk",
61921c1c48aSSascha Wildner 		    a->os_root, cmd_name(a, "ECHO"),
62021c1c48aSSascha Wildner 		    slice_get_number(storage_get_selected_slice(a->s)),
62121c1c48aSSascha Wildner 		    a->tmp);
62221c1c48aSSascha Wildner 	}
62321c1c48aSSascha Wildner 
62421c1c48aSSascha Wildner 	command_add(cmds, "%s%s %snew.fdisk",
62521c1c48aSSascha Wildner 	    a->os_root, cmd_name(a, "CAT"), a->tmp);
62621c1c48aSSascha Wildner 	temp_file_add(a, "new.fdisk");
62721c1c48aSSascha Wildner 
62821c1c48aSSascha Wildner 	/*
62921c1c48aSSascha Wildner 	 * Execute the fdisk script.
63021c1c48aSSascha Wildner 	 */
631*a096577dSSascha Wildner 	cmd = command_add(cmds, "%s%s -v -f %snew.fdisk %s",
63221c1c48aSSascha Wildner 	    a->os_root, cmd_name(a, "FDISK"), a->tmp,
633f59b7dfaSSascha Wildner 	    disk_get_device_name(storage_get_selected_disk(a->s)));
634*a096577dSSascha Wildner 	if (slice_get_size(storage_get_selected_slice(a->s)) == 0xFFFFFFFFU)
635*a096577dSSascha Wildner 		command_set_failure_mode(cmd, COMMAND_FAILURE_IGNORE);
63621c1c48aSSascha Wildner 
63721c1c48aSSascha Wildner 	/*
63821c1c48aSSascha Wildner 	 * If there is an old 'virgin' disklabel hanging around
63921c1c48aSSascha Wildner 	 * in the temp dir, get rid of it.  This won't happen
64021c1c48aSSascha Wildner 	 * from a real CD, but might happen with '-o' installs.
64121c1c48aSSascha Wildner 	 */
64221c1c48aSSascha Wildner 	command_add(cmds, "%s%s -f %sinstall.disklabel.%s",
64321c1c48aSSascha Wildner 	    a->os_root, cmd_name(a, "RM"),
64421c1c48aSSascha Wildner 	    a->tmp,
64521c1c48aSSascha Wildner 	    slice_get_device_name(storage_get_selected_slice(a->s)));
64621c1c48aSSascha Wildner 
64721c1c48aSSascha Wildner 	result = commands_execute(a, cmds);
64821c1c48aSSascha Wildner 
64921c1c48aSSascha Wildner 	commands_free(cmds);
65021c1c48aSSascha Wildner 
65121c1c48aSSascha Wildner 	return(result);
65221c1c48aSSascha Wildner }
653