disks.c revision 34811
1175261Sobrien/* 2175261Sobrien * The new sysinstall program. 3175261Sobrien * 4175261Sobrien * This is probably the last program in the `sysinstall' line - the next 5175261Sobrien * generation being essentially a complete rewrite. 6175261Sobrien * 7175261Sobrien * $Id: disks.c,v 1.97 1998/03/23 05:59:10 jkh Exp $ 8175261Sobrien * 9175261Sobrien * Copyright (c) 1995 10175261Sobrien * Jordan Hubbard. All rights reserved. 11175261Sobrien * 12175261Sobrien * Redistribution and use in source and binary forms, with or without 13175261Sobrien * modification, are permitted provided that the following conditions 14175261Sobrien * are met: 1525839Speter * 1. Redistributions of source code must retain the above copyright 1625839Speter * notice, this list of conditions and the following disclaimer, 1725839Speter * verbatim and that no modifications are made prior to this 1825839Speter * point in the file. 1925839Speter * 2. Redistributions in binary form must reproduce the above copyright 2025839Speter * notice, this list of conditions and the following disclaimer in the 2125839Speter * documentation and/or other materials provided with the distribution. 2225839Speter * 2325839Speter * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 2425839Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2525839Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2625839Speter * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 2725839Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2825839Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2925839Speter * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 3025839Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3125839Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3225839Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3325839Speter * SUCH DAMAGE. 3425839Speter * 3525839Speter */ 3625839Speter 3725839Speter#include "sysinstall.h" 3825839Speter#include <ctype.h> 3925839Speter#include <sys/disklabel.h> 4025839Speter 4125839Speter/* Where we start displaying chunk information on the screen */ 4225839Speter#define CHUNK_START_ROW 5 4325839Speter 4425839Speter/* Where we keep track of MBR chunks */ 4525839Speterstatic struct chunk *chunk_info[16]; 4625839Speterstatic int current_chunk; 4725839Speter 4825839Speterstatic void diskPartitionNonInteractive(Device *dev); 4925839Speter 5025839Speterstatic void 5125839Speterrecord_chunks(Disk *d) 5225839Speter{ 5325839Speter struct chunk *c1 = NULL; 5425839Speter int i = 0; 5525839Speter int last_free = 0; 5625839Speter 5725839Speter if (!d->chunks) 5825839Speter msgFatal("No chunk list found for %s!", d->name); 5925839Speter 6025839Speter for (c1 = d->chunks->part; c1; c1 = c1->next) { 6125839Speter if (c1->type == unused && c1->size > last_free) { 6225839Speter last_free = c1->size; 6325839Speter current_chunk = i; 6425839Speter } 6525839Speter chunk_info[i++] = c1; 6625839Speter } 6725839Speter chunk_info[i] = NULL; 6825839Speter if (current_chunk >= i) 6925839Speter current_chunk = i - 1; 7025839Speter} 7125839Speter 7225839Speterstatic int Total; 7325839Speter 7425839Speterstatic void 7525839Speterprint_chunks(Disk *d) 7625839Speter{ 7725839Speter int row; 78102840Speter int i; 7925839Speter 8025839Speter for (i = Total = 0; chunk_info[i]; i++) 8125839Speter Total += chunk_info[i]->size; 8225839Speter if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64) { 8325839Speter dialog_clear_norefresh(); 8425839Speter msgConfirm("WARNING: A geometry of %d/%d/%d for %s is incorrect. Using\n" 8525839Speter "a more likely geometry. If this geometry is incorrect or you\n" 8625839Speter "are unsure as to whether or not it's correct, please consult\n" 8725839Speter "the Hardware Guide in the Documentation submenu or use the\n" 8825839Speter "(G)eometry command to change it now.\n\n" 8925839Speter "Remember: you need to enter whatever your BIOS thinks the\n" 9025839Speter "geometry is! For IDE, it's what you were told in the BIOS\n" 9125839Speter "setup. For SCSI, it's the translation mode your controller is\n" 9225839Speter "using. Do NOT use a ``physical geometry''.", 9325839Speter d->bios_cyl, d->bios_hd, d->bios_sect, d->name); 9425839Speter Sanitize_Bios_Geom(d); 9525839Speter } 9625839Speter attrset(A_NORMAL); 9725839Speter mvaddstr(0, 0, "Disk name:\t"); 9825839Speter clrtobot(); 9925839Speter attrset(A_REVERSE); addstr(d->name); attrset(A_NORMAL); 10025839Speter attrset(A_REVERSE); mvaddstr(0, 55, "FDISK Partition Editor"); attrset(A_NORMAL); 10125839Speter mvprintw(1, 0, 10225839Speter "DISK Geometry:\t%lu cyls/%lu heads/%lu sectors = %lu sectors", 10325839Speter d->bios_cyl, d->bios_hd, d->bios_sect, 10425839Speter d->bios_cyl * d->bios_hd * d->bios_sect); 10525839Speter mvprintw(3, 0, "%10s %10s %10s %8s %6s %10s %8s %8s", 10625839Speter "Offset", "Size", "End", "Name", "PType", "Desc", 10725839Speter "Subtype", "Flags"); 10825839Speter for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) { 10925839Speter if (i == current_chunk) 11025839Speter attrset(ATTR_SELECTED); 11125839Speter mvprintw(row, 0, "%10ld %10lu %10lu %8s %6d %10s %8d\t%-6s", 11225839Speter chunk_info[i]->offset, chunk_info[i]->size, 11334461Speter chunk_info[i]->end, chunk_info[i]->name, 11434461Speter chunk_info[i]->type, 11534461Speter slice_type_name(chunk_info[i]->type, chunk_info[i]->subtype), 11625839Speter chunk_info[i]->subtype, ShowChunkFlags(chunk_info[i])); 11725839Speter if (i == current_chunk) 11825839Speter attrset(A_NORMAL); 11925839Speter } 12025839Speter} 12125839Speter 122102840Speterstatic void 12325839Speterprint_command_summary() 12425839Speter{ 12534461Speter mvprintw(14, 0, "The following commands are supported (in upper or lower case):"); 12625839Speter mvprintw(16, 0, "A = Use Entire Disk B = Bad Block Scan C = Create Slice"); 12725839Speter mvprintw(17, 0, "D = Delete Slice G = Set Drive Geometry S = Set Bootable"); 128102840Speter mvprintw(18, 0, "T = Change Type U = Undo All Changes Q = Finish"); 129107484Speter if (!RunningAsInit) 13025839Speter mvprintw(18, 48, "W = Write Changes"); 13125839Speter mvprintw(21, 0, "Use F1 or ? to get more help, arrow keys to select."); 13232785Speter move(0, 0); 13332785Speter} 13432785Speter 13532785Speterstatic u_char * 136128266SpetergetBootMgr(char *dname) 13725839Speter{ 13825839Speter extern u_char mbr[], bteasy17[]; 13925839Speter char str[80]; 14025839Speter char *cp; 14125839Speter int i = 0; 14225839Speter 14325839Speter cp = variable_get(VAR_BOOTMGR); 14425839Speter if (!cp) { 14525839Speter /* Figure out what kind of MBR the user wants */ 14625839Speter sprintf(str, "Install Boot Manager for drive %s?", dname); 14725839Speter MenuMBRType.title = str; 14825839Speter i = dmenuOpenSimple(&MenuMBRType, FALSE); 14925839Speter } 15034461Speter else { 15125839Speter if (!strncmp(cp, "boot", 4)) 15225839Speter BootMgr = 0; 15325839Speter else if (!strcmp(cp, "standard")) 15425839Speter BootMgr = 1; 15525839Speter else 15625839Speter BootMgr = 2; 15725839Speter } 15825839Speter if (cp || i) { 15925839Speter switch (BootMgr) { 16025839Speter case 0: 16134461Speter return bteasy17; 16225839Speter 16325839Speter case 1: 16425839Speter return mbr; 16525839Speter 16625839Speter case 2: 16725839Speter default: 16825839Speter 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 0 488 if ((d->chunks->part->flags & CHUNK_FORCE_ALL) != CHUNK_FORCE_ALL 489 && (mbrContents = getBootMgr(d->name)) != NULL) 490 Set_Boot_Mgr(d, mbrContents); 491#else 492 /* 493 * Don't offer to update the MBR on this disk if the first "real" chunk looks like 494 * a FreeBSD "all disk" partition, or the disk is entirely FreeBSD. 495 */ 496 if (((d->chunks->part->type != freebsd) || (d->chunks->part->offset > 1)) && 497 (mbrContents = getBootMgr(d->name)) != NULL) 498 Set_Boot_Mgr(d, mbrContents); 499#endif 500 break; 501 502 default: 503 beep(); 504 msg = "Type F1 or ? for help"; 505 break; 506 } 507 } 508 p = CheckRules(d); 509 if (p) { 510 char buf[FILENAME_MAX]; 511 512 dialog_clear_norefresh(); 513 use_helpline("Press F1 to read more about disk slices."); 514 use_helpfile(systemHelpFile("partition", buf)); 515 if (!variable_get(VAR_NO_WARN)) 516 dialog_mesgbox("Disk slicing warning:", p, -1, -1); 517 free(p); 518 } 519 restorescr(w); 520} 521 522static int 523partitionHook(dialogMenuItem *selected) 524{ 525 Device **devs = NULL; 526 527 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 528 if (!devs) { 529 msgConfirm("Unable to find disk %s!", selected->prompt); 530 return DITEM_FAILURE; 531 } 532 /* Toggle enabled status? */ 533 if (!devs[0]->enabled) { 534 devs[0]->enabled = TRUE; 535 diskPartition(devs[0]); 536 } 537 else 538 devs[0]->enabled = FALSE; 539 return DITEM_SUCCESS | DITEM_RESTORE; 540} 541 542static int 543partitionCheck(dialogMenuItem *selected) 544{ 545 Device **devs = NULL; 546 547 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK); 548 if (!devs || devs[0]->enabled == FALSE) 549 return FALSE; 550 return TRUE; 551} 552 553int 554diskPartitionEditor(dialogMenuItem *self) 555{ 556 DMenu *menu; 557 Device **devs; 558 int i, cnt, devcnt; 559 560 cnt = diskGetSelectCount(&devs); 561 devcnt = deviceCount(devs); 562 if (cnt == -1) { 563 msgConfirm("No disks found! Please verify that your disk controller is being\n" 564 "properly probed at boot time. See the Hardware Guide on the\n" 565 "Documentation menu for clues on diagnosing this type of problem."); 566 return DITEM_FAILURE; 567 } 568 else if (cnt) { 569 /* Some are already selected */ 570 for (i = 0; i < devcnt; i++) { 571 if (devs[i]->enabled) { 572 if (variable_get(VAR_NONINTERACTIVE)) 573 diskPartitionNonInteractive(devs[i]); 574 else 575 diskPartition(devs[i]); 576 } 577 } 578 } 579 else { 580 /* No disks are selected, fall-back case now */ 581 if (devcnt == 1) { 582 devs[0]->enabled = TRUE; 583 if (variable_get(VAR_NONINTERACTIVE)) 584 diskPartitionNonInteractive(devs[0]); 585 else 586 diskPartition(devs[0]); 587 return DITEM_SUCCESS; 588 } 589 else { 590 menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook, partitionCheck); 591 if (!menu) { 592 msgConfirm("No devices suitable for installation found!\n\n" 593 "Please verify that your disk controller (and attached drives)\n" 594 "were detected properly. This can be done by pressing the\n" 595 "[Scroll Lock] key and using the Arrow keys to move back to\n" 596 "the boot messages. Press [Scroll Lock] again to return."); 597 return DITEM_FAILURE; 598 } 599 else { 600 i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE; 601 free(menu); 602 } 603 return i | DITEM_RESTORE; 604 } 605 } 606 return DITEM_SUCCESS; 607} 608 609int 610diskPartitionWrite(dialogMenuItem *self) 611{ 612 Device **devs; 613 int i; 614 char *cp; 615 616 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 617 if (!devs) { 618 msgConfirm("Unable to find any disks to write to??"); 619 return DITEM_FAILURE; 620 } 621 if (isDebug()) 622 msgDebug("diskPartitionWrite: Examining %d devices\n", deviceCount(devs)); 623 cp = variable_get(DISK_PARTITIONED); 624 if (cp && !strcmp(cp, "written")) 625 return DITEM_SUCCESS; 626 627 for (i = 0; devs[i]; i++) { 628 Chunk *c1; 629 Disk *d = (Disk *)devs[i]->private; 630 631 if (!devs[i]->enabled) 632 continue; 633 634 Set_Boot_Blocks(d, boot1, boot2); 635 msgNotify("Writing partition information to drive %s", d->name); 636 if (!Fake && Write_Disk(d)) { 637 msgConfirm("ERROR: Unable to write data to disk %s!", d->name); 638 return DITEM_FAILURE; 639 } 640 641 /* If we've been through here before, we don't need to do the rest */ 642 if (cp && !strcmp(cp, "written")) 643 return DITEM_SUCCESS; 644 645 /* Now scan for bad blocks, if necessary */ 646 for (c1 = d->chunks->part; c1; c1 = c1->next) { 647 if (c1->flags & CHUNK_BAD144) { 648 int ret; 649 650 msgNotify("Running bad block scan on slice %s", c1->name); 651 if (!Fake) { 652 ret = vsystem("bad144 -v /dev/r%s 1234", c1->name); 653 if (ret) 654 msgConfirm("Bad144 init on %s returned status of %d!", c1->name, ret); 655 ret = vsystem("bad144 -v -s /dev/r%s", c1->name); 656 if (ret) 657 msgConfirm("Bad144 scan on %s returned status of %d!", c1->name, ret); 658 } 659 } 660 } 661 } 662 /* Now it's not "yes", but "written" */ 663 variable_set2(DISK_PARTITIONED, "written"); 664 return DITEM_SUCCESS; 665} 666 667/* Partition a disk based wholly on which variables are set */ 668static void 669diskPartitionNonInteractive(Device *dev) 670{ 671 char *cp; 672 int i, sz, all_disk = 0; 673 u_char *mbrContents; 674 Disk *d = (Disk *)dev->private; 675 676 record_chunks(d); 677 cp = variable_get(VAR_GEOMETRY); 678 if (cp) { 679 msgDebug("Setting geometry from script to: %s\n", cp); 680 d->bios_cyl = strtol(cp, &cp, 0); 681 d->bios_hd = strtol(cp + 1, &cp, 0); 682 d->bios_sect = strtol(cp + 1, 0, 0); 683 } 684 685 cp = variable_get(VAR_PARTITION); 686 if (cp) { 687 if (!strcmp(cp, "free")) { 688 /* Do free disk space case */ 689 for (i = 0; chunk_info[i]; i++) { 690 /* If a chunk is at least 10MB in size, use it. */ 691 if (chunk_info[i]->type == unused && chunk_info[i]->size > (10 * ONE_MEG)) { 692 Create_Chunk(d, chunk_info[i]->offset, chunk_info[i]->size, freebsd, 3, 693 (chunk_info[i]->flags & CHUNK_ALIGN)); 694 variable_set2(DISK_PARTITIONED, "yes"); 695 break; 696 } 697 } 698 if (!chunk_info[i]) { 699 dialog_clear(); 700 msgConfirm("Unable to find any free space on this disk!"); 701 return; 702 } 703 } 704 else if (!strcmp(cp, "all")) { 705 /* Do all disk space case */ 706 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); 707 708 All_FreeBSD(d, FALSE); 709 } 710 else if (!strcmp(cp, "exclusive")) { 711 /* Do really-all-the-disk-space case */ 712 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name); 713 714 All_FreeBSD(d, all_disk = TRUE); 715 } 716 else if ((sz = strtol(cp, &cp, 0))) { 717 /* Look for sz bytes free */ 718 if (*cp && toupper(*cp) == 'M') 719 sz *= ONE_MEG; 720 for (i = 0; chunk_info[i]; i++) { 721 /* If a chunk is at least sz MB, use it. */ 722 if (chunk_info[i]->type == unused && chunk_info[i]->size >= sz) { 723 Create_Chunk(d, chunk_info[i]->offset, sz, freebsd, 3, (chunk_info[i]->flags & CHUNK_ALIGN)); 724 variable_set2(DISK_PARTITIONED, "yes"); 725 break; 726 } 727 } 728 if (!chunk_info[i]) { 729 dialog_clear(); 730 msgConfirm("Unable to find %d free blocks on this disk!", sz); 731 return; 732 } 733 } 734 else if (!strcmp(cp, "existing")) { 735 /* Do existing FreeBSD case */ 736 for (i = 0; chunk_info[i]; i++) { 737 if (chunk_info[i]->type == freebsd) 738 break; 739 } 740 if (!chunk_info[i]) { 741 dialog_clear(); 742 msgConfirm("Unable to find any existing FreeBSD partitions on this disk!"); 743 return; 744 } 745 } 746 else { 747 dialog_clear(); 748 msgConfirm("`%s' is an invalid value for %s - is config file valid?", cp, VAR_PARTITION); 749 return; 750 } 751 if (!all_disk) { 752 mbrContents = getBootMgr(d->name); 753 Set_Boot_Mgr(d, mbrContents); 754 } 755 variable_set2(DISK_PARTITIONED, "yes"); 756 } 757} 758