2 * The new sysinstall program.
4 * This is probably the last program in the `sysinstall' line - the next
5 * generation being essentially a complete rewrite.
10 * Jordan Hubbard. All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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
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.
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
37 #include "sysinstall.h"
43 #include <sys/disklabel.h>
46 enum size_units_t { UNIT_BLOCKS, UNIT_KILO, UNIT_MEG, UNIT_GIG, UNIT_SIZE };
49 #define SUBTYPE_FREEBSD 50324
50 #define SUBTYPE_FAT 37218
52 #define SUBTYPE_FREEBSD 165
55 #define SUBTYPE_EFI 239
58 #define OTHER_SLICE_VALUES \
59 "Other popular values are 37218 for a\n" \
60 "DOS FAT partition.\n\n"
62 #define OTHER_SLICE_VALUES \
63 "Other popular values are 6 for a\n" \
64 "DOS FAT partition, 131 for a Linux ext2fs partition, or\n" \
65 "130 for a Linux swap partition.\n\n"
67 #define NON_FREEBSD_NOTE \
68 "Note: If you choose a non-FreeBSD partition type, it will not\n" \
69 "be formatted or otherwise prepared, it will simply reserve space\n" \
70 "for you to use another tool, such as DOS format, to later format\n" \
71 "and actually use the partition."
73 /* Where we start displaying chunk information on the screen */
74 #define CHUNK_START_ROW 5
76 /* Where we keep track of MBR chunks */
77 #define CHUNK_INFO_ENTRIES 16
78 static struct chunk *chunk_info[CHUNK_INFO_ENTRIES];
79 static int current_chunk;
81 static void diskPartitionNonInteractive(Device *dev);
82 static u_char * bootalloc(char *name, size_t *size);
85 record_chunks(Disk *d)
87 struct chunk *c1 = NULL;
89 daddr_t last_free = 0;
92 msgFatal("No chunk list found for %s!", d->name);
94 for (c1 = d->chunks->part; c1; c1 = c1->next) {
95 if (c1->type == unused && c1->size > last_free) {
101 chunk_info[i] = NULL;
102 if (current_chunk >= i)
103 current_chunk = i - 1;
106 static daddr_t Total;
109 check_geometry(Disk *d)
114 if (d->bios_cyl >= 65536 || d->bios_hd > 256 || d->bios_sect >= 256)
116 if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64)
119 dialog_clear_norefresh();
120 sg = msgYesNo("WARNING: It is safe to use a geometry of %lu/%lu/%lu for %s on\n"
121 "computers with modern BIOS versions. If this disk is to be used\n"
122 "on rather old machines, however, it is recommended to ensure that\n"
123 "it does not have more than 65535 cylinders, or more than 255 heads\n"
130 " sectors per track.\n"
132 "Would you like that to keep using the current geometry?\n",
133 d->bios_cyl, d->bios_hd, d->bios_sect, d->name);
135 Sanitize_Bios_Geom(d);
136 msgConfirm("A geometry of %lu/%lu/%lu was calculated for %s.\n"
138 "If you are not sure about this, please consult the Hardware Guide\n"
139 "in the Documentation submenu or use the (G)eometry command to\n"
140 "change it. Remember: you need to enter whatever your BIOS thinks\n"
141 "the geometry is! For IDE, it's what you were told in the BIOS\n"
142 "setup. For SCSI, it's the translation mode your controller is\n"
143 "using. Do NOT use a ``physical geometry''.\n",
144 d->bios_cyl, d->bios_hd, d->bios_sect, d->name);
150 print_chunks(Disk *d, int u)
157 szstr = (u == UNIT_GIG ? "GB" : (u == UNIT_MEG ? "MB" :
158 (u == UNIT_KILO ? "KB" : "ST")));
161 for (i = 0; chunk_info[i]; i++)
162 Total += chunk_info[i]->size;
164 mvaddstr(0, 0, "Disk name:\t");
166 attrset(A_REVERSE); addstr(d->name); attrset(A_NORMAL);
167 attrset(A_REVERSE); mvaddstr(0, 55, "FDISK Partition Editor"); attrset(A_NORMAL);
169 "DISK Geometry:\t%lu cyls/%lu heads/%lu sectors = %jd sectors (%jdMB)",
170 d->bios_cyl, d->bios_hd, d->bios_sect,
171 (intmax_t)d->bios_cyl * d->bios_hd * d->bios_sect,
172 (intmax_t)d->bios_cyl * d->bios_hd * d->bios_sect / (1024/512) / 1024);
173 mvprintw(3, 0, "%6s %10s(%s) %10s %8s %6s %10s %8s %8s",
174 "Offset", "Size", szstr, "End", "Name", "PType", "Desc",
176 for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) {
178 default: /* fall thru */
180 sz = chunk_info[i]->size;
183 sz = chunk_info[i]->size / (1024/512);
186 sz = chunk_info[i]->size / (1024/512) / 1024;
189 sz = chunk_info[i]->size / (1024/512) / 1024 / 1024;
192 if (i == current_chunk)
193 attrset(ATTR_SELECTED);
194 mvprintw(row, 0, "%10jd %10jd %10jd %8s %6d %10s %8d\t%-6s",
195 (intmax_t)chunk_info[i]->offset, (intmax_t)sz,
196 (intmax_t)chunk_info[i]->end, chunk_info[i]->name,
198 slice_type_name(chunk_info[i]->type, chunk_info[i]->subtype),
199 chunk_info[i]->subtype, ShowChunkFlags(chunk_info[i]));
200 if (i == current_chunk)
206 print_command_summary(void)
208 mvprintw(14, 0, "The following commands are supported (in upper or lower case):");
209 mvprintw(16, 0, "A = Use Entire Disk G = set Drive Geometry C = Create Slice F = `DD' mode");
210 mvprintw(17, 0, "D = Delete Slice Z = Toggle Size Units S = Set Bootable | = Wizard m.");
211 mvprintw(18, 0, "T = Change Type U = Undo All Changes Q = Finish");
213 mvprintw(18, 47, "W = Write Changes");
214 mvprintw(21, 0, "Use F1 or ? to get more help, arrow keys to select.");
220 getBootMgr(char *dname, u_char **bootipl, size_t *bootipl_size,
221 u_char **bootmenu, size_t *bootmenu_size)
223 static u_char *boot0;
224 static size_t boot0_size;
225 static u_char *boot05;
226 static size_t boot05_size;
232 cp = variable_get(VAR_BOOTMGR);
234 /* Figure out what kind of IPL the user wants */
235 sprintf(str, "Install Boot Manager for drive %s?", dname);
236 MenuIPLType.title = str;
237 i = dmenuOpenSimple(&MenuIPLType, FALSE);
239 if (!strncmp(cp, "boot", 4))
247 if (!boot0) boot0 = bootalloc("boot0", &boot0_size);
249 *bootipl_size = boot0_size;
250 if (!boot05) boot05 = bootalloc("boot0.5", &boot05_size);
252 *bootmenu_size = boot05_size;
266 getBootMgr(char *dname, u_char **bootCode, size_t *bootCodeSize)
268 #if defined(__i386__) || defined(__amd64__) /* only meaningful on x86 */
269 static u_char *mbr, *boot0;
270 static size_t mbr_size, boot0_size;
275 cp = variable_get(VAR_BOOTMGR);
277 /* Figure out what kind of MBR the user wants */
278 sprintf(str, "Install Boot Manager for drive %s?", dname);
279 MenuMBRType.title = str;
280 i = dmenuOpenSimple(&MenuMBRType, FALSE);
283 if (!strncmp(cp, "boot", 4))
285 else if (!strcmp(cp, "standard"))
293 if (!boot0) boot0 = bootalloc("boot0", &boot0_size);
295 *bootCodeSize = boot0_size;
298 if (!mbr) mbr = bootalloc("mbr", &mbr_size);
300 *bootCodeSize = mbr_size;
312 #endif /* WITH_SLICES */
315 diskGetSelectCount(Device ***devs)
321 cp = variable_get(VAR_DISK);
322 dp = *devs = deviceFind(cp, DEVICE_TYPE_DISK);
323 cnt = deviceCount(dp);
326 for (i = 0, enabled = 0; i < cnt; i++) {
335 diskPartition(Device *dev)
346 size_t bootmenu_size;
351 WINDOW *w = savescr();
352 Disk *d = (Disk *)dev->private;
355 size_unit = UNIT_BLOCKS;
357 keypad(stdscr, TRUE);
359 /* Flush both the dialog and curses library views of the screen
360 since we don't always know who called us */
361 dialog_clear_norefresh(), clear();
364 /* Set up the chunk array */
367 /* Give the user a chance to sanitize the disk geometry, if necessary */
371 char *val, geometry[80];
373 /* Now print our overall state */
375 print_chunks(d, size_unit);
376 print_command_summary();
378 attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL);
387 /* Get command character */
389 switch (toupper(key)) {
390 case '\014': /* ^L (redraw) */
395 case '\020': /* ^P */
398 if (current_chunk != 0)
402 case '\016': /* ^N */
407 if (chunk_info[current_chunk + 1])
416 while (chunk_info[current_chunk + 1])
422 systemDisplayHelp("slice");
427 case 'F': /* Undocumented magic Dangerously Dedicated mode */
428 #if !defined(__i386__) && !defined(__amd64__)
430 #else /* The rest is only relevant on x86 */
431 cp = variable_get(VAR_DEDICATE_DISK);
432 if (cp && !strcasecmp(cp, "always"))
434 else if (toupper(key) == 'A')
437 rv = msgYesNo("Do you want to do this with a true partition entry\n"
438 "so as to remain cooperative with any future possible\n"
439 "operating systems on the drive(s)?\n"
440 "(See also the section about ``dangerously dedicated''\n"
441 "disks in the FreeBSD FAQ.)");
447 variable_set2(DISK_PARTITIONED, "yes", 0);
453 if (chunk_info[current_chunk]->type != unused)
454 msg = "Slice in use, delete it first or move to an unused one.";
456 char *val, tmp[20], name[16], *cp;
459 chunk_e partitiontype;
461 snprintf(name, sizeof (name), "%s", "FreeBSD");
462 val = msgGetInput(name,
463 "Please specify the name for new FreeBSD slice.");
465 strncpy(name, val, sizeof (name));
469 snprintf(tmp, 20, "%jd", (intmax_t)chunk_info[current_chunk]->size);
470 val = msgGetInput(tmp, "Please specify the size for new FreeBSD slice in blocks\n"
471 "or append a trailing `M' for megabytes (e.g. 20M).");
472 if (val && (size = strtoimax(val, &cp, 0)) > 0) {
473 if (*cp && toupper(*cp) == 'M')
475 else if (*cp && toupper(*cp) == 'G')
477 sprintf(tmp, "%d", SUBTYPE_FREEBSD);
478 val = msgGetInput(tmp, "Enter type of partition to create:\n\n"
479 "Pressing Enter will choose the default, a native FreeBSD\n"
482 NON_FREEBSD_NOTE, SUBTYPE_FREEBSD);
483 if (val && (subtype = strtol(val, NULL, 0)) > 0) {
484 if (subtype == SUBTYPE_FREEBSD)
485 partitiontype = freebsd;
486 else if (subtype == SUBTYPE_FAT)
488 else if (subtype == SUBTYPE_EFI)
492 partitiontype = pc98;
496 Create_Chunk(d, chunk_info[current_chunk]->offset, size, partitiontype, subtype,
497 (chunk_info[current_chunk]->flags & CHUNK_ALIGN), name);
498 variable_set2(DISK_PARTITIONED, "yes", 0);
508 if (chunk_info[current_chunk]->type == unused)
509 msg = "Slice is already unused!";
511 Delete_Chunk(d, chunk_info[current_chunk]);
512 variable_set2(DISK_PARTITIONED, "yes", 0);
518 if (chunk_info[current_chunk]->type == unused)
519 msg = "Slice is currently unused (use create instead)";
523 chunk_e partitiontype;
525 sprintf(tmp, "%d", chunk_info[current_chunk]->subtype);
526 val = msgGetInput(tmp, "New partition type:\n\n"
527 "Pressing Enter will use the current type. To choose a native\n"
528 "FreeBSD slice enter %u. "
530 NON_FREEBSD_NOTE, SUBTYPE_FREEBSD);
531 if (val && (subtype = strtol(val, NULL, 0)) > 0) {
532 if (subtype == SUBTYPE_FREEBSD)
533 partitiontype = freebsd;
534 else if (subtype == SUBTYPE_FAT)
536 else if (subtype == SUBTYPE_EFI)
540 partitiontype = pc98;
544 chunk_info[current_chunk]->type = partitiontype;
545 chunk_info[current_chunk]->subtype = subtype;
551 snprintf(geometry, 80, "%lu/%lu/%lu", d->bios_cyl, d->bios_hd, d->bios_sect);
552 val = msgGetInput(geometry, "Please specify the new geometry in cyl/hd/sect format.\n"
553 "Don't forget to use the two slash (/) separator characters!\n"
554 "It's not possible to parse the field without them.");
557 nc = strtol(val, &val, 0);
558 nh = strtol(val + 1, &val, 0);
559 ns = strtol(val + 1, 0, 0);
560 Set_Bios_Geom(d, nc, nh, ns);
566 /* Clear active states so we won't have two */
567 for (i = 0; (chunk_info[i] != NULL) && (i < CHUNK_INFO_ENTRIES); i++)
568 chunk_info[i]->flags &= !CHUNK_ACTIVE;
571 chunk_info[current_chunk]->flags |= CHUNK_ACTIVE;
575 if (!variable_cmp(DISK_LABELLED, "written")) {
576 msgConfirm("You've already written this information out - you\n"
579 else if (!msgNoYes("Are you SURE you want to Undo everything?")) {
582 sstrncpy(cp, d->name, sizeof cp);
583 Free_Disk(dev->private);
586 msgConfirm("Can't reopen disk %s! Internal state is probably corrupted", cp);
588 variable_unset(DISK_PARTITIONED);
589 variable_unset(DISK_LABELLED);
597 if (!msgNoYes("WARNING: This should only be used when modifying an EXISTING\n"
598 "installation. If you are installing FreeBSD for the first time\n"
599 "then you should simply type Q when you're finished here and your\n"
600 "changes will be committed in one batch automatically at the end of\n"
601 "these questions. If you're adding a disk, you should NOT write\n"
602 "from this screen, you should do it from the label editor.\n\n"
603 "Are you absolutely sure you want to do this now?")) {
604 variable_set2(DISK_PARTITIONED, "yes", 0);
608 * Don't trash the IPL if the first (and therefore only) chunk
609 * is marked for a truly dedicated disk (i.e., the disklabel
610 * starts at sector 0), even in cases where the user has
611 * requested a FreeBSD Boot Manager -- both would be fatal in
615 * Don't offer to update the IPL on this disk if the first
616 * "real" chunk looks like a FreeBSD "all disk" partition,
617 * or the disk is entirely FreeBSD.
619 if ((d->chunks->part->type != freebsd) ||
620 (d->chunks->part->offset > 1))
621 getBootMgr(d->name, &bootipl, &bootipl_size,
622 &bootmenu, &bootmenu_size);
629 Set_Boot_Mgr(d, bootipl, bootipl_size, bootmenu, bootmenu_size);
632 * Don't trash the MBR if the first (and therefore only) chunk
633 * is marked for a truly dedicated disk (i.e., the disklabel
634 * starts at sector 0), even in cases where the user has
635 * requested booteasy or a "standard" MBR -- both would be
636 * fatal in this case.
639 * Don't offer to update the MBR on this disk if the first
640 * "real" chunk looks like a FreeBSD "all disk" partition,
641 * or the disk is entirely FreeBSD.
643 if ((d->chunks->part->type != freebsd) ||
644 (d->chunks->part->offset > 1))
645 getBootMgr(d->name, &mbrContents, &mbrSize);
650 Set_Boot_Mgr(d, mbrContents, mbrSize);
653 if (DITEM_STATUS(diskPartitionWrite(NULL)) != DITEM_SUCCESS)
654 msgConfirm("Disk partition write returned an error status!");
656 msgConfirm("Wrote FDISK partition information out successfully.");
662 if (!msgNoYes("Are you SURE you want to go into Wizard mode?\n"
663 "No seat belts whatsoever are provided!")) {
667 variable_set2(DISK_PARTITIONED, "yes", 0);
671 msg = "Wise choice!";
675 case '\033': /* ESC */
680 * Don't trash the IPL if the first (and therefore only) chunk
681 * is marked for a truly dedicated disk (i.e., the disklabel
682 * starts at sector 0), even in cases where the user has requested
683 * a FreeBSD Boot Manager -- both would be fatal in this case.
686 * Don't offer to update the IPL on this disk if the first "real"
687 * chunk looks like a FreeBSD "all disk" partition, or the disk is
690 if ((d->chunks->part->type != freebsd) ||
691 (d->chunks->part->offset > 1)) {
692 if (variable_cmp(DISK_PARTITIONED, "written")) {
693 getBootMgr(d->name, &bootipl, &bootipl_size,
694 &bootmenu, &bootmenu_size);
695 if (bootipl != NULL && bootmenu != NULL)
696 Set_Boot_Mgr(d, bootipl, bootipl_size,
697 bootmenu, bootmenu_size);
702 * Don't trash the MBR if the first (and therefore only) chunk
703 * is marked for a truly dedicated disk (i.e., the disklabel
704 * starts at sector 0), even in cases where the user has requested
705 * booteasy or a "standard" MBR -- both would be fatal in this case.
708 * Don't offer to update the MBR on this disk if the first "real"
709 * chunk looks like a FreeBSD "all disk" partition, or the disk is
712 if ((d->chunks->part->type != freebsd) ||
713 (d->chunks->part->offset > 1)) {
714 if (variable_cmp(DISK_PARTITIONED, "written")) {
715 getBootMgr(d->name, &mbrContents, &mbrSize);
716 if (mbrContents != NULL)
717 Set_Boot_Mgr(d, mbrContents, mbrSize);
724 size_unit = (size_unit + 1) % UNIT_SIZE;
729 msg = "Type F1 or ? for help";
735 char buf[FILENAME_MAX];
737 use_helpline("Press F1 to read more about disk slices.");
738 use_helpfile(systemHelpFile("partition", buf));
739 if (!variable_get(VAR_NO_WARN))
740 dialog_mesgbox("Disk slicing warning:", p, -1, -1);
745 #endif /* WITH_SLICES */
748 bootalloc(char *name, size_t *size)
750 char buf[FILENAME_MAX];
753 snprintf(buf, sizeof buf, "/boot/%s", name);
754 if (stat(buf, &sb) != -1) {
757 fd = open(buf, O_RDONLY);
761 cp = malloc(sb.st_size);
762 if (read(fd, cp, sb.st_size) != sb.st_size) {
765 msgDebug("bootalloc: couldn't read %ld bytes from %s\n", (long)sb.st_size, buf);
773 msgDebug("bootalloc: couldn't open %s\n", buf);
776 msgDebug("bootalloc: can't stat %s\n", buf);
782 partitionHook(dialogMenuItem *selected)
784 Device **devs = NULL;
786 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK);
788 msgConfirm("Unable to find disk %s!", selected->prompt);
789 return DITEM_FAILURE;
791 /* Toggle enabled status? */
792 if (!devs[0]->enabled) {
793 devs[0]->enabled = TRUE;
794 diskPartition(devs[0]);
797 devs[0]->enabled = FALSE;
798 return DITEM_SUCCESS;
802 partitionCheck(dialogMenuItem *selected)
804 Device **devs = NULL;
806 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK);
807 if (!devs || devs[0]->enabled == FALSE)
813 diskPartitionEditor(dialogMenuItem *self)
819 cnt = diskGetSelectCount(&devs);
820 devcnt = deviceCount(devs);
822 msgConfirm("No disks found! Please verify that your disk controller is being\n"
823 "properly probed at boot time. See the Hardware Guide on the\n"
824 "Documentation menu for clues on diagnosing this type of problem.");
825 return DITEM_FAILURE;
828 /* Some are already selected */
829 for (i = 0; i < devcnt; i++) {
830 if (devs[i]->enabled) {
831 if (variable_get(VAR_NONINTERACTIVE) &&
832 !variable_get(VAR_DISKINTERACTIVE))
833 diskPartitionNonInteractive(devs[i]);
835 diskPartition(devs[i]);
840 /* No disks are selected, fall-back case now */
842 devs[0]->enabled = TRUE;
843 if (variable_get(VAR_NONINTERACTIVE) &&
844 !variable_get(VAR_DISKINTERACTIVE))
845 diskPartitionNonInteractive(devs[0]);
847 diskPartition(devs[0]);
848 return DITEM_SUCCESS;
851 menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook, partitionCheck);
853 msgConfirm("No devices suitable for installation found!\n\n"
854 "Please verify that your disk controller (and attached drives)\n"
855 "were detected properly. This can be done by pressing the\n"
856 "[Scroll Lock] key and using the Arrow keys to move back to\n"
857 "the boot messages. Press [Scroll Lock] again to return.");
858 return DITEM_FAILURE;
861 i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE;
867 return DITEM_SUCCESS;
869 #endif /* WITH_SLICES */
872 diskPartitionWrite(dialogMenuItem *self)
877 if (!variable_cmp(DISK_PARTITIONED, "written"))
878 return DITEM_SUCCESS;
880 devs = deviceFind(NULL, DEVICE_TYPE_DISK);
882 msgConfirm("Unable to find any disks to write to??");
883 return DITEM_FAILURE;
886 msgDebug("diskPartitionWrite: Examining %d devices\n", deviceCount(devs));
887 for (i = 0; devs[i]; i++) {
888 Disk *d = (Disk *)devs[i]->private;
889 static u_char *boot1;
890 #if defined(__i386__) || defined(__amd64__)
891 static u_char *boot2;
894 if (!devs[i]->enabled)
897 #if defined(__i386__) || defined(__amd64__)
898 if (!boot1) boot1 = bootalloc("boot1", NULL);
899 if (!boot2) boot2 = bootalloc("boot2", NULL);
900 Set_Boot_Blocks(d, boot1, boot2);
901 #elif !defined(__ia64__)
902 if (!boot1) boot1 = bootalloc("boot1", NULL);
903 Set_Boot_Blocks(d, boot1, NULL);
906 msgNotify("Writing partition information to drive %s", d->name);
907 if (!Fake && Write_Disk(d)) {
909 msgConfirm("ERROR: Unable to write data to disk %s!", d->name);
911 msgConfirm("ERROR: Unable to write data to disk %s!\n\n"
912 "To edit the labels on a running system set\n"
913 "sysctl kern.geom.debugflags=16 and try again.", d->name);
915 return DITEM_FAILURE;
918 /* Now it's not "yes", but "written" */
919 variable_set2(DISK_PARTITIONED, "written", 0);
920 return DITEM_SUCCESS | DITEM_RESTORE;
924 /* Partition a disk based wholly on which variables are set */
926 diskPartitionNonInteractive(Device *dev)
935 size_t bootmenu_size;
940 Disk *d = (Disk *)dev->private;
943 cp = variable_get(VAR_GEOMETRY);
945 if (!strcasecmp(cp, "sane")) {
947 if (d->bios_cyl >= 65536 || d->bios_hd > 256 || d->bios_sect >= 256)
949 if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64)
952 msgDebug("Warning: A geometry of %lu/%lu/%lu for %s is incorrect.\n",
953 d->bios_cyl, d->bios_hd, d->bios_sect, d->name);
954 Sanitize_Bios_Geom(d);
955 msgDebug("Sanitized geometry for %s is %lu/%lu/%lu.\n",
956 d->name, d->bios_cyl, d->bios_hd, d->bios_sect);
959 msgDebug("Setting geometry from script to: %s\n", cp);
960 d->bios_cyl = strtol(cp, &cp, 0);
961 d->bios_hd = strtol(cp + 1, &cp, 0);
962 d->bios_sect = strtol(cp + 1, 0, 0);
966 cp = variable_get(VAR_PARTITION);
968 if (!strcmp(cp, "free")) {
969 /* Do free disk space case */
970 for (i = 0; chunk_info[i]; i++) {
971 /* If a chunk is at least 10MB in size, use it. */
972 if (chunk_info[i]->type == unused && chunk_info[i]->size > (10 * ONE_MEG)) {
973 Create_Chunk(d, chunk_info[i]->offset, chunk_info[i]->size,
975 (chunk_info[i]->flags & CHUNK_ALIGN),
977 variable_set2(DISK_PARTITIONED, "yes", 0);
981 if (!chunk_info[i]) {
982 msgConfirm("Unable to find any free space on this disk!");
986 else if (!strcmp(cp, "all")) {
987 /* Do all disk space case */
988 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name);
990 All_FreeBSD(d, FALSE);
992 else if (!strcmp(cp, "exclusive")) {
993 /* Do really-all-the-disk-space case */
994 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name);
996 All_FreeBSD(d, all_disk = TRUE);
998 else if ((sz = strtoimax(cp, &cp, 0))) {
999 /* Look for sz bytes free */
1000 if (*cp && toupper(*cp) == 'M')
1002 else if (*cp && toupper(*cp) == 'G')
1004 for (i = 0; chunk_info[i]; i++) {
1005 /* If a chunk is at least sz MB, use it. */
1006 if (chunk_info[i]->type == unused && chunk_info[i]->size >= sz) {
1007 Create_Chunk(d, chunk_info[i]->offset, sz, freebsd, 3,
1008 (chunk_info[i]->flags & CHUNK_ALIGN),
1010 variable_set2(DISK_PARTITIONED, "yes", 0);
1014 if (!chunk_info[i]) {
1015 msgConfirm("Unable to find %jd free blocks on this disk!",
1020 else if (!strcmp(cp, "existing")) {
1021 /* Do existing FreeBSD case */
1022 for (i = 0; chunk_info[i]; i++) {
1023 if (chunk_info[i]->type == freebsd)
1026 if (!chunk_info[i]) {
1027 msgConfirm("Unable to find any existing FreeBSD partitions on this disk!");
1032 msgConfirm("`%s' is an invalid value for %s - is config file valid?", cp, VAR_PARTITION);
1037 getBootMgr(d->name, &bootipl, &bootipl_size,
1038 &bootmenu, &bootmenu_size);
1039 Set_Boot_Mgr(d, bootipl, bootipl_size, bootmenu, bootmenu_size);
1041 getBootMgr(d->name, &mbrContents, &mbrSize);
1042 Set_Boot_Mgr(d, mbrContents, mbrSize);
1045 variable_set2(DISK_PARTITIONED, "yes", 0);
1048 #endif /* WITH_SLICES */