disks.c revision 18683
1232958Sbschmidt/*
2232958Sbschmidt * The new sysinstall program.
3232958Sbschmidt *
4232958Sbschmidt * This is probably the last program in the `sysinstall' line - the next
5232958Sbschmidt * generation being essentially a complete rewrite.
6232958Sbschmidt *
7232958Sbschmidt * $Id: disks.c,v 1.66 1996/10/03 06:01:31 jkh Exp $
8232958Sbschmidt *
9232958Sbschmidt * Copyright (c) 1995
10232958Sbschmidt *	Jordan Hubbard.  All rights reserved.
11232958Sbschmidt *
12232958Sbschmidt * Redistribution and use in source and binary forms, with or without
13232958Sbschmidt * modification, are permitted provided that the following conditions
14232958Sbschmidt * are met:
15232958Sbschmidt * 1. Redistributions of source code must retain the above copyright
16232958Sbschmidt *    notice, this list of conditions and the following disclaimer,
17232958Sbschmidt *    verbatim and that no modifications are made prior to this
18232958Sbschmidt *    point in the file.
19232958Sbschmidt * 2. Redistributions in binary form must reproduce the above copyright
20232958Sbschmidt *    notice, this list of conditions and the following disclaimer in the
21232958Sbschmidt *    documentation and/or other materials provided with the distribution.
22232958Sbschmidt *
23232958Sbschmidt * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
24232958Sbschmidt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25232958Sbschmidt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26232958Sbschmidt * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
27232958Sbschmidt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28232958Sbschmidt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29232958Sbschmidt * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
30232958Sbschmidt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31232958Sbschmidt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32232958Sbschmidt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33232958Sbschmidt * SUCH DAMAGE.
34232958Sbschmidt *
35232958Sbschmidt */
36232958Sbschmidt
37232958Sbschmidt#include "sysinstall.h"
38232958Sbschmidt#include <ctype.h>
39232958Sbschmidt#include <sys/disklabel.h>
40232958Sbschmidt
41232958Sbschmidt/* Where we start displaying chunk information on the screen */
42232958Sbschmidt#define CHUNK_START_ROW		5
43232958Sbschmidt
44232958Sbschmidt/* Where we keep track of MBR chunks */
45232958Sbschmidtstatic struct chunk *chunk_info[16];
46232958Sbschmidtstatic int current_chunk;
47232958Sbschmidt
48232958Sbschmidtstatic void
49232958Sbschmidtrecord_chunks(Disk *d)
50232958Sbschmidt{
51232958Sbschmidt    struct chunk *c1 = NULL;
52232958Sbschmidt    int i = 0;
53232958Sbschmidt    int last_free = 0;
54232958Sbschmidt
55232958Sbschmidt    if (!d->chunks)
56232958Sbschmidt	msgFatal("No chunk list found for %s!", d->name);
57232958Sbschmidt
58232958Sbschmidt    for (c1 = d->chunks->part; c1; c1 = c1->next) {
59232958Sbschmidt	if (c1->type == unused && c1->size > last_free) {
60232958Sbschmidt	    last_free = c1->size;
61232958Sbschmidt	    current_chunk = i;
62232958Sbschmidt	}
63232958Sbschmidt	chunk_info[i++] = c1;
64232958Sbschmidt    }
65232958Sbschmidt    chunk_info[i] = NULL;
66232958Sbschmidt}
67232958Sbschmidt
68232958Sbschmidtstatic void
69232958Sbschmidtprint_chunks(Disk *d)
70232958Sbschmidt{
71232958Sbschmidt    int row;
72232958Sbschmidt    int i, sz;
73232958Sbschmidt
74232958Sbschmidt    for (i = sz = 0; chunk_info[i]; i++)
75232958Sbschmidt	sz += chunk_info[i]->size;
76232958Sbschmidt    if (d->bios_hd <= 1 && d->bios_sect <= 1) {
77232958Sbschmidt	All_FreeBSD(d, TRUE);
78232958Sbschmidt	d->bios_hd = d->bios_sect = d->bios_cyl = 1;
79232958Sbschmidt    }
80232958Sbschmidt    else if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) {
81232958Sbschmidt	dialog_clear_norefresh();
82232958Sbschmidt	msgConfirm("WARNING:  A geometry of %d/%d/%d for %s is incorrect.  Using\n"
83232958Sbschmidt		   "a default geometry of 64 heads and 32 sectors.  If this geometry\n"
84232958Sbschmidt		   "is incorrect or you are unsure as to whether or not it's correct,\n"
85232958Sbschmidt		   "please consult the Hardware Guide in the Documentation submenu\n"
86232958Sbschmidt		   "or use the (G)eometry command to change it now.", d->bios_cyl, d->bios_hd, d->bios_sect, d->name);
87232958Sbschmidt	d->bios_hd = 64;
88232958Sbschmidt	d->bios_sect = 32;
89232958Sbschmidt	d->bios_cyl = sz / ONE_MEG;
90232958Sbschmidt    }
91232958Sbschmidt    attrset(A_NORMAL);
92232958Sbschmidt    mvaddstr(0, 0, "Disk name:\t");
93232958Sbschmidt    clrtobot();
94232958Sbschmidt    attrset(A_REVERSE); addstr(d->name); attrset(A_NORMAL);
95232958Sbschmidt    attrset(A_REVERSE); mvaddstr(0, 55, "FDISK Partition Editor"); attrset(A_NORMAL);
96232958Sbschmidt    mvprintw(1, 0,
97232958Sbschmidt	     "DISK Geometry:\t%lu cyls/%lu heads/%lu sectors",
98232958Sbschmidt	     d->bios_cyl, d->bios_hd, d->bios_sect);
99232958Sbschmidt    mvprintw(3, 1, "%10s %10s %10s %8s %8s %8s %8s %8s",
100232958Sbschmidt	     "Offset", "Size", "End", "Name", "PType", "Desc",
101232958Sbschmidt	     "Subtype", "Flags");
102232958Sbschmidt    for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) {
103232958Sbschmidt	if (i == current_chunk)
104232958Sbschmidt	    attrset(ATTR_SELECTED);
105232958Sbschmidt	mvprintw(row, 2, "%10ld %10lu %10lu %8s %8d %8s %8d\t%-6s",
106232958Sbschmidt		 chunk_info[i]->offset, chunk_info[i]->size,
107232958Sbschmidt		 chunk_info[i]->end, chunk_info[i]->name,
108232958Sbschmidt		 chunk_info[i]->type, chunk_n[chunk_info[i]->type],
109232958Sbschmidt		 chunk_info[i]->subtype, ShowChunkFlags(chunk_info[i]));
110232958Sbschmidt	if (i == current_chunk)
111232958Sbschmidt	    attrset(A_NORMAL);
112232958Sbschmidt    }
113232958Sbschmidt}
114232958Sbschmidt
115232958Sbschmidtstatic void
116232958Sbschmidtprint_command_summary()
117232958Sbschmidt{
118232958Sbschmidt    mvprintw(14, 0, "The following commands are supported (in upper or lower case):");
119232958Sbschmidt    mvprintw(16, 0, "A = Use Entire Disk    B = Bad Block Scan     C = Create Partition");
120232958Sbschmidt    mvprintw(17, 0, "D = Delete Partition   G = Set Drive Geometry S = Set Bootable");
121232958Sbschmidt    mvprintw(18, 0, "U = Undo All Changes   Q = Finish");
122232958Sbschmidt    if (!RunningAsInit)
123232958Sbschmidt	mvprintw(18, 46, "W = Write Changes");
124232958Sbschmidt    mvprintw(21, 0, "Use F1 or ? to get more help, arrow keys to select.");
125232958Sbschmidt    move(0, 0);
126232958Sbschmidt}
127232958Sbschmidt
128232958Sbschmidtstatic u_char *
129232958SbschmidtgetBootMgr(char *dname)
130232958Sbschmidt{
131232958Sbschmidt    extern u_char mbr[], bteasy17[];
132232958Sbschmidt    char str[80];
133232958Sbschmidt    char *cp;
134232958Sbschmidt    int i = 0;
135232958Sbschmidt
136232958Sbschmidt    cp = variable_get(VAR_BOOTMGR);
137232958Sbschmidt    if (!cp) {
138232958Sbschmidt	/* Figure out what kind of MBR the user wants */
139232958Sbschmidt	sprintf(str, "Install Boot Manager for drive %s?", dname);
140232958Sbschmidt	MenuMBRType.title = str;
141232958Sbschmidt	i = dmenuOpenSimple(&MenuMBRType, FALSE);
142232958Sbschmidt    }
143232958Sbschmidt    else {
144232958Sbschmidt	if (!strncmp(cp, "boot", 4))
145232958Sbschmidt	    BootMgr = 0;
146232958Sbschmidt	else if (!strcmp(cp, "standard"))
147232958Sbschmidt	    BootMgr = 1;
148232958Sbschmidt	else
149232958Sbschmidt	    BootMgr = 2;
150232958Sbschmidt    }
151232958Sbschmidt    if (cp || i) {
152232958Sbschmidt	switch (BootMgr) {
153232958Sbschmidt	case 0:
154232958Sbschmidt	    return bteasy17;
155232958Sbschmidt
156232958Sbschmidt	case 1:
157232958Sbschmidt	    return mbr;
158232958Sbschmidt
159232958Sbschmidt	case 2:
160232958Sbschmidt	default:
161232958Sbschmidt	    break;
162232958Sbschmidt	}
163232958Sbschmidt    }
164232958Sbschmidt    return NULL;
165232958Sbschmidt}
166232958Sbschmidt
167232958Sbschmidtvoid
168232958SbschmidtdiskPartition(Device *dev, Disk *d)
169232958Sbschmidt{
170232958Sbschmidt    char *p;
171232958Sbschmidt    int rv, key = 0;
172232958Sbschmidt    Boolean chunking;
173232958Sbschmidt    char *msg = NULL;
174232958Sbschmidt    u_char *mbrContents;
175232958Sbschmidt    WINDOW *w = savescr();
176232958Sbschmidt
177232958Sbschmidt    chunking = TRUE;
178232958Sbschmidt    keypad(stdscr, TRUE);
179232958Sbschmidt
180232958Sbschmidt    /* Flush both the dialog and curses library views of the screen
181232958Sbschmidt       since we don't always know who called us */
182232958Sbschmidt    dialog_clear_norefresh(), clear();
183232958Sbschmidt
184232958Sbschmidt    /* Set up the chunk array */
185232958Sbschmidt    record_chunks(d);
186232958Sbschmidt
187232958Sbschmidt    while (chunking) {
188232958Sbschmidt	/* Now print our overall state */
189232958Sbschmidt	print_chunks(d);
190232958Sbschmidt	print_command_summary();
191232958Sbschmidt	if (msg) {
192232958Sbschmidt	    attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL);
193232958Sbschmidt	    beep();
194232958Sbschmidt	    msg = NULL;
195232958Sbschmidt	}
196232958Sbschmidt	else {
197232958Sbschmidt	    move(23, 0);
198232958Sbschmidt	    clrtoeol();
199232958Sbschmidt	}
200232958Sbschmidt
201232958Sbschmidt	/* Get command character */
202232958Sbschmidt	key = getch();
203232958Sbschmidt	switch (toupper(key)) {
204232958Sbschmidt
205232958Sbschmidt	    /* redraw */
206232958Sbschmidt	case '\014':	/* ^L */
207232958Sbschmidt	    clear();
208232958Sbschmidt	    msg = NULL;
209232958Sbschmidt	    break;
210232958Sbschmidt
211232958Sbschmidt	case KEY_UP:
212232958Sbschmidt	case '-':
213232958Sbschmidt	    if (current_chunk != 0)
214232958Sbschmidt		--current_chunk;
215232958Sbschmidt	    break;
216232958Sbschmidt
217232958Sbschmidt	case KEY_DOWN:
218232958Sbschmidt	case '+':
219232958Sbschmidt	case '\r':
220232958Sbschmidt	case '\n':
221232958Sbschmidt	    if (chunk_info[current_chunk + 1])
222232958Sbschmidt		++current_chunk;
223232958Sbschmidt	    break;
224232958Sbschmidt
225232958Sbschmidt	case KEY_HOME:
226232958Sbschmidt	    current_chunk = 0;
227232958Sbschmidt	    break;
228232958Sbschmidt
229232958Sbschmidt	case KEY_END:
230232958Sbschmidt	    while (chunk_info[current_chunk + 1])
231232958Sbschmidt		++current_chunk;
232232958Sbschmidt	    break;
233232958Sbschmidt
234232958Sbschmidt	case KEY_F(1):
235232958Sbschmidt	case '?':
236232958Sbschmidt	    systemDisplayHelp("slice");
237232958Sbschmidt	    clear();
238232958Sbschmidt	    break;
239232958Sbschmidt
240232958Sbschmidt	case 'A':
241232958Sbschmidt	    rv = msgYesNo("Do you want to do this with a true partition entry\n"
242232958Sbschmidt			  "so as to remain cooperative with any future possible\n"
243232958Sbschmidt			  "operating systems on the drive(s)?");
244232958Sbschmidt	    if (rv) {
245232958Sbschmidt		rv = !msgYesNo("This is dangerous in that it will make the drive totally\n"
246232958Sbschmidt			       "uncooperative with other potential operating systems on the\n"
247232958Sbschmidt			       "same disk.  It will lead instead to a totally dedicated disk,\n"
248232958Sbschmidt			       "starting at the very first sector, bypassing all BIOS geometry\n"
249232958Sbschmidt			       "considerations.  This precludes the existance of any boot\n"
250232958Sbschmidt			       "manager or other stuff in sector 0, since the BSD bootstrap\n"
251232958Sbschmidt			       "will live there.\n"
252232958Sbschmidt			       "You will run into serious trouble with ST-506 and ESDI drives\n"
253232958Sbschmidt			       "and possibly some IDE drives (e.g. drives running under the\n"
254232958Sbschmidt			       "control of sort of disk manager).  SCSI drives are considerably\n"
255232958Sbschmidt			       "less at risk.\n\n"
256232958Sbschmidt			       "Do you insist on dedicating the entire disk this way?");
257232958Sbschmidt	    }
258232958Sbschmidt	    All_FreeBSD(d, rv);
259232958Sbschmidt	    if (rv)
260232958Sbschmidt		d->bios_hd = d->bios_sect = d->bios_cyl = 1;
261232958Sbschmidt	    variable_set2(DISK_PARTITIONED, "yes");
262232958Sbschmidt	    record_chunks(d);
263232958Sbschmidt	    clear();
264232958Sbschmidt	    break;
265232958Sbschmidt
266232958Sbschmidt	case 'B':
267232958Sbschmidt	    if (chunk_info[current_chunk]->type != freebsd)
268232958Sbschmidt		msg = "Can only scan for bad blocks in FreeBSD partition.";
269232958Sbschmidt	    else if (strncmp(d->name, "sd", 2) ||
270232958Sbschmidt		     !msgYesNo("This typically makes sense only for ESDI, IDE or MFM drives.\n"
271232958Sbschmidt			       "Are you sure you want to do this on a SCSI disk?")) {
272232958Sbschmidt		if (chunk_info[current_chunk]->flags & CHUNK_BAD144)
273232958Sbschmidt		    chunk_info[current_chunk]->flags &= ~CHUNK_BAD144;
274232958Sbschmidt		else
275232958Sbschmidt		    chunk_info[current_chunk]->flags |= CHUNK_BAD144;
276232958Sbschmidt	    }
277232958Sbschmidt	    clear();
278232958Sbschmidt	    break;
279232958Sbschmidt
280232958Sbschmidt	case 'C':
281232958Sbschmidt	    if (chunk_info[current_chunk]->type != unused)
282232958Sbschmidt		msg = "Partition in use, delete it first or move to an unused one.";
283232958Sbschmidt	    else {
284232958Sbschmidt		char *val, tmp[20], *cp;
285232958Sbschmidt		int size, subtype;
286232958Sbschmidt		chunk_e partitiontype;
287232958Sbschmidt
288232958Sbschmidt		snprintf(tmp, 20, "%d", chunk_info[current_chunk]->size);
289232958Sbschmidt		val = msgGetInput(tmp, "Please specify the size for new FreeBSD partition in blocks\n"
290232958Sbschmidt				       "or append a trailing `M' for megabytes (e.g. 20M).");
291232958Sbschmidt		if (val && (size = strtol(val, &cp, 0)) > 0) {
292232958Sbschmidt		    if (*cp && toupper(*cp) == 'M')
293232958Sbschmidt			size *= ONE_MEG;
294232958Sbschmidt		    strcpy(tmp, "165");
295232958Sbschmidt		    val = msgGetInput(tmp, "Enter type of partition to create:\n\n"
296232958Sbschmidt				      "Pressing Enter will choose the default, a native FreeBSD\n"
297232958Sbschmidt				      "partition (type 165).  You can choose other types, 6 for a\n"
298232958Sbschmidt				      "DOS partition or 131 for a Linux partition, for example.\n\n"
299232958Sbschmidt				      "Note:  If you choose a non-FreeBSD partition type, it will not\n"
300232958Sbschmidt				      "be formatted or otherwise prepared, it will simply reserve space\n"
301232958Sbschmidt				      "for you to use another tool, such as DOS FORMAT, to later format\n"
302232958Sbschmidt				      "and use the partition.");
303232958Sbschmidt		    if (val && (subtype = strtol(val, NULL, 0)) > 0) {
304232958Sbschmidt			if (subtype==165)
305232958Sbschmidt				partitiontype=freebsd;
306232958Sbschmidt			else if (subtype==6)
307232958Sbschmidt				partitiontype=fat;
308232958Sbschmidt			else
309232958Sbschmidt				partitiontype=unknown;
310232958Sbschmidt		    Create_Chunk(d, chunk_info[current_chunk]->offset, size, partitiontype, subtype,
311232958Sbschmidt				 (chunk_info[current_chunk]->flags & CHUNK_ALIGN));
312232958Sbschmidt		    variable_set2(DISK_PARTITIONED, "yes");
313232958Sbschmidt		    record_chunks(d);
314232958Sbschmidt		    }
315232958Sbschmidt		}
316232958Sbschmidt		clear();
317232958Sbschmidt	    }
318232958Sbschmidt	    break;
319232958Sbschmidt
320232958Sbschmidt	case KEY_DC:
321232958Sbschmidt	case 'D':
322232958Sbschmidt	    if (chunk_info[current_chunk]->type == unused)
323232958Sbschmidt		msg = "Partition is already unused!";
324232958Sbschmidt	    else {
325232958Sbschmidt		Delete_Chunk(d, chunk_info[current_chunk]);
326232958Sbschmidt		variable_set2(DISK_PARTITIONED, "yes");
327232958Sbschmidt		record_chunks(d);
328232958Sbschmidt	    }
329232958Sbschmidt	    break;
330232958Sbschmidt
331232958Sbschmidt	case 'G': {
332232958Sbschmidt	    char *val, geometry[80];
333232958Sbschmidt
334232958Sbschmidt	    snprintf(geometry, 80, "%lu/%lu/%lu", d->bios_cyl, d->bios_hd, d->bios_sect);
335232958Sbschmidt	    val = msgGetInput(geometry, "Please specify the new geometry in cyl/hd/sect format.\n"
336232958Sbschmidt			      "Don't forget to use the two slash (/) separator characters!\n"
337232958Sbschmidt			      "It's not possible to parse the field without them.");
338232958Sbschmidt	    if (val) {
339232958Sbschmidt		d->bios_cyl = strtol(val, &val, 0);
340232958Sbschmidt		d->bios_hd = strtol(val + 1, &val, 0);
341232958Sbschmidt		d->bios_sect = strtol(val + 1, 0, 0);
342232958Sbschmidt	    }
343232958Sbschmidt	    clear();
344232958Sbschmidt	}
345232958Sbschmidt	break;
346232958Sbschmidt
347232958Sbschmidt    case 'S':
348232958Sbschmidt	/* Set Bootable */
349232958Sbschmidt	chunk_info[current_chunk]->flags |= CHUNK_ACTIVE;
350232958Sbschmidt	break;
351232958Sbschmidt
352232958Sbschmidt    case 'U':
353232958Sbschmidt	    if (msgYesNo("Are you SURE you want to Undo everything?")) {
354232958Sbschmidt		clear();
355232958Sbschmidt		break;
356232958Sbschmidt	    }
357232958Sbschmidt	    d = Open_Disk(d->name);
358232958Sbschmidt	    if (!d) {
359232958Sbschmidt		msgConfirm("Can't reopen disk %s! Internal state is probably corrupted", d->name);
360232958Sbschmidt	    	clear();
361232958Sbschmidt		break;
362232958Sbschmidt	    }
363232958Sbschmidt	    Free_Disk(dev->private);
364232958Sbschmidt	    dev->private = d;
365232958Sbschmidt	    variable_unset(DISK_PARTITIONED);
366232958Sbschmidt	    variable_unset(DISK_LABELLED);
367232958Sbschmidt	    record_chunks(d);
368232958Sbschmidt	    clear();
369232958Sbschmidt	    break;
370232958Sbschmidt
371232958Sbschmidt	case 'W':
372232958Sbschmidt	    if (!msgYesNo("WARNING:  This should only be used for modifying an\n"
373232958Sbschmidt			  "EXISTING installation - If you are installing FreeBSD\n"
374232958Sbschmidt			  "for the first time then you should simply hit 'Q' now."
375232958Sbschmidt			  "Your changes will be committed in one batch at the end\n"
376232958Sbschmidt			  "of this section and do not have to be written now.\n\n"
377232958Sbschmidt			  "Are you absolutely sure you want to do this now?")) {
378232958Sbschmidt
379232958Sbschmidt		variable_set2(DISK_PARTITIONED, "yes");
380232958Sbschmidt
381232958Sbschmidt		/* Don't trash the MBR if the first (and therefore only) chunk is marked for a truly dedicated
382232958Sbschmidt		 * disk (i.e., the disklabel starts at sector 0), even in cases where the user has requested
383232958Sbschmidt		 * booteasy or a "standard" MBR -- both would be fatal in this case.
384232958Sbschmidt		 */
385232958Sbschmidt		if ((d->chunks->part->flags & CHUNK_FORCE_ALL) != CHUNK_FORCE_ALL
386232958Sbschmidt		    && (mbrContents = getBootMgr(d->name)) != NULL)
387232958Sbschmidt		    Set_Boot_Mgr(d, mbrContents);
388232958Sbschmidt
389232958Sbschmidt		if (DITEM_STATUS(diskPartitionWrite(NULL)) != DITEM_SUCCESS)
390232958Sbschmidt		    msgConfirm("Disk partition write returned an error status!");
391232958Sbschmidt		else
392232958Sbschmidt		    msgConfirm("Wrote FDISK partition information out successfully.");
393232958Sbschmidt	    }
394232958Sbschmidt	    clear();
395232958Sbschmidt	    break;
396232958Sbschmidt
397232958Sbschmidt	case '|':
398232958Sbschmidt	    if (!msgYesNo("Are you SURE you want to go into Wizard mode?\n"
399232958Sbschmidt			  "No seat belts whatsoever are provided!")) {
400232958Sbschmidt		clear();
401232958Sbschmidt		refresh();
402232958Sbschmidt		slice_wizard(d);
403232958Sbschmidt		variable_set2(DISK_PARTITIONED, "yes");
404232958Sbschmidt		record_chunks(d);
405232958Sbschmidt	    }
406232958Sbschmidt	    else
407232958Sbschmidt		msg = "Wise choice!";
408232958Sbschmidt	    clear();
409232958Sbschmidt	    break;
410232958Sbschmidt
411232958Sbschmidt	case 'Q':
412232958Sbschmidt	    chunking = FALSE;
413232958Sbschmidt	    /* Don't trash the MBR if the first (and therefore only) chunk is marked for a truly dedicated
414232958Sbschmidt	     * disk (i.e., the disklabel starts at sector 0), even in cases where the user has requested
415232958Sbschmidt	     * booteasy or a "standard" MBR -- both would be fatal in this case.
416232958Sbschmidt	     */
417232958Sbschmidt	    if ((d->chunks->part->flags & CHUNK_FORCE_ALL) != CHUNK_FORCE_ALL
418232958Sbschmidt		&& (mbrContents = getBootMgr(d->name)) != NULL)
419232958Sbschmidt		Set_Boot_Mgr(d, mbrContents);
420232958Sbschmidt	    break;
421232958Sbschmidt
422232958Sbschmidt	default:
423232958Sbschmidt	    beep();
424232958Sbschmidt	    msg = "Type F1 or ? for help";
425232958Sbschmidt	    break;
426232958Sbschmidt	}
427232958Sbschmidt    }
428232958Sbschmidt    p = CheckRules(d);
429232958Sbschmidt    if (p) {
430232958Sbschmidt	char buf[FILENAME_MAX];
431232958Sbschmidt
432232958Sbschmidt	dialog_clear_norefresh();
433232958Sbschmidt        use_helpline("Press F1 to read more about disk partitioning.");
434232958Sbschmidt	use_helpfile(systemHelpFile("partition", buf));
435232958Sbschmidt	dialog_mesgbox("Disk partitioning warning:", p, -1, -1);
436232958Sbschmidt	free(p);
437232958Sbschmidt    }
438232958Sbschmidt    restorescr(w);
439232958Sbschmidt}
440232958Sbschmidt
441232958Sbschmidtstatic int
442232958SbschmidtpartitionHook(dialogMenuItem *selected)
443232958Sbschmidt{
444232958Sbschmidt    Device **devs = NULL;
445232958Sbschmidt
446232958Sbschmidt    devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK);
447232958Sbschmidt    if (!devs) {
448232958Sbschmidt	msgConfirm("Unable to find disk %s!", selected->prompt);
449232958Sbschmidt	return DITEM_FAILURE;
450232958Sbschmidt    }
451232958Sbschmidt    /* Toggle enabled status? */
452232958Sbschmidt    if (!devs[0]->enabled) {
453232958Sbschmidt	devs[0]->enabled = TRUE;
454232958Sbschmidt	diskPartition(devs[0], (Disk *)devs[0]->private);
455232958Sbschmidt    }
456232958Sbschmidt    else
457232958Sbschmidt	devs[0]->enabled = FALSE;
458232958Sbschmidt    return DITEM_SUCCESS | DITEM_REDRAW;
459232958Sbschmidt}
460232958Sbschmidt
461232958Sbschmidtstatic int
462232958SbschmidtpartitionCheck(dialogMenuItem *selected)
463232958Sbschmidt{
464232958Sbschmidt    Device **devs = NULL;
465232958Sbschmidt
466232958Sbschmidt    devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK);
467232958Sbschmidt    if (!devs || devs[0]->enabled == FALSE)
468232958Sbschmidt	return FALSE;
469232958Sbschmidt    return TRUE;
470232958Sbschmidt}
471232958Sbschmidt
472232958Sbschmidtint
473232958SbschmidtdiskPartitionEditor(dialogMenuItem *self)
474232958Sbschmidt{
475232958Sbschmidt    DMenu *menu;
476232958Sbschmidt    Device **devs;
477232958Sbschmidt    int i, cnt;
478232958Sbschmidt    char *cp;
479232958Sbschmidt
480232958Sbschmidt    cp = variable_get(VAR_DISK);
481232958Sbschmidt    devs = deviceFind(cp, DEVICE_TYPE_DISK);
482232958Sbschmidt    cnt = deviceCount(devs);
483232958Sbschmidt    if (!cnt) {
484232958Sbschmidt	msgConfirm("No disks found!  Please verify that your disk controller is being\n"
485232958Sbschmidt		   "properly probed at boot time.  See the Hardware Guide on the\n"
486232958Sbschmidt		   "Documentation menu for clues on diagnosing this type of problem.");
487232958Sbschmidt	i = DITEM_FAILURE;
488232958Sbschmidt    }
489232958Sbschmidt    else if (cnt == 1) {
490232958Sbschmidt	devs[0]->enabled = TRUE;
491232958Sbschmidt	diskPartition(devs[0], (Disk *)devs[0]->private);
492232958Sbschmidt	i = DITEM_SUCCESS;
493232958Sbschmidt    }
494232958Sbschmidt    else {
495232958Sbschmidt	menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook, partitionCheck);
496232958Sbschmidt	if (!menu) {
497232958Sbschmidt	    msgConfirm("No devices suitable for installation found!\n\n"
498232958Sbschmidt		       "Please verify that your disk controller (and attached drives)\n"
499232958Sbschmidt		       "were detected properly.  This can be done by pressing the\n"
500232958Sbschmidt		       "[Scroll Lock] key and using the Arrow keys to move back to\n"
501232958Sbschmidt		       "the boot messages.  Press [Scroll Lock] again to return.");
502232958Sbschmidt	    i = DITEM_FAILURE;
503232958Sbschmidt	}
504232958Sbschmidt	else {
505232958Sbschmidt	    i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE;
506232958Sbschmidt	    free(menu);
507232958Sbschmidt	}
508232958Sbschmidt	i = i | DITEM_RECREATE;
509232958Sbschmidt    }
510232958Sbschmidt    return i;
511232958Sbschmidt}
512232958Sbschmidt
513232958Sbschmidtint
514232958SbschmidtdiskPartitionWrite(dialogMenuItem *self)
515232958Sbschmidt{
516232958Sbschmidt    Device **devs;
517232958Sbschmidt    char *cp;
518232958Sbschmidt    int i;
519232958Sbschmidt
520232958Sbschmidt    if ((cp = variable_get(DISK_PARTITIONED)) && strcmp(cp, "yes"))
521232958Sbschmidt	return DITEM_SUCCESS;
522232958Sbschmidt    else if (!cp) {
523232958Sbschmidt	msgConfirm("You must partition the disk(s) before this option can be used.");
524232958Sbschmidt	return DITEM_FAILURE;
525232958Sbschmidt    }
526232958Sbschmidt
527232958Sbschmidt    devs = deviceFind(NULL, DEVICE_TYPE_DISK);
528232958Sbschmidt    if (!devs) {
529232958Sbschmidt	msgConfirm("Unable to find any disks to write to??");
530232958Sbschmidt	return DITEM_FAILURE;
531232958Sbschmidt    }
532232958Sbschmidt    if (isDebug())
533232958Sbschmidt	msgDebug("diskPartitionWrite: Examining %d devices\n", deviceCount(devs));
534232958Sbschmidt
535232958Sbschmidt    for (i = 0; devs[i]; i++) {
536232958Sbschmidt	Chunk *c1;
537232958Sbschmidt	Disk *d = (Disk *)devs[i]->private;
538232958Sbschmidt
539232958Sbschmidt	if (!devs[i]->enabled)
540232958Sbschmidt	    continue;
541232958Sbschmidt
542232958Sbschmidt	Set_Boot_Blocks(d, boot1, boot2);
543232958Sbschmidt	msgNotify("Writing partition information to drive %s", d->name);
544232958Sbschmidt	if (!Fake && Write_Disk(d)) {
545232958Sbschmidt	    msgConfirm("ERROR: Unable to write data to disk %s!", d->name);
546232958Sbschmidt	    return DITEM_FAILURE;
547232958Sbschmidt	}
548232958Sbschmidt	/* Now scan for bad blocks, if necessary */
549232958Sbschmidt	for (c1 = d->chunks->part; c1; c1 = c1->next) {
550232958Sbschmidt	    if (c1->flags & CHUNK_BAD144) {
551232958Sbschmidt		int ret;
552232958Sbschmidt
553232958Sbschmidt		msgNotify("Running bad block scan on partition %s", c1->name);
554232958Sbschmidt		if (!Fake) {
555232958Sbschmidt		    ret = vsystem("bad144 -v /dev/r%s 1234", c1->name);
556232958Sbschmidt		    if (ret)
557232958Sbschmidt			msgConfirm("Bad144 init on %s returned status of %d!", c1->name, ret);
558232958Sbschmidt		    ret = vsystem("bad144 -v -s /dev/r%s", c1->name);
559232958Sbschmidt		    if (ret)
560232958Sbschmidt			msgConfirm("Bad144 scan on %s returned status of %d!", c1->name, ret);
561232958Sbschmidt		}
562232958Sbschmidt	    }
563232958Sbschmidt	}
564232958Sbschmidt    }
565232958Sbschmidt    /* Now it's not "yes", but "written" */
566232958Sbschmidt    variable_set2(DISK_PARTITIONED, "written");
567232958Sbschmidt    return DITEM_SUCCESS;
568232958Sbschmidt}
569232958Sbschmidt