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