disks.c revision 43685
195967Speter/* 295967Speter * The new sysinstall program. 3127326Smarkm * 4127326Smarkm * This is probably the last program in the `sysinstall' line - the next 5127326Smarkm * generation being essentially a complete rewrite. 6127326Smarkm * 7127326Smarkm * $Id: disks.c,v 1.108 1999/01/08 00:14:21 jkh Exp $ 895967Speter * 995967Speter * Copyright (c) 1995 1095967Speter * Jordan Hubbard. All rights reserved. 1195967Speter * 1295967Speter * Redistribution and use in source and binary forms, with or without 1395967Speter * modification, are permitted provided that the following conditions 1495967Speter * are met: 1595967Speter * 1. Redistributions of source code must retain the above copyright 1695967Speter * notice, this list of conditions and the following disclaimer, 1795967Speter * verbatim and that no modifications are made prior to this 1895967Speter * point in the file. 1995967Speter * 2. Redistributions in binary form must reproduce the above copyright 2095967Speter * notice, this list of conditions and the following disclaimer in the 2195967Speter * documentation and/or other materials provided with the distribution. 22127326Smarkm * 2395967Speter * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 2495967Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25127326Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26127326Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 27127326Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2895967Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2995967Speter * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 3095967Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31127326Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32127326Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3395967Speter * SUCH DAMAGE. 3495967Speter * 35127326Smarkm */ 3695967Speter 3795967Speter#include "sysinstall.h" 3895967Speter#include <ctype.h> 3995967Speter#include <fcntl.h> 4095967Speter#include <sys/stat.h> 4195967Speter#include <sys/disklabel.h> 4295967Speter 4395967Speter/* Where we start displaying chunk information on the screen */ 4495967Speter#define CHUNK_START_ROW 5 4595967Speter 4695967Speter/* Where we keep track of MBR chunks */ 4795967Speterstatic struct chunk *chunk_info[16]; 4895967Speterstatic int current_chunk; 4995967Speter 5095967Speterstatic void diskPartitionNonInteractive(Device *dev); 5195967Speter 5295967Speterstatic void 5395967Speterrecord_chunks(Disk *d) 5495967Speter{ 5595967Speter struct chunk *c1 = NULL; 5695967Speter int i = 0; 5795967Speter int last_free = 0; 58127326Smarkm 59127326Smarkm if (!d->chunks) 6095967Speter msgFatal("No chunk list found for %s!", d->name); 61127326Smarkm 6295967Speter for (c1 = d->chunks->part; c1; c1 = c1->next) { 6395967Speter if (c1->type == unused && c1->size > last_free) { 64127326Smarkm last_free = c1->size; 6595967Speter current_chunk = i; 6695967Speter } 67127326Smarkm chunk_info[i++] = c1; 6895967Speter } 6995967Speter chunk_info[i] = NULL; 7095967Speter if (current_chunk >= i) 71127326Smarkm current_chunk = i - 1; 7295967Speter} 73127326Smarkm 7495967Speterstatic int Total; 75127326Smarkm 7695967Speterstatic void 77127326Smarkmprint_chunks(Disk *d) 7895967Speter{ 79127326Smarkm int row; 8095967Speter int i; 81127326Smarkm 82127326Smarkm for (i = Total = 0; chunk_info[i]; i++) 8395967Speter Total += chunk_info[i]->size; 8495967Speter if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) { 85127326Smarkm dialog_clear_norefresh(); 8695967Speter msgConfirm("WARNING: A geometry of %d/%d/%d for %s is incorrect. Using\n" 8795967Speter "a more likely geometry. If this geometry is incorrect or you\n" 8895967Speter "are unsure as to whether or not it's correct, please consult\n" 8995967Speter "the Hardware Guide in the Documentation submenu or use the\n" 9095967Speter "(G)eometry command to change it now.\n\n" 9195967Speter "Remember: you need to enter whatever your BIOS thinks the\n" 9295967Speter "geometry is! For IDE, it's what you were told in the BIOS\n" 9395967Speter "setup. For SCSI, it's the translation mode your controller is\n" 9495967Speter "using. Do NOT use a ``physical geometry''.", 9595967Speter d->bios_cyl, d->bios_hd, d->bios_sect, d->name); 9695967Speter Sanitize_Bios_Geom(d); 9795967Speter } 9895967Speter attrset(A_NORMAL); 9995967Speter mvaddstr(0, 0, "Disk name:\t"); 10095967Speter clrtobot(); 10195967Speter attrset(A_REVERSE); addstr(d->name); attrset(A_NORMAL); 10295967Speter attrset(A_REVERSE); mvaddstr(0, 55, "FDISK Partition Editor"); attrset(A_NORMAL); 10395967Speter mvprintw(1, 0, 10495967Speter "DISK Geometry:\t%lu cyls/%lu heads/%lu sectors = %lu sectors", 10595967Speter d->bios_cyl, d->bios_hd, d->bios_sect, 10695967Speter d->bios_cyl * d->bios_hd * d->bios_sect); 10795967Speter mvprintw(3, 0, "%10s %10s %10s %8s %6s %10s %8s %8s", 108127326Smarkm "Offset", "Size", "End", "Name", "PType", "Desc", 109127326Smarkm "Subtype", "Flags"); 11095967Speter for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) { 111127326Smarkm if (i == current_chunk) 11295967Speter attrset(ATTR_SELECTED); 11395967Speter mvprintw(row, 0, "%10ld %10lu %10lu %8s %6d %10s %8d\t%-6s", 114127326Smarkm chunk_info[i]->offset, chunk_info[i]->size, 11595967Speter chunk_info[i]->end, chunk_info[i]->name, 11695967Speter chunk_info[i]->type, 117127326Smarkm slice_type_name(chunk_info[i]->type, chunk_info[i]->subtype), 11895967Speter chunk_info[i]->subtype, ShowChunkFlags(chunk_info[i])); 11995967Speter if (i == current_chunk) 12095967Speter attrset(A_NORMAL); 121127326Smarkm } 12295967Speter} 123127326Smarkm 12495967Speterstatic void 125127326Smarkmprint_command_summary() 12695967Speter{ 127127326Smarkm mvprintw(14, 0, "The following commands are supported (in upper or lower case):"); 12895967Speter mvprintw(16, 0, "A = Use Entire Disk B = Bad Block Scan C = Create Slice"); 129127326Smarkm mvprintw(17, 0, "D = Delete Slice G = Set Drive Geometry S = Set Bootable"); 13095967Speter mvprintw(18, 0, "T = Change Type U = Undo All Changes Q = Finish"); 131127326Smarkm if (!RunningAsInit) 132127326Smarkm mvprintw(18, 48, "W = Write Changes"); 13395967Speter mvprintw(21, 0, "Use F1 or ? to get more help, arrow keys to select."); 13495967Speter move(0, 0); 135127326Smarkm} 13695967Speter 13795967Speterstatic u_char * 13895967SpetergetBootMgr(char *dname) 13995967Speter{ 14095967Speter#ifndef __alpha__ /* only meaningful on x86 */ 14195967Speter extern u_char mbr[], boot0[]; 14295967Speter char str[80]; 14395967Speter char *cp; 14495967Speter int i = 0; 14595967Speter 14695967Speter cp = variable_get(VAR_BOOTMGR); 14795967Speter if (!cp) { 14895967Speter /* Figure out what kind of MBR the user wants */ 14995967Speter sprintf(str, "Install Boot Manager for drive %s?", dname); 15095967Speter MenuMBRType.title = str; 15195967Speter i = dmenuOpenSimple(&MenuMBRType, FALSE); 15295967Speter } 15395967Speter else { 15495967Speter if (!strncmp(cp, "boot", 4)) 15595967Speter BootMgr = 0; 15695967Speter else if (!strcmp(cp, "standard")) 15795967Speter BootMgr = 1; 158127326Smarkm else 159127326Smarkm BootMgr = 2; 16095967Speter } 161127326Smarkm if (cp || i) { 16295967Speter switch (BootMgr) { 16395967Speter case 0: 164127326Smarkm return boot0; 16595967Speter 16695967Speter case 1: 167127326Smarkm return mbr; 16895967Speter 16995967Speter case 2: 17095967Speter default: 171127326Smarkm break; 17295967Speter } 173127326Smarkm } 17495967Speter#endif 175127326Smarkm return NULL; 17695967Speter} 177127326Smarkm 17895967Speterint 179127326SmarkmdiskGetSelectCount(Device ***devs) 18095967Speter{ 181127326Smarkm int i, cnt, enabled; 182127326Smarkm char *cp; 18395967Speter Device **dp; 18495967Speter 185127326Smarkm cp = variable_get(VAR_DISK); 18695967Speter dp = *devs = deviceFind(cp, DEVICE_TYPE_DISK); 18795967Speter cnt = deviceCount(dp); 18895967Speter if (!cnt) 18995967Speter return -1; 19095967Speter for (i = 0, enabled = 0; i < cnt; i++) { 19195967Speter if (dp[i]->enabled) 19295967Speter ++enabled; 19395967Speter } 19495967Speter return enabled; 19595967Speter} 19695967Speter 19795967Spetervoid 19895967SpeterdiskPartition(Device *dev) 19995967Speter{ 20095967Speter char *cp, *p; 20195967Speter int rv, key = 0; 20295967Speter Boolean chunking; 20395967Speter char *msg = NULL; 20495967Speter u_char *mbrContents; 20595967Speter WINDOW *w = savescr(); 20695967Speter Disk *d = (Disk *)dev->private; 20795967Speter 208127326Smarkm chunking = TRUE; 209127326Smarkm keypad(stdscr, TRUE); 21095967Speter 211127326Smarkm /* Flush both the dialog and curses library views of the screen 21295967Speter since we don't always know who called us */ 21395967Speter dialog_clear_norefresh(), clear(); 214127326Smarkm current_chunk = 0; 21595967Speter 21695967Speter /* Set up the chunk array */ 217127326Smarkm record_chunks(d); 21895967Speter 21995967Speter while (chunking) { 22095967Speter char *val, geometry[80]; 221127326Smarkm 22295967Speter /* Now print our overall state */ 223127326Smarkm if (d) 22495967Speter print_chunks(d); 225127326Smarkm print_command_summary(); 22695967Speter if (msg) { 227127326Smarkm attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); 22895967Speter beep(); 229127326Smarkm msg = NULL; 23095967Speter } 231127326Smarkm else { 232127326Smarkm move(23, 0); 23395967Speter clrtoeol(); 23495967Speter } 235127326Smarkm 23695967Speter /* Get command character */ 23795967Speter key = getch(); 23895967Speter switch (toupper(key)) { 23995967Speter case '\014': /* ^L (redraw) */ 24095967Speter clear(); 24195967Speter msg = NULL; 24295967Speter break; 24395967Speter 24495967Speter case '\020': /* ^P */ 24595967Speter case KEY_UP: 24695967Speter case '-': 24795967Speter if (current_chunk != 0) 24895967Speter --current_chunk; 24995967Speter break; 25095967Speter 25195967Speter case '\016': /* ^N */ 25295967Speter case KEY_DOWN: 25395967Speter case '+': 25495967Speter case '\r': 25595967Speter case '\n': 25695967Speter if (chunk_info[current_chunk + 1]) 25795967Speter ++current_chunk; 258127326Smarkm break; 259127326Smarkm 26095967Speter case KEY_HOME: 261127326Smarkm current_chunk = 0; 26295967Speter break; 26395967Speter 264127326Smarkm case KEY_END: 26595967Speter while (chunk_info[current_chunk + 1]) 26695967Speter ++current_chunk; 267127326Smarkm break; 26895967Speter 26995967Speter case KEY_F(1): 27095967Speter case '?': 271127326Smarkm systemDisplayHelp("slice"); 27295967Speter clear(); 273127326Smarkm break; 27495967Speter 275127326Smarkm case 'A': 27695967Speter#ifdef __alpha__ 277127326Smarkm rv = 1; 27895967Speter#else /* The rest is only relevant on x86 */ 279127326Smarkm cp = variable_get(VAR_DEDICATE_DISK); 28095967Speter if (cp && !strcasecmp(cp, "always")) 281127326Smarkm rv = 1; 282127326Smarkm else { 28395967Speter rv = msgYesNo("Do you want to do this with a true partition entry\n" 28495967Speter "so as to remain cooperative with any future possible\n" 285127326Smarkm "operating systems on the drive(s)?\n" 28695967Speter "(See also the section about ``dangerously dedicated''\n" 28795967Speter "disks in the FreeBSD FAQ.)"); 28895967Speter if (rv == -1) 28995967Speter rv = 0; 29095967Speter } 29195967Speter#endif 29295967Speter All_FreeBSD(d, rv); 29395967Speter variable_set2(DISK_PARTITIONED, "yes", 0); 29495967Speter record_chunks(d); 29595967Speter clear(); 29695967Speter break; 29795967Speter 29895967Speter case 'B': 29995967Speter if (chunk_info[current_chunk]->type != freebsd) 30095967Speter msg = "Can only scan for bad blocks in FreeBSD slice."; 30195967Speter else if (strncmp(d->name, "sd", 2) || 30295967Speter strncmp(d->name, "da", 2) || 30395967Speter !msgYesNo("This typically makes sense only for ESDI, IDE or MFM drives.\n" 30495967Speter "Are you sure you want to do this on a SCSI disk?")) { 30595967Speter if (chunk_info[current_chunk]->flags & CHUNK_BAD144) 30695967Speter chunk_info[current_chunk]->flags &= ~CHUNK_BAD144; 30795967Speter else 308127326Smarkm chunk_info[current_chunk]->flags |= CHUNK_BAD144; 309127326Smarkm } 31095967Speter clear(); 311127326Smarkm break; 31295967Speter 31395967Speter case 'C': 314127326Smarkm if (chunk_info[current_chunk]->type != unused) 31595967Speter msg = "Slice in use, delete it first or move to an unused one."; 31695967Speter else { 317127326Smarkm char *val, tmp[20], *cp; 31895967Speter int size, subtype; 31995967Speter chunk_e partitiontype; 32095967Speter 321127326Smarkm snprintf(tmp, 20, "%lu", chunk_info[current_chunk]->size); 32295967Speter val = msgGetInput(tmp, "Please specify the size for new FreeBSD slice in blocks\n" 323127326Smarkm "or append a trailing `M' for megabytes (e.g. 20M)."); 32495967Speter if (val && (size = strtol(val, &cp, 0)) > 0) { 325127326Smarkm if (*cp && toupper(*cp) == 'M') 32695967Speter size *= ONE_MEG; 327127326Smarkm strcpy(tmp, "165"); 32895967Speter val = msgGetInput(tmp, "Enter type of partition to create:\n\n" 329127326Smarkm "Pressing Enter will choose the default, a native FreeBSD\n" 33095967Speter "slice (type 165). You can choose other types, 6 for a\n" 331127326Smarkm "DOS partition or 131 for a Linux partition, for example.\n\n" 332127326Smarkm "Note: If you choose a non-FreeBSD partition type, it will not\n" 33395967Speter "be formatted or otherwise prepared, it will simply reserve space\n" 33495967Speter "for you to use another tool, such as DOS FORMAT, to later format\n" 335127326Smarkm "and use the partition."); 33695967Speter if (val && (subtype = strtol(val, NULL, 0)) > 0) { 33795967Speter if (subtype == 165) 33895967Speter partitiontype = freebsd; 33995967Speter else if (subtype == 6) 34095967Speter partitiontype = fat; 34195967Speter else 34295967Speter partitiontype = unknown; 34395967Speter#ifdef __alpha__ 34495967Speter if (partitiontype == freebsd && size == chunk_info[current_chunk]->size) 34595967Speter All_FreeBSD(d, 1); 34695967Speter else 34795967Speter#endif 34895967Speter Create_Chunk(d, chunk_info[current_chunk]->offset, size, partitiontype, subtype, 34995967Speter (chunk_info[current_chunk]->flags & CHUNK_ALIGN)); 35095967Speter variable_set2(DISK_PARTITIONED, "yes", 0); 35195967Speter record_chunks(d); 35295967Speter } 35395967Speter } 35495967Speter clear(); 35595967Speter } 35695967Speter break; 35795967Speter 358127326Smarkm case KEY_DC: 359127326Smarkm case 'D': 36095967Speter if (chunk_info[current_chunk]->type == unused) 361127326Smarkm msg = "Slice is already unused!"; 36295967Speter else { 36395967Speter Delete_Chunk(d, chunk_info[current_chunk]); 364127326Smarkm variable_set2(DISK_PARTITIONED, "yes", 0); 36595967Speter record_chunks(d); 36695967Speter } 367127326Smarkm break; 36895967Speter 36995967Speter case 'T': 37095967Speter if (chunk_info[current_chunk]->type == unused) 371127326Smarkm msg = "Slice is currently unused (use create instead)"; 37295967Speter else { 373127326Smarkm char *val, tmp[20]; 37495967Speter int subtype; 375127326Smarkm chunk_e partitiontype; 37695967Speter WINDOW *save = savescr(); 377127326Smarkm 37895967Speter strcpy(tmp, "165"); 379127326Smarkm val = msgGetInput(tmp, "New partition type:\n\n" 38095967Speter "Pressing Enter will choose the default, a native FreeBSD\n" 381127326Smarkm "slice (type 165). Other popular values are 6 for\n" 382127326Smarkm "DOS FAT partition, 131 for a Linux ext2fs partition or\n" 38395967Speter "130 for a Linux swap partition.\n\n" 38495967Speter "Note: If you choose a non-FreeBSD partition type, it will not\n" 385127326Smarkm "be formatted or otherwise prepared, it will simply reserve space\n" 38695967Speter "for you to use another tool, such as DOS format, to later format\n" 38795967Speter "and actually use the partition."); 38895967Speter if (val && (subtype = strtol(val, NULL, 0)) > 0) { 38995967Speter if (subtype == 165) 39095967Speter partitiontype = freebsd; 39195967Speter else if (subtype == 6) 39295967Speter partitiontype = fat; 39395967Speter else 39495967Speter partitiontype = unknown; 39595967Speter chunk_info[current_chunk]->type = partitiontype; 39695967Speter chunk_info[current_chunk]->subtype = subtype; 39795967Speter } 39895967Speter restorescr(save); 39995967Speter } 40095967Speter break; 40195967Speter 40295967Speter case 'G': 40395967Speter snprintf(geometry, 80, "%lu/%lu/%lu", d->bios_cyl, d->bios_hd, d->bios_sect); 40495967Speter val = msgGetInput(geometry, "Please specify the new geometry in cyl/hd/sect format.\n" 40595967Speter "Don't forget to use the two slash (/) separator characters!\n" 40695967Speter "It's not possible to parse the field without them."); 40795967Speter if (val) { 408127326Smarkm long nc, nh, ns; 409127326Smarkm nc = strtol(val, &val, 0); 41095967Speter nh = strtol(val + 1, &val, 0); 411127326Smarkm ns = strtol(val + 1, 0, 0); 41295967Speter Set_Bios_Geom(d, nc, nh, ns); 41395967Speter } 414127326Smarkm clear(); 41595967Speter break; 41695967Speter 417127326Smarkm case 'S': 41895967Speter /* Set Bootable */ 41995967Speter chunk_info[current_chunk]->flags |= CHUNK_ACTIVE; 42095967Speter break; 421127326Smarkm 42295967Speter case 'U': 423127326Smarkm if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) { 42495967Speter msgConfirm("You've already written this information out - you\n" 425127326Smarkm "can't undo it."); 42695967Speter } 427127326Smarkm else if (!msgYesNo("Are you SURE you want to Undo everything?")) { 42895967Speter char cp[BUFSIZ]; 429127326Smarkm 43095967Speter sstrncpy(cp, d->name, sizeof cp); 431127326Smarkm Free_Disk(dev->private); 432127326Smarkm d = Open_Disk(cp); 43395967Speter if (!d) 43495967Speter msgConfirm("Can't reopen disk %s! Internal state is probably corrupted", cp); 435127326Smarkm dev->private = d; 43695967Speter variable_unset(DISK_PARTITIONED); 43795967Speter variable_unset(DISK_LABELLED); 43895967Speter if (d) 43995967Speter record_chunks(d); 44095967Speter } 44195967Speter clear(); 44295967Speter break; 44395967Speter 44495967Speter case 'W': 44595967Speter if (!msgYesNo("WARNING: This should only be used when modifying an EXISTING\n" 44695967Speter "installation. If you are installing FreeBSD for the first time\n" 44795967Speter "then you should simply type Q when you're finished here and your\n" 44895967Speter "changes will be committed in one batch automatically at the end of\n" 44995967Speter "these questions. If you're adding a disk, you should NOT write\n" 45095967Speter "from this screen, you should do it from the label editor.\n\n" 45195967Speter "Are you absolutely sure you want to do this now?")) { 45295967Speter variable_set2(DISK_PARTITIONED, "yes", 0); 45395967Speter 45495967Speter /* Don't trash the MBR if the first (and therefore only) chunk is marked for a truly dedicated 45595967Speter * disk (i.e., the disklabel starts at sector 0), even in cases where the user has requested 45695967Speter * booteasy or a "standard" MBR -- both would be fatal in this case. 45795967Speter */ 458127326Smarkm#if 0 459127326Smarkm if ((d->chunks->part->flags & CHUNK_FORCE_ALL) != CHUNK_FORCE_ALL 46095967Speter && (mbrContents = getBootMgr(d->name)) != NULL) 461127326Smarkm Set_Boot_Mgr(d, mbrContents); 46295967Speter#else 46395967Speter /* 464127326Smarkm * Don't offer to update the MBR on this disk if the first "real" chunk looks like 46595967Speter * a FreeBSD "all disk" partition, or the disk is entirely FreeBSD. 46695967Speter */ 467127326Smarkm if (((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) && 46895967Speter (mbrContents = getBootMgr(d->name)) != NULL) 46995967Speter Set_Boot_Mgr(d, mbrContents); 47095967Speter#endif 471127326Smarkm 47295967Speter if (DITEM_STATUS(diskPartitionWrite(NULL)) != DITEM_SUCCESS) 473127326Smarkm msgConfirm("Disk partition write returned an error status!"); 47495967Speter else 475127326Smarkm msgConfirm("Wrote FDISK partition information out successfully."); 47695967Speter } 477127326Smarkm clear(); 47895967Speter break; 479127326Smarkm 48095967Speter case '|': 481127326Smarkm if (!msgYesNo("Are you SURE you want to go into Wizard mode?\n" 482127326Smarkm "No seat belts whatsoever are provided!")) { 48395967Speter clear(); 48495967Speter refresh(); 485127326Smarkm slice_wizard(d); 48695967Speter variable_set2(DISK_PARTITIONED, "yes", 0); 48795967Speter record_chunks(d); 48895967Speter } 48995967Speter else 49095967Speter msg = "Wise choice!"; 49195967Speter clear(); 49295967Speter break; 49395967Speter 49495967Speter case '\033': /* ESC */ 49595967Speter case 'Q': 49695967Speter chunking = FALSE; 49795967Speter /* Don't trash the MBR if the first (and therefore only) chunk is marked for a truly dedicated 49895967Speter * disk (i.e., the disklabel starts at sector 0), even in cases where the user has requested 49995967Speter * booteasy or a "standard" MBR -- both would be fatal in this case. 50095967Speter */ 50195967Speter#if 0 50295967Speter if ((d->chunks->part->flags & CHUNK_FORCE_ALL) != CHUNK_FORCE_ALL 50395967Speter && (mbrContents = getBootMgr(d->name)) != NULL) 50495967Speter Set_Boot_Mgr(d, mbrContents); 50595967Speter#else 50695967Speter /* 50795967Speter * Don't offer to update the MBR on this disk if the first "real" chunk looks like 508127326Smarkm * a FreeBSD "all disk" partition, or the disk is entirely FreeBSD. 509127326Smarkm */ 51095967Speter if (((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) && 511127326Smarkm (mbrContents = getBootMgr(d->name)) != NULL) 51295967Speter Set_Boot_Mgr(d, mbrContents); 51395967Speter#endif 514127326Smarkm break; 51595967Speter 51695967Speter default: 517127326Smarkm beep(); 51895967Speter msg = "Type F1 or ? for help"; 51995967Speter break; 52095967Speter } 521127326Smarkm } 52295967Speter p = CheckRules(d); 523127326Smarkm if (p) { 52495967Speter char buf[FILENAME_MAX]; 525127326Smarkm 52695967Speter dialog_clear_norefresh(); 527127326Smarkm use_helpline("Press F1 to read more about disk slices."); 52895967Speter use_helpfile(systemHelpFile("partition", buf)); 529127326Smarkm if (!variable_get(VAR_NO_WARN)) 53095967Speter dialog_mesgbox("Disk slicing warning:", p, -1, -1); 531127326Smarkm free(p); 532127326Smarkm } 53395967Speter restorescr(w); 53495967Speter} 535127326Smarkm 53695967Speterstatic u_char * 53795967Speterbootalloc(char *name) 53895967Speter{ 53995967Speter char buf[FILENAME_MAX]; 54095967Speter struct stat sb; 54195967Speter 54295967Speter snprintf(buf, sizeof buf, "/boot/%s", name); 54395967Speter if (stat(buf, &sb) != -1) { 54495967Speter int fd; 54595967Speter 54695967Speter fd = open(buf, O_RDONLY); 54795967Speter if (fd != -1) { 54895967Speter u_char *cp; 54995967Speter 55095967Speter cp = malloc(sb.st_size); 55195967Speter if (read(fd, cp, sb.st_size) != sb.st_size) { 55295967Speter free(cp); 55395967Speter close(fd); 55495967Speter msgDebug("bootalloc: couldn't read %d bytes from %s\n", sb.st_size, buf); 55595967Speter return NULL; 55695967Speter } 55795967Speter close(fd); 558127326Smarkm return cp; 559127326Smarkm } 56095967Speter msgDebug("bootalloc: couldn't open %s\n", buf); 561127326Smarkm } 56295967Speter else 56395967Speter msgDebug("bootalloc: can't stat %s\n", buf); 564127326Smarkm return NULL; 56595967Speter} 56695967Speter 567127326Smarkmstatic int 56895967SpeterpartitionHook(dialogMenuItem *selected) 56995967Speter{ 57095967Speter Device **devs = NULL; 571127326Smarkm 57295967Speter devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 573127326Smarkm if (!devs) { 57495967Speter msgConfirm("Unable to find disk %s!", selected->prompt); 575127326Smarkm return DITEM_FAILURE; 57695967Speter } 577127326Smarkm /* Toggle enabled status? */ 57895967Speter if (!devs[0]->enabled) { 579127326Smarkm devs[0]->enabled = TRUE; 58095967Speter diskPartition(devs[0]); 581127326Smarkm } 582127326Smarkm else 58395967Speter devs[0]->enabled = FALSE; 58495967Speter return DITEM_SUCCESS | DITEM_RESTORE; 585127326Smarkm} 58695967Speter 58795967Speterstatic int 58895967SpeterpartitionCheck(dialogMenuItem *selected) 58995967Speter{ 59095967Speter Device **devs = NULL; 59195967Speter 59295967Speter devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 59395967Speter if (!devs || devs[0]->enabled == FALSE) 59495967Speter return FALSE; 59595967Speter return TRUE; 59695967Speter} 59795967Speter 59895967Speterint 59995967SpeterdiskPartitionEditor(dialogMenuItem *self) 60095967Speter{ 60195967Speter DMenu *menu; 60295967Speter Device **devs; 60395967Speter int i, cnt, devcnt; 60495967Speter 60595967Speter cnt = diskGetSelectCount(&devs); 60695967Speter devcnt = deviceCount(devs); 60795967Speter if (cnt == -1) { 608127326Smarkm msgConfirm("No disks found! Please verify that your disk controller is being\n" 609127326Smarkm "properly probed at boot time. See the Hardware Guide on the\n" 61095967Speter "Documentation menu for clues on diagnosing this type of problem."); 611127326Smarkm return DITEM_FAILURE; 61295967Speter } 61395967Speter else if (cnt) { 614127326Smarkm /* Some are already selected */ 61595967Speter for (i = 0; i < devcnt; i++) { 61695967Speter if (devs[i]->enabled) { 617127326Smarkm if (variable_get(VAR_NONINTERACTIVE)) 61895967Speter diskPartitionNonInteractive(devs[i]); 61995967Speter else 62095967Speter diskPartition(devs[i]); 621127326Smarkm } 62295967Speter } 623127326Smarkm } 62495967Speter else { 625127326Smarkm /* No disks are selected, fall-back case now */ 62695967Speter if (devcnt == 1) { 627127326Smarkm devs[0]->enabled = TRUE; 62895967Speter if (variable_get(VAR_NONINTERACTIVE)) 629127326Smarkm diskPartitionNonInteractive(devs[0]); 63095967Speter else 631127326Smarkm diskPartition(devs[0]); 632127326Smarkm return DITEM_SUCCESS; 63395967Speter } 63495967Speter else { 635127326Smarkm menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook, partitionCheck); 63695967Speter if (!menu) { 63795967Speter msgConfirm("No devices suitable for installation found!\n\n" 63895967Speter "Please verify that your disk controller (and attached drives)\n" 63995967Speter "were detected properly. This can be done by pressing the\n" 64095967Speter "[Scroll Lock] key and using the Arrow keys to move back to\n" 64195967Speter "the boot messages. Press [Scroll Lock] again to return."); 64295967Speter return DITEM_FAILURE; 64395967Speter } 64495967Speter else { 64595967Speter i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; 64695967Speter free(menu); 64795967Speter } 64895967Speter return i | DITEM_RESTORE; 64995967Speter } 65095967Speter } 65195967Speter return DITEM_SUCCESS; 65295967Speter} 65395967Speter 65495967Speterint 65595967SpeterdiskPartitionWrite(dialogMenuItem *self) 65695967Speter{ 65795967Speter Device **devs; 658127326Smarkm int i; 659127326Smarkm char *cp; 66095967Speter 661127326Smarkm devs = deviceFind(NULL, DEVICE_TYPE_DISK); 66295967Speter if (!devs) { 66395967Speter msgConfirm("Unable to find any disks to write to??"); 664127326Smarkm return DITEM_FAILURE; 66595967Speter } 66695967Speter if (isDebug()) 667127326Smarkm msgDebug("diskPartitionWrite: Examining %d devices\n", deviceCount(devs)); 66895967Speter cp = variable_get(DISK_PARTITIONED); 66995967Speter if (cp && !strcmp(cp, "written")) 67095967Speter return DITEM_SUCCESS; 671127326Smarkm 67295967Speter for (i = 0; devs[i]; i++) { 673127326Smarkm Chunk *c1; 67495967Speter Disk *d = (Disk *)devs[i]->private; 675127326Smarkm static u_char *boot1; 67695967Speter#ifndef __alpha__ 677127326Smarkm static u_char *boot2; 67895967Speter#endif 679127326Smarkm 68095967Speter if (!devs[i]->enabled) 681127326Smarkm continue; 682127326Smarkm 68395967Speter#ifdef __alpha__ 68495967Speter if (!boot1) boot1 = bootalloc("boot1"); 685127326Smarkm Set_Boot_Blocks(d, boot1, NULL); 68695967Speter#else 68795967Speter if (!boot1) boot1 = bootalloc("boot1"); 68895967Speter if (!boot2) boot2 = bootalloc("boot2"); 68995967Speter Set_Boot_Blocks(d, boot1, boot2); 69095967Speter#endif 69195967Speter 69295967Speter msgNotify("Writing partition information to drive %s", d->name); 69395967Speter if (!Fake && Write_Disk(d)) { 69495967Speter msgConfirm("ERROR: Unable to write data to disk %s!", d->name); 69595967Speter return DITEM_FAILURE; 69695967Speter } 69795967Speter 69895967Speter /* If we've been through here before, we don't need to do the rest */ 69995967Speter if (cp && !strcmp(cp, "written")) 70095967Speter return DITEM_SUCCESS; 70195967Speter 70295967Speter /* Now scan for bad blocks, if necessary */ 70395967Speter for (c1 = d->chunks->part; c1; c1 = c1->next) { 70495967Speter if (c1->flags & CHUNK_BAD144) { 70595967Speter int ret; 70695967Speter 70795967Speter msgNotify("Running bad block scan on slice %s", c1->name); 708127326Smarkm if (!Fake) { 709127326Smarkm ret = vsystem("bad144 -v /dev/r%s 1234", c1->name); 71095967Speter if (ret) 711127326Smarkm msgConfirm("Bad144 init on %s returned status of %d!", c1->name, ret); 71295967Speter ret = vsystem("bad144 -v -s /dev/r%s", c1->name); 71395967Speter if (ret) 714127326Smarkm msgConfirm("Bad144 scan on %s returned status of %d!", c1->name, ret); 71595967Speter } 71695967Speter } 717127326Smarkm } 71895967Speter } 71995967Speter /* Now it's not "yes", but "written" */ 72095967Speter variable_set2(DISK_PARTITIONED, "written", 0); 721127326Smarkm return DITEM_SUCCESS; 72295967Speter} 723127326Smarkm 72495967Speter/* Partition a disk based wholly on which variables are set */ 725127326Smarkmstatic void 72695967SpeterdiskPartitionNonInteractive(Device *dev) 727127326Smarkm{ 72895967Speter char *cp; 729127326Smarkm int i, sz, all_disk = 0; 73095967Speter u_char *mbrContents; 731127326Smarkm Disk *d = (Disk *)dev->private; 732127326Smarkm 73395967Speter record_chunks(d); 73495967Speter cp = variable_get(VAR_GEOMETRY); 735127326Smarkm if (cp) { 73695967Speter msgDebug("Setting geometry from script to: %s\n", cp); 73795967Speter d->bios_cyl = strtol(cp, &cp, 0); 73895967Speter d->bios_hd = strtol(cp + 1, &cp, 0); 73995967Speter d->bios_sect = strtol(cp + 1, 0, 0); 74095967Speter } 74195967Speter 74295967Speter cp = variable_get(VAR_PARTITION); 74395967Speter if (cp) { 74495967Speter if (!strcmp(cp, "free")) { 74595967Speter /* Do free disk space case */ 74695967Speter for (i = 0; chunk_info[i]; i++) { 74795967Speter /* If a chunk is at least 10MB in size, use it. */ 74895967Speter if (chunk_info[i]->type == unused && chunk_info[i]->size > (10 * ONE_MEG)) { 74995967Speter Create_Chunk(d, chunk_info[i]->offset, chunk_info[i]->size, freebsd, 3, 75095967Speter (chunk_info[i]->flags & CHUNK_ALIGN)); 75195967Speter variable_set2(DISK_PARTITIONED, "yes", 0); 75295967Speter break; 75395967Speter } 75495967Speter } 75595967Speter if (!chunk_info[i]) { 75695967Speter dialog_clear(); 75795967Speter msgConfirm("Unable to find any free space on this disk!"); 758127326Smarkm return; 759127326Smarkm } 76095967Speter } 761127326Smarkm else if (!strcmp(cp, "all")) { 76295967Speter /* Do all disk space case */ 76395967Speter msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); 764127326Smarkm 76595967Speter All_FreeBSD(d, FALSE); 76695967Speter } 767127326Smarkm else if (!strcmp(cp, "exclusive")) { 76895967Speter /* Do really-all-the-disk-space case */ 76995967Speter msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); 77095967Speter 771127326Smarkm All_FreeBSD(d, all_disk = TRUE); 77295967Speter } 773127326Smarkm else if ((sz = strtol(cp, &cp, 0))) { 77495967Speter /* Look for sz bytes free */ 775127326Smarkm if (*cp && toupper(*cp) == 'M') 77695967Speter sz *= ONE_MEG; 777127326Smarkm for (i = 0; chunk_info[i]; i++) { 77895967Speter /* If a chunk is at least sz MB, use it. */ 779127326Smarkm if (chunk_info[i]->type == unused && chunk_info[i]->size >= sz) { 78095967Speter Create_Chunk(d, chunk_info[i]->offset, sz, freebsd, 3, (chunk_info[i]->flags & CHUNK_ALIGN)); 781127326Smarkm variable_set2(DISK_PARTITIONED, "yes", 0); 782127326Smarkm break; 78395967Speter } 78495967Speter } 785127326Smarkm if (!chunk_info[i]) { 78695967Speter dialog_clear(); 78795967Speter msgConfirm("Unable to find %d free blocks on this disk!", sz); 78895967Speter return; 78995967Speter } 79095967Speter } 79195967Speter else if (!strcmp(cp, "existing")) { 79295967Speter /* Do existing FreeBSD case */ 79395967Speter for (i = 0; chunk_info[i]; i++) { 79495967Speter if (chunk_info[i]->type == freebsd) 79595967Speter break; 79695967Speter } 79795967Speter if (!chunk_info[i]) { 79895967Speter dialog_clear(); 79995967Speter msgConfirm("Unable to find any existing FreeBSD partitions on this disk!"); 80095967Speter return; 80195967Speter } 80295967Speter } 80395967Speter else { 80495967Speter dialog_clear(); 80595967Speter msgConfirm("`%s' is an invalid value for %s - is config file valid?", cp, VAR_PARTITION); 80695967Speter return; 80795967Speter } 808127326Smarkm if (!all_disk) { 809127326Smarkm mbrContents = getBootMgr(d->name); 81095967Speter Set_Boot_Mgr(d, mbrContents); 811127326Smarkm } 81295967Speter variable_set2(DISK_PARTITIONED, "yes", 0); 81395967Speter } 814127326Smarkm} 81595967Speter