disks.c revision 53748
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 * $FreeBSD: head/usr.sbin/sade/disks.c 53748 1999-11-27 14:33:07Z phk $ 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 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", 0); 294 record_chunks(d); 295 clear(); 296 break; 297 298 case 'C': 299 if (chunk_info[current_chunk]->type != unused) 300 msg = "Slice in use, delete it first or move to an unused one."; 301 else { 302 char *val, tmp[20], *cp; 303 int size, subtype; 304 chunk_e partitiontype; 305 306 snprintf(tmp, 20, "%lu", chunk_info[current_chunk]->size); 307 val = msgGetInput(tmp, "Please specify the size for new FreeBSD slice in blocks\n" 308 "or append a trailing `M' for megabytes (e.g. 20M)."); 309 if (val && (size = strtol(val, &cp, 0)) > 0) { 310 if (*cp && toupper(*cp) == 'M') 311 size *= ONE_MEG; 312 strcpy(tmp, "165"); 313 val = msgGetInput(tmp, "Enter type of partition to create:\n\n" 314 "Pressing Enter will choose the default, a native FreeBSD\n" 315 "slice (type 165). You can choose other types, 6 for a\n" 316 "DOS partition or 131 for a Linux partition, for example.\n\n" 317 "Note: If you choose a non-FreeBSD partition type, it will not\n" 318 "be formatted or otherwise prepared, it will simply reserve space\n" 319 "for you to use another tool, such as DOS FORMAT, to later format\n" 320 "and use the partition."); 321 if (val && (subtype = strtol(val, NULL, 0)) > 0) { 322 if (subtype == 165) 323 partitiontype = freebsd; 324 else if (subtype == 6) 325 partitiontype = fat; 326 else 327 partitiontype = unknown; 328#ifdef __alpha__ 329 if (partitiontype == freebsd && size == chunk_info[current_chunk]->size) 330 All_FreeBSD(d, 1); 331 else 332#endif 333 Create_Chunk(d, chunk_info[current_chunk]->offset, size, partitiontype, subtype, 334 (chunk_info[current_chunk]->flags & CHUNK_ALIGN)); 335 variable_set2(DISK_PARTITIONED, "yes", 0); 336 record_chunks(d); 337 } 338 } 339 clear(); 340 } 341 break; 342 343 case KEY_DC: 344 case 'D': 345 if (chunk_info[current_chunk]->type == unused) 346 msg = "Slice is already unused!"; 347 else { 348 Delete_Chunk(d, chunk_info[current_chunk]); 349 variable_set2(DISK_PARTITIONED, "yes", 0); 350 record_chunks(d); 351 } 352 break; 353 354 case 'T': 355 if (chunk_info[current_chunk]->type == unused) 356 msg = "Slice is currently unused (use create instead)"; 357 else { 358 char *val, tmp[20]; 359 int subtype; 360 chunk_e partitiontype; 361 WINDOW *save = savescr(); 362 363 strcpy(tmp, "165"); 364 val = msgGetInput(tmp, "New partition type:\n\n" 365 "Pressing Enter will choose the default, a native FreeBSD\n" 366 "slice (type 165). Other popular values are 6 for\n" 367 "DOS FAT partition, 131 for a Linux ext2fs partition or\n" 368 "130 for a Linux swap partition.\n\n" 369 "Note: If you choose a non-FreeBSD partition type, it will not\n" 370 "be formatted or otherwise prepared, it will simply reserve space\n" 371 "for you to use another tool, such as DOS format, to later format\n" 372 "and actually use the partition."); 373 if (val && (subtype = strtol(val, NULL, 0)) > 0) { 374 if (subtype == 165) 375 partitiontype = freebsd; 376 else if (subtype == 6) 377 partitiontype = fat; 378 else 379 partitiontype = unknown; 380 chunk_info[current_chunk]->type = partitiontype; 381 chunk_info[current_chunk]->subtype = subtype; 382 } 383 restorescr(save); 384 } 385 break; 386 387 case 'G': 388 snprintf(geometry, 80, "%lu/%lu/%lu", d->bios_cyl, d->bios_hd, d->bios_sect); 389 val = msgGetInput(geometry, "Please specify the new geometry in cyl/hd/sect format.\n" 390 "Don't forget to use the two slash (/) separator characters!\n" 391 "It's not possible to parse the field without them."); 392 if (val) { 393 long nc, nh, ns; 394 nc = strtol(val, &val, 0); 395 nh = strtol(val + 1, &val, 0); 396 ns = strtol(val + 1, 0, 0); 397 Set_Bios_Geom(d, nc, nh, ns); 398 } 399 clear(); 400 break; 401 402 case 'S': 403 /* Set Bootable */ 404 chunk_info[current_chunk]->flags |= CHUNK_ACTIVE; 405 break; 406 407 case 'U': 408 if ((cp = variable_get(DISK_LABELLED)) && !strcmp(cp, "written")) { 409 msgConfirm("You've already written this information out - you\n" 410 "can't undo it."); 411 } 412 else if (!msgYesNo("Are you SURE you want to Undo everything?")) { 413 char cp[BUFSIZ]; 414 415 sstrncpy(cp, d->name, sizeof cp); 416 Free_Disk(dev->private); 417 d = Open_Disk(cp); 418 if (!d) 419 msgConfirm("Can't reopen disk %s! Internal state is probably corrupted", cp); 420 dev->private = d; 421 variable_unset(DISK_PARTITIONED); 422 variable_unset(DISK_LABELLED); 423 if (d) 424 record_chunks(d); 425 } 426 clear(); 427 break; 428 429 case 'W': 430 if (!msgYesNo("WARNING: This should only be used when modifying an EXISTING\n" 431 "installation. If you are installing FreeBSD for the first time\n" 432 "then you should simply type Q when you're finished here and your\n" 433 "changes will be committed in one batch automatically at the end of\n" 434 "these questions. If you're adding a disk, you should NOT write\n" 435 "from this screen, you should do it from the label editor.\n\n" 436 "Are you absolutely sure you want to do this now?")) { 437 variable_set2(DISK_PARTITIONED, "yes", 0); 438 439 /* Don't trash the MBR if the first (and therefore only) chunk is marked for a truly dedicated 440 * disk (i.e., the disklabel starts at sector 0), even in cases where the user has requested 441 * booteasy or a "standard" MBR -- both would be fatal in this case. 442 */ 443 /* 444 * Don't offer to update the MBR on this disk if the first "real" chunk looks like 445 * a FreeBSD "all disk" partition, or the disk is entirely FreeBSD. 446 */ 447 if (((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1))) 448 mbrContents = getBootMgr(d->name); 449 else 450 mbrContents = NULL; 451 Set_Boot_Mgr(d, mbrContents); 452 453 if (DITEM_STATUS(diskPartitionWrite(NULL)) != DITEM_SUCCESS) 454 msgConfirm("Disk partition write returned an error status!"); 455 else 456 msgConfirm("Wrote FDISK partition information out successfully."); 457 } 458 clear(); 459 break; 460 461 case '|': 462 if (!msgYesNo("Are you SURE you want to go into Wizard mode?\n" 463 "No seat belts whatsoever are provided!")) { 464 clear(); 465 refresh(); 466 slice_wizard(d); 467 variable_set2(DISK_PARTITIONED, "yes", 0); 468 record_chunks(d); 469 } 470 else 471 msg = "Wise choice!"; 472 clear(); 473 break; 474 475 case '\033': /* ESC */ 476 case 'Q': 477 chunking = FALSE; 478 /* Don't trash the MBR if the first (and therefore only) chunk is marked for a truly dedicated 479 * disk (i.e., the disklabel starts at sector 0), even in cases where the user has requested 480 * booteasy or a "standard" MBR -- both would be fatal in this case. 481 */ 482#if 0 483 if ((d->chunks->part->flags & CHUNK_FORCE_ALL) != CHUNK_FORCE_ALL 484 && (mbrContents = getBootMgr(d->name)) != NULL) 485 Set_Boot_Mgr(d, mbrContents); 486#else 487 /* 488 * Don't offer to update the MBR on this disk if the first "real" chunk looks like 489 * a FreeBSD "all disk" partition, or the disk is entirely FreeBSD. 490 */ 491 if (((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) && 492 (mbrContents = getBootMgr(d->name)) != NULL) 493 Set_Boot_Mgr(d, mbrContents); 494#endif 495 break; 496 497 default: 498 beep(); 499 msg = "Type F1 or ? for help"; 500 break; 501 } 502 } 503 p = CheckRules(d); 504 if (p) { 505 char buf[FILENAME_MAX]; 506 507 dialog_clear_norefresh(); 508 use_helpline("Press F1 to read more about disk slices."); 509 use_helpfile(systemHelpFile("partition", buf)); 510 if (!variable_get(VAR_NO_WARN)) 511 dialog_mesgbox("Disk slicing warning:", p, -1, -1); 512 free(p); 513 } 514 restorescr(w); 515} 516 517static u_char * 518bootalloc(char *name) 519{ 520 char buf[FILENAME_MAX]; 521 struct stat sb; 522 523 snprintf(buf, sizeof buf, "/boot/%s", name); 524 if (stat(buf, &sb) != -1) { 525 int fd; 526 527 fd = open(buf, O_RDONLY); 528 if (fd != -1) { 529 u_char *cp; 530 531 cp = malloc(sb.st_size); 532 if (read(fd, cp, sb.st_size) != sb.st_size) { 533 free(cp); 534 close(fd); 535 msgDebug("bootalloc: couldn't read %d bytes from %s\n", sb.st_size, buf); 536 return NULL; 537 } 538 close(fd); 539 return cp; 540 } 541 msgDebug("bootalloc: couldn't open %s\n", buf); 542 } 543 else 544 msgDebug("bootalloc: can't stat %s\n", buf); 545 return NULL; 546} 547 548static int 549partitionHook(dialogMenuItem *selected) 550{ 551 Device **devs = NULL; 552 553 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 554 if (!devs) { 555 msgConfirm("Unable to find disk %s!", selected->prompt); 556 return DITEM_FAILURE; 557 } 558 /* Toggle enabled status? */ 559 if (!devs[0]->enabled) { 560 devs[0]->enabled = TRUE; 561 diskPartition(devs[0]); 562 } 563 else 564 devs[0]->enabled = FALSE; 565 return DITEM_SUCCESS | DITEM_RESTORE; 566} 567 568static int 569partitionCheck(dialogMenuItem *selected) 570{ 571 Device **devs = NULL; 572 573 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 574 if (!devs || devs[0]->enabled == FALSE) 575 return FALSE; 576 return TRUE; 577} 578 579int 580diskPartitionEditor(dialogMenuItem *self) 581{ 582 DMenu *menu; 583 Device **devs; 584 int i, cnt, devcnt; 585 586 cnt = diskGetSelectCount(&devs); 587 devcnt = deviceCount(devs); 588 if (cnt == -1) { 589 msgConfirm("No disks found! Please verify that your disk controller is being\n" 590 "properly probed at boot time. See the Hardware Guide on the\n" 591 "Documentation menu for clues on diagnosing this type of problem."); 592 return DITEM_FAILURE; 593 } 594 else if (cnt) { 595 /* Some are already selected */ 596 for (i = 0; i < devcnt; i++) { 597 if (devs[i]->enabled) { 598 if (variable_get(VAR_NONINTERACTIVE)) 599 diskPartitionNonInteractive(devs[i]); 600 else 601 diskPartition(devs[i]); 602 } 603 } 604 } 605 else { 606 /* No disks are selected, fall-back case now */ 607 if (devcnt == 1) { 608 devs[0]->enabled = TRUE; 609 if (variable_get(VAR_NONINTERACTIVE)) 610 diskPartitionNonInteractive(devs[0]); 611 else 612 diskPartition(devs[0]); 613 return DITEM_SUCCESS; 614 } 615 else { 616 menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook, partitionCheck); 617 if (!menu) { 618 msgConfirm("No devices suitable for installation found!\n\n" 619 "Please verify that your disk controller (and attached drives)\n" 620 "were detected properly. This can be done by pressing the\n" 621 "[Scroll Lock] key and using the Arrow keys to move back to\n" 622 "the boot messages. Press [Scroll Lock] again to return."); 623 return DITEM_FAILURE; 624 } 625 else { 626 i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; 627 free(menu); 628 } 629 return i | DITEM_RESTORE; 630 } 631 } 632 return DITEM_SUCCESS; 633} 634 635int 636diskPartitionWrite(dialogMenuItem *self) 637{ 638 Device **devs; 639 int i; 640 char *cp; 641 642 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 643 if (!devs) { 644 msgConfirm("Unable to find any disks to write to??"); 645 return DITEM_FAILURE; 646 } 647 if (isDebug()) 648 msgDebug("diskPartitionWrite: Examining %d devices\n", deviceCount(devs)); 649 cp = variable_get(DISK_PARTITIONED); 650 if (cp && !strcmp(cp, "written")) 651 return DITEM_SUCCESS; 652 653 for (i = 0; devs[i]; i++) { 654 Chunk *c1; 655 Disk *d = (Disk *)devs[i]->private; 656 static u_char *boot1; 657#ifndef __alpha__ 658 static u_char *boot2; 659#endif 660 661 if (!devs[i]->enabled) 662 continue; 663 664#ifdef __alpha__ 665 if (!boot1) boot1 = bootalloc("boot1"); 666 Set_Boot_Blocks(d, boot1, NULL); 667#else 668 if (!boot1) boot1 = bootalloc("boot1"); 669 if (!boot2) boot2 = bootalloc("boot2"); 670 Set_Boot_Blocks(d, boot1, boot2); 671#endif 672 673 msgNotify("Writing partition information to drive %s", d->name); 674 if (!Fake && Write_Disk(d)) { 675 msgConfirm("ERROR: Unable to write data to disk %s!", d->name); 676 return DITEM_FAILURE; 677 } 678 679 /* If we've been through here before, we don't need to do the rest */ 680 if (cp && !strcmp(cp, "written")) 681 return DITEM_SUCCESS; 682 } 683 /* Now it's not "yes", but "written" */ 684 variable_set2(DISK_PARTITIONED, "written", 0); 685 return DITEM_SUCCESS; 686} 687 688/* Partition a disk based wholly on which variables are set */ 689static void 690diskPartitionNonInteractive(Device *dev) 691{ 692 char *cp; 693 int i, sz, all_disk = 0; 694 u_char *mbrContents; 695 Disk *d = (Disk *)dev->private; 696 697 record_chunks(d); 698 cp = variable_get(VAR_GEOMETRY); 699 if (cp) { 700 msgDebug("Setting geometry from script to: %s\n", cp); 701 d->bios_cyl = strtol(cp, &cp, 0); 702 d->bios_hd = strtol(cp + 1, &cp, 0); 703 d->bios_sect = strtol(cp + 1, 0, 0); 704 } 705 706 cp = variable_get(VAR_PARTITION); 707 if (cp) { 708 if (!strcmp(cp, "free")) { 709 /* Do free disk space case */ 710 for (i = 0; chunk_info[i]; i++) { 711 /* If a chunk is at least 10MB in size, use it. */ 712 if (chunk_info[i]->type == unused && chunk_info[i]->size > (10 * ONE_MEG)) { 713 Create_Chunk(d, chunk_info[i]->offset, chunk_info[i]->size, freebsd, 3, 714 (chunk_info[i]->flags & CHUNK_ALIGN)); 715 variable_set2(DISK_PARTITIONED, "yes", 0); 716 break; 717 } 718 } 719 if (!chunk_info[i]) { 720 dialog_clear(); 721 msgConfirm("Unable to find any free space on this disk!"); 722 return; 723 } 724 } 725 else if (!strcmp(cp, "all")) { 726 /* Do all disk space case */ 727 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); 728 729 All_FreeBSD(d, FALSE); 730 } 731 else if (!strcmp(cp, "exclusive")) { 732 /* Do really-all-the-disk-space case */ 733 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); 734 735 All_FreeBSD(d, all_disk = TRUE); 736 } 737 else if ((sz = strtol(cp, &cp, 0))) { 738 /* Look for sz bytes free */ 739 if (*cp && toupper(*cp) == 'M') 740 sz *= ONE_MEG; 741 for (i = 0; chunk_info[i]; i++) { 742 /* If a chunk is at least sz MB, use it. */ 743 if (chunk_info[i]->type == unused && chunk_info[i]->size >= sz) { 744 Create_Chunk(d, chunk_info[i]->offset, sz, freebsd, 3, (chunk_info[i]->flags & CHUNK_ALIGN)); 745 variable_set2(DISK_PARTITIONED, "yes", 0); 746 break; 747 } 748 } 749 if (!chunk_info[i]) { 750 dialog_clear(); 751 msgConfirm("Unable to find %d free blocks on this disk!", sz); 752 return; 753 } 754 } 755 else if (!strcmp(cp, "existing")) { 756 /* Do existing FreeBSD case */ 757 for (i = 0; chunk_info[i]; i++) { 758 if (chunk_info[i]->type == freebsd) 759 break; 760 } 761 if (!chunk_info[i]) { 762 dialog_clear(); 763 msgConfirm("Unable to find any existing FreeBSD partitions on this disk!"); 764 return; 765 } 766 } 767 else { 768 dialog_clear(); 769 msgConfirm("`%s' is an invalid value for %s - is config file valid?", cp, VAR_PARTITION); 770 return; 771 } 772 if (!all_disk) { 773 mbrContents = getBootMgr(d->name); 774 Set_Boot_Mgr(d, mbrContents); 775 } 776 variable_set2(DISK_PARTITIONED, "yes", 0); 777 } 778} 779