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