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