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