disks.c revision 42247
1/* 2 * The new sysinstall program. 3 * 4 * This is probably the last program in the `sysinstall' line - the next 5 * generation being essentially a complete rewrite. 6 * 7 * $Id: disks.c,v 1.106 1998/10/13 09:49:16 jkh Exp $ 8 * 9 * Copyright (c) 1995 10 * Jordan Hubbard. All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer, 17 * verbatim and that no modifications are made prior to this 18 * point in the file. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 23 * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 */ 36 37#include "sysinstall.h" 38#include <ctype.h> 39#include <fcntl.h> 40#include <sys/stat.h> 41#include <sys/disklabel.h> 42 43/* Where we start displaying chunk information on the screen */ 44#define CHUNK_START_ROW 5 45 46/* Where we keep track of MBR chunks */ 47static struct chunk *chunk_info[16]; 48static int current_chunk; 49 50static void diskPartitionNonInteractive(Device *dev); 51 52static void 53record_chunks(Disk *d) 54{ 55 struct chunk *c1 = NULL; 56 int i = 0; 57 int last_free = 0; 58 59 if (!d->chunks) 60 msgFatal("No chunk list found for %s!", d->name); 61 62 for (c1 = d->chunks->part; c1; c1 = c1->next) { 63 if (c1->type == unused && c1->size > last_free) { 64 last_free = c1->size; 65 current_chunk = i; 66 } 67 chunk_info[i++] = c1; 68 } 69 chunk_info[i] = NULL; 70 if (current_chunk >= i) 71 current_chunk = i - 1; 72} 73 74static int Total; 75 76static void 77print_chunks(Disk *d) 78{ 79 int row; 80 int i; 81 82 for (i = Total = 0; chunk_info[i]; i++) 83 Total += chunk_info[i]->size; 84 if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) { 85 dialog_clear_norefresh(); 86 msgConfirm("WARNING: A geometry of %d/%d/%d for %s is incorrect. Using\n" 87 "a more likely geometry. If this geometry is incorrect or you\n" 88 "are unsure as to whether or not it's correct, please consult\n" 89 "the Hardware Guide in the Documentation submenu or use the\n" 90 "(G)eometry command to change it now.\n\n" 91 "Remember: you need to enter whatever your BIOS thinks the\n" 92 "geometry is! For IDE, it's what you were told in the BIOS\n" 93 "setup. For SCSI, it's the translation mode your controller is\n" 94 "using. Do NOT use a ``physical geometry''.", 95 d->bios_cyl, d->bios_hd, d->bios_sect, d->name); 96 Sanitize_Bios_Geom(d); 97 } 98 attrset(A_NORMAL); 99 mvaddstr(0, 0, "Disk name:\t"); 100 clrtobot(); 101 attrset(A_REVERSE); addstr(d->name); attrset(A_NORMAL); 102 attrset(A_REVERSE); mvaddstr(0, 55, "FDISK Partition Editor"); attrset(A_NORMAL); 103 mvprintw(1, 0, 104 "DISK Geometry:\t%lu cyls/%lu heads/%lu sectors = %lu sectors", 105 d->bios_cyl, d->bios_hd, d->bios_sect, 106 d->bios_cyl * d->bios_hd * d->bios_sect); 107 mvprintw(3, 0, "%10s %10s %10s %8s %6s %10s %8s %8s", 108 "Offset", "Size", "End", "Name", "PType", "Desc", 109 "Subtype", "Flags"); 110 for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) { 111 if (i == current_chunk) 112 attrset(ATTR_SELECTED); 113 mvprintw(row, 0, "%10ld %10lu %10lu %8s %6d %10s %8d\t%-6s", 114 chunk_info[i]->offset, chunk_info[i]->size, 115 chunk_info[i]->end, chunk_info[i]->name, 116 chunk_info[i]->type, 117 slice_type_name(chunk_info[i]->type, chunk_info[i]->subtype), 118 chunk_info[i]->subtype, ShowChunkFlags(chunk_info[i])); 119 if (i == current_chunk) 120 attrset(A_NORMAL); 121 } 122} 123 124static void 125print_command_summary() 126{ 127 mvprintw(14, 0, "The following commands are supported (in upper or lower case):"); 128 mvprintw(16, 0, "A = Use Entire Disk B = Bad Block Scan C = Create Slice"); 129 mvprintw(17, 0, "D = Delete Slice G = Set Drive Geometry S = Set Bootable"); 130 mvprintw(18, 0, "T = Change Type U = Undo All Changes Q = Finish"); 131 if (!RunningAsInit) 132 mvprintw(18, 48, "W = Write Changes"); 133 mvprintw(21, 0, "Use F1 or ? to get more help, arrow keys to select."); 134 move(0, 0); 135} 136 137static u_char * 138getBootMgr(char *dname) 139{ 140#ifndef __alpha__ /* only meaningful on x86 */ 141 extern u_char mbr[], boot0[]; 142 char str[80]; 143 char *cp; 144 int i = 0; 145 146 cp = variable_get(VAR_BOOTMGR); 147 if (!cp) { 148 /* Figure out what kind of MBR the user wants */ 149 sprintf(str, "Install Boot Manager for drive %s?", dname); 150 MenuMBRType.title = str; 151 i = dmenuOpenSimple(&MenuMBRType, FALSE); 152 } 153 else { 154 if (!strncmp(cp, "boot", 4)) 155 BootMgr = 0; 156 else if (!strcmp(cp, "standard")) 157 BootMgr = 1; 158 else 159 BootMgr = 2; 160 } 161 if (cp || i) { 162 switch (BootMgr) { 163 case 0: 164 return boot0; 165 166 case 1: 167 return mbr; 168 169 case 2: 170 default: 171 break; 172 } 173 } 174#endif 175 return NULL; 176} 177 178int 179diskGetSelectCount(Device ***devs) 180{ 181 int i, cnt, enabled; 182 char *cp; 183 Device **dp; 184 185 cp = variable_get(VAR_DISK); 186 dp = *devs = deviceFind(cp, DEVICE_TYPE_DISK); 187 cnt = deviceCount(dp); 188 if (!cnt) 189 return -1; 190 for (i = 0, enabled = 0; i < cnt; i++) { 191 if (dp[i]->enabled) 192 ++enabled; 193 } 194 return enabled; 195} 196 197void 198diskPartition(Device *dev) 199{ 200 char *cp, *p; 201 int rv, key = 0; 202 Boolean chunking; 203 char *msg = NULL; 204 u_char *mbrContents; 205 WINDOW *w = savescr(); 206 Disk *d = (Disk *)dev->private; 207 208 chunking = TRUE; 209 keypad(stdscr, TRUE); 210 211 /* Flush both the dialog and curses library views of the screen 212 since we don't always know who called us */ 213 dialog_clear_norefresh(), clear(); 214 current_chunk = 0; 215 216 /* Set up the chunk array */ 217 record_chunks(d); 218 219 while (chunking) { 220 char *val, geometry[80]; 221 222 /* Now print our overall state */ 223 if (d) 224 print_chunks(d); 225 print_command_summary(); 226 if (msg) { 227 attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL); 228 beep(); 229 msg = NULL; 230 } 231 else { 232 move(23, 0); 233 clrtoeol(); 234 } 235 236 /* Get command character */ 237 key = getch(); 238 switch (toupper(key)) { 239 case '\014': /* ^L (redraw) */ 240 clear(); 241 msg = NULL; 242 break; 243 244 case '\020': /* ^P */ 245 case KEY_UP: 246 case '-': 247 if (current_chunk != 0) 248 --current_chunk; 249 break; 250 251 case '\016': /* ^N */ 252 case KEY_DOWN: 253 case '+': 254 case '\r': 255 case '\n': 256 if (chunk_info[current_chunk + 1]) 257 ++current_chunk; 258 break; 259 260 case KEY_HOME: 261 current_chunk = 0; 262 break; 263 264 case KEY_END: 265 while (chunk_info[current_chunk + 1]) 266 ++current_chunk; 267 break; 268 269 case KEY_F(1): 270 case '?': 271 systemDisplayHelp("slice"); 272 clear(); 273 break; 274 275 case 'A': 276#ifdef __alpha__ 277 rv = 1; 278#else /* The rest is only relevant on x86 */ 279 cp = variable_get(VAR_DEDICATE_DISK); 280 if (cp && !strcasecmp(cp, "always")) 281 rv = 1; 282 else { 283 rv = msgYesNo("Do you want to do this with a true partition entry\n" 284 "so as to remain cooperative with any future possible\n" 285 "operating systems on the drive(s)?\n" 286 "(See also the section about ``dangerously dedicated''\n" 287 "disks in the FreeBSD FAQ.)"); 288 if (rv == -1) 289 rv = 0; 290 } 291#endif 292 All_FreeBSD(d, rv); 293 variable_set2(DISK_PARTITIONED, "yes"); 294 record_chunks(d); 295 clear(); 296 break; 297 298 case 'B': 299 if (chunk_info[current_chunk]->type != freebsd) 300 msg = "Can only scan for bad blocks in FreeBSD slice."; 301 else if (strncmp(d->name, "sd", 2) || 302 strncmp(d->name, "da", 2) || 303 !msgYesNo("This typically makes sense only for ESDI, IDE or MFM drives.\n" 304 "Are you sure you want to do this on a SCSI disk?")) { 305 if (chunk_info[current_chunk]->flags & CHUNK_BAD144) 306 chunk_info[current_chunk]->flags &= ~CHUNK_BAD144; 307 else 308 chunk_info[current_chunk]->flags |= CHUNK_BAD144; 309 } 310 clear(); 311 break; 312 313 case 'C': 314 if (chunk_info[current_chunk]->type != unused) 315 msg = "Slice in use, delete it first or move to an unused one."; 316 else { 317 char *val, tmp[20], *cp; 318 int size, subtype; 319 chunk_e partitiontype; 320 321 snprintf(tmp, 20, "%lu", chunk_info[current_chunk]->size); 322 val = msgGetInput(tmp, "Please specify the size for new FreeBSD slice in blocks\n" 323 "or append a trailing `M' for megabytes (e.g. 20M)."); 324 if (val && (size = strtol(val, &cp, 0)) > 0) { 325 if (*cp && toupper(*cp) == 'M') 326 size *= ONE_MEG; 327 strcpy(tmp, "165"); 328 val = msgGetInput(tmp, "Enter type of partition to create:\n\n" 329 "Pressing Enter will choose the default, a native FreeBSD\n" 330 "slice (type 165). You can choose other types, 6 for a\n" 331 "DOS partition or 131 for a Linux partition, for example.\n\n" 332 "Note: If you choose a non-FreeBSD partition type, it will not\n" 333 "be formatted or otherwise prepared, it will simply reserve space\n" 334 "for you to use another tool, such as DOS FORMAT, to later format\n" 335 "and use the partition."); 336 if (val && (subtype = strtol(val, NULL, 0)) > 0) { 337 if (subtype == 165) 338 partitiontype = freebsd; 339 else if (subtype == 6) 340 partitiontype = fat; 341 else 342 partitiontype = unknown; 343#ifdef __alpha__ 344 if (partitiontype == freebsd && size == chunk_info[current_chunk]->size) 345 All_FreeBSD(d, 1); 346 else 347#endif 348 Create_Chunk(d, chunk_info[current_chunk]->offset, size, partitiontype, subtype, 349 (chunk_info[current_chunk]->flags & CHUNK_ALIGN)); 350 variable_set2(DISK_PARTITIONED, "yes"); 351 record_chunks(d); 352 } 353 } 354 clear(); 355 } 356 break; 357 358 case KEY_DC: 359 case 'D': 360 if (chunk_info[current_chunk]->type == unused) 361 msg = "Slice is already unused!"; 362 else { 363 Delete_Chunk(d, chunk_info[current_chunk]); 364 variable_set2(DISK_PARTITIONED, "yes"); 365 record_chunks(d); 366 } 367 break; 368 369 case 'T': 370 if (chunk_info[current_chunk]->type == unused) 371 msg = "Slice is currently unused (use create instead)"; 372 else { 373 char *val, tmp[20]; 374 int subtype; 375 chunk_e partitiontype; 376 WINDOW *save = savescr(); 377 378 strcpy(tmp, "165"); 379 val = msgGetInput(tmp, "New partition type:\n\n" 380 "Pressing Enter will choose the default, a native FreeBSD\n" 381 "slice (type 165). Other popular values are 6 for\n" 382 "DOS FAT partition, 131 for a Linux ext2fs partition or\n" 383 "130 for a Linux swap partition.\n\n" 384 "Note: If you choose a non-FreeBSD partition type, it will not\n" 385 "be formatted or otherwise prepared, it will simply reserve space\n" 386 "for you to use another tool, such as DOS format, to later format\n" 387 "and actually use the partition."); 388 if (val && (subtype = strtol(val, NULL, 0)) > 0) { 389 if (subtype == 165) 390 partitiontype = freebsd; 391 else if (subtype == 6) 392 partitiontype = fat; 393 else 394 partitiontype = unknown; 395 chunk_info[current_chunk]->type = partitiontype; 396 chunk_info[current_chunk]->subtype = subtype; 397 } 398 restorescr(save); 399 } 400 break; 401 402 case 'G': 403 snprintf(geometry, 80, "%lu/%lu/%lu", d->bios_cyl, d->bios_hd, d->bios_sect); 404 val = msgGetInput(geometry, "Please specify the new geometry in cyl/hd/sect format.\n" 405 "Don't forget to use the two slash (/) separator characters!\n" 406 "It's not possible to parse the field without them."); 407 if (val) { 408 long nc, nh, ns; 409 nc = strtol(val, &val, 0); 410 nh = strtol(val + 1, &val, 0); 411 ns = strtol(val + 1, 0, 0); 412 Set_Bios_Geom(d, nc, nh, ns); 413 } 414 clear(); 415 break; 416 417 case 'S': 418 /* Set Bootable */ 419 chunk_info[current_chunk]->flags |= CHUNK_ACTIVE; 420 break; 421 422 case 'U': 423 if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) { 424 msgConfirm("You've already written this information out - you\n" 425 "can't undo it."); 426 } 427 else if (!msgYesNo("Are you SURE you want to Undo everything?")) { 428 char cp[BUFSIZ]; 429 430 sstrncpy(cp, d->name, sizeof cp); 431 Free_Disk(dev->private); 432 d = Open_Disk(cp); 433 if (!d) 434 msgConfirm("Can't reopen disk %s! Internal state is probably corrupted", cp); 435 dev->private = d; 436 variable_unset(DISK_PARTITIONED); 437 variable_unset(DISK_LABELLED); 438 if (d) 439 record_chunks(d); 440 } 441 clear(); 442 break; 443 444 case 'W': 445 if (!msgYesNo("WARNING: This should only be used when modifying an EXISTING\n" 446 "installation. If you are installing FreeBSD for the first time\n" 447 "then you should simply type Q when you're finished here and your\n" 448 "changes will be committed in one batch automatically at the end of\n" 449 "these questions. If you're adding a disk, you should NOT write\n" 450 "from this screen, you should do it from the label editor.\n\n" 451 "Are you absolutely sure you want to do this now?")) { 452 variable_set2(DISK_PARTITIONED, "yes"); 453 454 /* Don't trash the MBR if the first (and therefore only) chunk is marked for a truly dedicated 455 * disk (i.e., the disklabel starts at sector 0), even in cases where the user has requested 456 * booteasy or a "standard" MBR -- both would be fatal in this case. 457 */ 458#if 0 459 if ((d->chunks->part->flags & CHUNK_FORCE_ALL) != CHUNK_FORCE_ALL 460 && (mbrContents = getBootMgr(d->name)) != NULL) 461 Set_Boot_Mgr(d, mbrContents); 462#else 463 /* 464 * Don't offer to update the MBR on this disk if the first "real" chunk looks like 465 * a FreeBSD "all disk" partition, or the disk is entirely FreeBSD. 466 */ 467 if (((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) && 468 (mbrContents = getBootMgr(d->name)) != NULL) 469 Set_Boot_Mgr(d, mbrContents); 470#endif 471 472 if (DITEM_STATUS(diskPartitionWrite(NULL)) != DITEM_SUCCESS) 473 msgConfirm("Disk partition write returned an error status!"); 474 else 475 msgConfirm("Wrote FDISK partition information out successfully."); 476 } 477 clear(); 478 break; 479 480 case '|': 481 if (!msgYesNo("Are you SURE you want to go into Wizard mode?\n" 482 "No seat belts whatsoever are provided!")) { 483 clear(); 484 refresh(); 485 slice_wizard(d); 486 variable_set2(DISK_PARTITIONED, "yes"); 487 record_chunks(d); 488 } 489 else 490 msg = "Wise choice!"; 491 clear(); 492 break; 493 494 case '\033': /* ESC */ 495 case 'Q': 496 chunking = FALSE; 497 /* Don't trash the MBR if the first (and therefore only) chunk is marked for a truly dedicated 498 * disk (i.e., the disklabel starts at sector 0), even in cases where the user has requested 499 * booteasy or a "standard" MBR -- both would be fatal in this case. 500 */ 501#if 0 502 if ((d->chunks->part->flags & CHUNK_FORCE_ALL) != CHUNK_FORCE_ALL 503 && (mbrContents = getBootMgr(d->name)) != NULL) 504 Set_Boot_Mgr(d, mbrContents); 505#else 506 /* 507 * Don't offer to update the MBR on this disk if the first "real" chunk looks like 508 * a FreeBSD "all disk" partition, or the disk is entirely FreeBSD. 509 */ 510 if (((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) && 511 (mbrContents = getBootMgr(d->name)) != NULL) 512 Set_Boot_Mgr(d, mbrContents); 513#endif 514 break; 515 516 default: 517 beep(); 518 msg = "Type F1 or ? for help"; 519 break; 520 } 521 } 522 p = CheckRules(d); 523 if (p) { 524 char buf[FILENAME_MAX]; 525 526 dialog_clear_norefresh(); 527 use_helpline("Press F1 to read more about disk slices."); 528 use_helpfile(systemHelpFile("partition", buf)); 529 if (!variable_get(VAR_NO_WARN)) 530 dialog_mesgbox("Disk slicing warning:", p, -1, -1); 531 free(p); 532 } 533 restorescr(w); 534} 535 536static u_char * 537bootalloc(char *name) 538{ 539 char buf[FILENAME_MAX]; 540 struct stat sb; 541 542 snprintf(buf, sizeof buf, "/boot/%s", name); 543 if (stat(buf, &sb) != -1) { 544 int fd; 545 546 fd = open(buf, O_RDONLY); 547 if (fd != -1) { 548 u_char *cp; 549 550 cp = malloc(sb.st_size); 551 if (read(fd, cp, sb.st_size) != sb.st_size) { 552 free(cp); 553 close(fd); 554 msgDebug("bootalloc: couldn't read %d bytes from %s\n", sb.st_size, buf); 555 return NULL; 556 } 557 close(fd); 558 return cp; 559 } 560 msgDebug("bootalloc: couldn't open %s\n", buf); 561 } 562 else 563 msgDebug("bootalloc: can't stat %s\n", buf); 564 return NULL; 565} 566 567static int 568partitionHook(dialogMenuItem *selected) 569{ 570 Device **devs = NULL; 571 572 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 573 if (!devs) { 574 msgConfirm("Unable to find disk %s!", selected->prompt); 575 return DITEM_FAILURE; 576 } 577 /* Toggle enabled status? */ 578 if (!devs[0]->enabled) { 579 devs[0]->enabled = TRUE; 580 diskPartition(devs[0]); 581 } 582 else 583 devs[0]->enabled = FALSE; 584 return DITEM_SUCCESS | DITEM_RESTORE; 585} 586 587static int 588partitionCheck(dialogMenuItem *selected) 589{ 590 Device **devs = NULL; 591 592 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 593 if (!devs || devs[0]->enabled == FALSE) 594 return FALSE; 595 return TRUE; 596} 597 598int 599diskPartitionEditor(dialogMenuItem *self) 600{ 601 DMenu *menu; 602 Device **devs; 603 int i, cnt, devcnt; 604 605 cnt = diskGetSelectCount(&devs); 606 devcnt = deviceCount(devs); 607 if (cnt == -1) { 608 msgConfirm("No disks found! Please verify that your disk controller is being\n" 609 "properly probed at boot time. See the Hardware Guide on the\n" 610 "Documentation menu for clues on diagnosing this type of problem."); 611 return DITEM_FAILURE; 612 } 613 else if (cnt) { 614 /* Some are already selected */ 615 for (i = 0; i < devcnt; i++) { 616 if (devs[i]->enabled) { 617 if (variable_get(VAR_NONINTERACTIVE)) 618 diskPartitionNonInteractive(devs[i]); 619 else 620 diskPartition(devs[i]); 621 } 622 } 623 } 624 else { 625 /* No disks are selected, fall-back case now */ 626 if (devcnt == 1) { 627 devs[0]->enabled = TRUE; 628 if (variable_get(VAR_NONINTERACTIVE)) 629 diskPartitionNonInteractive(devs[0]); 630 else 631 diskPartition(devs[0]); 632 return DITEM_SUCCESS; 633 } 634 else { 635 menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook, partitionCheck); 636 if (!menu) { 637 msgConfirm("No devices suitable for installation found!\n\n" 638 "Please verify that your disk controller (and attached drives)\n" 639 "were detected properly. This can be done by pressing the\n" 640 "[Scroll Lock] key and using the Arrow keys to move back to\n" 641 "the boot messages. Press [Scroll Lock] again to return."); 642 return DITEM_FAILURE; 643 } 644 else { 645 i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; 646 free(menu); 647 } 648 return i | DITEM_RESTORE; 649 } 650 } 651 return DITEM_SUCCESS; 652} 653 654int 655diskPartitionWrite(dialogMenuItem *self) 656{ 657 Device **devs; 658 int i; 659 char *cp; 660 661 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 662 if (!devs) { 663 msgConfirm("Unable to find any disks to write to??"); 664 return DITEM_FAILURE; 665 } 666 if (isDebug()) 667 msgDebug("diskPartitionWrite: Examining %d devices\n", deviceCount(devs)); 668 cp = variable_get(DISK_PARTITIONED); 669 if (cp && !strcmp(cp, "written")) 670 return DITEM_SUCCESS; 671 672 for (i = 0; devs[i]; i++) { 673 Chunk *c1; 674 Disk *d = (Disk *)devs[i]->private; 675 static u_char *boot1; 676 static u_char *boot2; 677 678 if (!devs[i]->enabled) 679 continue; 680 681 if (!boot1) boot1 = bootalloc("boot1"); 682 if (!boot2) boot2 = bootalloc("boot2"); 683 Set_Boot_Blocks(d, boot1, boot2); 684 685 msgNotify("Writing partition information to drive %s", d->name); 686 if (!Fake && Write_Disk(d)) { 687 msgConfirm("ERROR: Unable to write data to disk %s!", d->name); 688 return DITEM_FAILURE; 689 } 690 691 /* If we've been through here before, we don't need to do the rest */ 692 if (cp && !strcmp(cp, "written")) 693 return DITEM_SUCCESS; 694 695 /* Now scan for bad blocks, if necessary */ 696 for (c1 = d->chunks->part; c1; c1 = c1->next) { 697 if (c1->flags & CHUNK_BAD144) { 698 int ret; 699 700 msgNotify("Running bad block scan on slice %s", c1->name); 701 if (!Fake) { 702 ret = vsystem("bad144 -v /dev/r%s 1234", c1->name); 703 if (ret) 704 msgConfirm("Bad144 init on %s returned status of %d!", c1->name, ret); 705 ret = vsystem("bad144 -v -s /dev/r%s", c1->name); 706 if (ret) 707 msgConfirm("Bad144 scan on %s returned status of %d!", c1->name, ret); 708 } 709 } 710 } 711 } 712 /* Now it's not "yes", but "written" */ 713 variable_set2(DISK_PARTITIONED, "written"); 714 return DITEM_SUCCESS; 715} 716 717/* Partition a disk based wholly on which variables are set */ 718static void 719diskPartitionNonInteractive(Device *dev) 720{ 721 char *cp; 722 int i, sz, all_disk = 0; 723 u_char *mbrContents; 724 Disk *d = (Disk *)dev->private; 725 726 record_chunks(d); 727 cp = variable_get(VAR_GEOMETRY); 728 if (cp) { 729 msgDebug("Setting geometry from script to: %s\n", cp); 730 d->bios_cyl = strtol(cp, &cp, 0); 731 d->bios_hd = strtol(cp + 1, &cp, 0); 732 d->bios_sect = strtol(cp + 1, 0, 0); 733 } 734 735 cp = variable_get(VAR_PARTITION); 736 if (cp) { 737 if (!strcmp(cp, "free")) { 738 /* Do free disk space case */ 739 for (i = 0; chunk_info[i]; i++) { 740 /* If a chunk is at least 10MB in size, use it. */ 741 if (chunk_info[i]->type == unused && chunk_info[i]->size > (10 * ONE_MEG)) { 742 Create_Chunk(d, chunk_info[i]->offset, chunk_info[i]->size, freebsd, 3, 743 (chunk_info[i]->flags & CHUNK_ALIGN)); 744 variable_set2(DISK_PARTITIONED, "yes"); 745 break; 746 } 747 } 748 if (!chunk_info[i]) { 749 dialog_clear(); 750 msgConfirm("Unable to find any free space on this disk!"); 751 return; 752 } 753 } 754 else if (!strcmp(cp, "all")) { 755 /* Do all disk space case */ 756 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); 757 758 All_FreeBSD(d, FALSE); 759 } 760 else if (!strcmp(cp, "exclusive")) { 761 /* Do really-all-the-disk-space case */ 762 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); 763 764 All_FreeBSD(d, all_disk = TRUE); 765 } 766 else if ((sz = strtol(cp, &cp, 0))) { 767 /* Look for sz bytes free */ 768 if (*cp && toupper(*cp) == 'M') 769 sz *= ONE_MEG; 770 for (i = 0; chunk_info[i]; i++) { 771 /* If a chunk is at least sz MB, use it. */ 772 if (chunk_info[i]->type == unused && chunk_info[i]->size >= sz) { 773 Create_Chunk(d, chunk_info[i]->offset, sz, freebsd, 3, (chunk_info[i]->flags & CHUNK_ALIGN)); 774 variable_set2(DISK_PARTITIONED, "yes"); 775 break; 776 } 777 } 778 if (!chunk_info[i]) { 779 dialog_clear(); 780 msgConfirm("Unable to find %d free blocks on this disk!", sz); 781 return; 782 } 783 } 784 else if (!strcmp(cp, "existing")) { 785 /* Do existing FreeBSD case */ 786 for (i = 0; chunk_info[i]; i++) { 787 if (chunk_info[i]->type == freebsd) 788 break; 789 } 790 if (!chunk_info[i]) { 791 dialog_clear(); 792 msgConfirm("Unable to find any existing FreeBSD partitions on this disk!"); 793 return; 794 } 795 } 796 else { 797 dialog_clear(); 798 msgConfirm("`%s' is an invalid value for %s - is config file valid?", cp, VAR_PARTITION); 799 return; 800 } 801 if (!all_disk) { 802 mbrContents = getBootMgr(d->name); 803 Set_Boot_Mgr(d, mbrContents); 804 } 805 variable_set2(DISK_PARTITIONED, "yes"); 806 } 807} 808