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);
84 record_chunks(Disk *d)
86 struct chunk *c1 = NULL;
88 daddr_t last_free = 0;
91 msgFatal("No chunk list found for %s!", d->name);
93 for (c1 = d->chunks->part; c1; c1 = c1->next) {
94 if (c1->type == unused && c1->size > last_free) {
100 chunk_info[i] = NULL;
101 if (current_chunk >= i)
102 current_chunk = i - 1;
105 static daddr_t Total;
108 check_geometry(Disk *d)
113 if (d->bios_cyl >= 65536 || d->bios_hd > 256 || d->bios_sect >= 256)
115 if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64)
118 dialog_clear_norefresh();
119 sg = msgYesNo("WARNING: It is safe to use a geometry of %lu/%lu/%lu for %s on\n"
120 "computers with modern BIOS versions. If this disk is to be used\n"
121 "on an old machine it is recommended that it does not have more\n"
122 "than 65535 cylinders, more than 255 heads, or more than\n"
128 " sectors per track.\n"
130 "Would you like to keep using the current geometry?\n",
131 d->bios_cyl, d->bios_hd, d->bios_sect, d->name);
133 Sanitize_Bios_Geom(d);
134 msgConfirm("A geometry of %lu/%lu/%lu was calculated for %s.\n"
136 "If you are not sure about this, please consult the Hardware Guide\n"
137 "in the Documentation submenu or use the (G)eometry command to\n"
138 "change it. Remember: you need to enter whatever your BIOS thinks\n"
139 "the geometry is! For IDE, it's what you were told in the BIOS\n"
140 "setup. For SCSI, it's the translation mode your controller is\n"
141 "using. Do NOT use a ``physical geometry''.\n",
142 d->bios_cyl, d->bios_hd, d->bios_sect, d->name);
148 print_chunks(Disk *d, int u)
155 szstr = (u == UNIT_GIG ? "GB" : (u == UNIT_MEG ? "MB" :
156 (u == UNIT_KILO ? "KB" : "ST")));
159 for (i = 0; chunk_info[i]; i++)
160 Total += chunk_info[i]->size;
162 mvaddstr(0, 0, "Disk name:\t");
164 attrset(A_REVERSE); addstr(d->name); attrset(A_NORMAL);
165 attrset(A_REVERSE); mvaddstr(0, 55, "FDISK Partition Editor"); attrset(A_NORMAL);
167 "DISK Geometry:\t%lu cyls/%lu heads/%lu sectors = %jd sectors (%jdMB)",
168 d->bios_cyl, d->bios_hd, d->bios_sect,
169 (intmax_t)d->bios_cyl * d->bios_hd * d->bios_sect,
170 (intmax_t)d->bios_cyl * d->bios_hd * d->bios_sect / (1024/512) / 1024);
171 mvprintw(3, 0, "%6s %10s(%s) %10s %8s %6s %10s %8s %8s",
172 "Offset", "Size", szstr, "End", "Name", "PType", "Desc",
174 for (i = 0, row = CHUNK_START_ROW; chunk_info[i]; i++, row++) {
176 default: /* fall thru */
178 sz = chunk_info[i]->size;
181 sz = chunk_info[i]->size / (1024/512);
184 sz = chunk_info[i]->size / (1024/512) / 1024;
187 sz = chunk_info[i]->size / (1024/512) / 1024 / 1024;
190 if (i == current_chunk)
191 attrset(ATTR_SELECTED);
192 mvprintw(row, 0, "%10jd %10jd %10jd %8s %6d %10s %8d\t%-6s",
193 (intmax_t)chunk_info[i]->offset, (intmax_t)sz,
194 (intmax_t)chunk_info[i]->end, chunk_info[i]->name,
196 slice_type_name(chunk_info[i]->type, chunk_info[i]->subtype),
197 chunk_info[i]->subtype, ShowChunkFlags(chunk_info[i]));
198 if (i == current_chunk)
204 print_command_summary(void)
206 mvprintw(14, 0, "The following commands are supported (in upper or lower case):");
207 mvprintw(16, 0, "A = Use Entire Disk G = set Drive Geometry C = Create Slice");
208 mvprintw(17, 0, "D = Delete Slice Z = Toggle Size Units S = Set Bootable | = Expert m.");
209 mvprintw(18, 0, "T = Change Type U = Undo All Changes");
212 mvprintw(18, 47, "W = Write Changes Q = Finish");
214 mvprintw(18, 47, "Q = Finish");
215 mvprintw(21, 0, "Use F1 or ? to get more help, arrow keys to select.");
218 #endif /* WITH_SLICES */
220 #if !defined(__ia64__)
222 bootalloc(char *name, size_t *size)
224 char buf[FILENAME_MAX];
227 snprintf(buf, sizeof buf, "/boot/%s", name);
228 if (stat(buf, &sb) != -1) {
231 fd = open(buf, O_RDONLY);
235 cp = malloc(sb.st_size);
236 if (read(fd, cp, sb.st_size) != sb.st_size) {
239 msgDebug("bootalloc: couldn't read %ld bytes from %s\n", (long)sb.st_size, buf);
247 msgDebug("bootalloc: couldn't open %s\n", buf);
250 msgDebug("bootalloc: can't stat %s\n", buf);
253 #endif /* !defined(__ia64__) */
258 getBootMgr(char *dname, u_char **bootipl, size_t *bootipl_size,
259 u_char **bootmenu, size_t *bootmenu_size)
261 static u_char *boot0;
262 static size_t boot0_size;
263 static u_char *boot05;
264 static size_t boot05_size;
270 cp = variable_get(VAR_BOOTMGR);
272 /* Figure out what kind of IPL the user wants */
273 sprintf(str, "Install Boot Manager for drive %s?", dname);
274 MenuIPLType.title = str;
275 i = dmenuOpenSimple(&MenuIPLType, FALSE);
277 if (!strncmp(cp, "boot", 4))
285 if (!boot0) boot0 = bootalloc("boot0", &boot0_size);
287 *bootipl_size = boot0_size;
288 if (!boot05) boot05 = bootalloc("boot0.5", &boot05_size);
290 *bootmenu_size = boot05_size;
304 getBootMgr(char *dname, u_char **bootCode, size_t *bootCodeSize)
306 #if defined(__i386__) || defined(__amd64__) /* only meaningful on x86 */
307 static u_char *mbr, *boot0;
308 static size_t mbr_size, boot0_size;
313 cp = variable_get(VAR_BOOTMGR);
315 /* Figure out what kind of MBR the user wants */
316 sprintf(str, "Install Boot Manager for drive %s?", dname);
317 MenuMBRType.title = str;
318 i = dmenuOpenSimple(&MenuMBRType, FALSE);
321 if (!strncmp(cp, "boot", 4))
323 else if (!strcmp(cp, "standard"))
331 if (!boot0) boot0 = bootalloc("boot0", &boot0_size);
333 *bootCodeSize = boot0_size;
336 if (!mbr) mbr = bootalloc("mbr", &mbr_size);
338 *bootCodeSize = mbr_size;
350 #endif /* WITH_SLICES */
353 diskGetSelectCount(Device ***devs)
359 cp = variable_get(VAR_DISK);
360 dp = *devs = deviceFind(cp, DEVICE_TYPE_DISK);
361 cnt = deviceCount(dp);
364 for (i = 0, enabled = 0; i < cnt; i++) {
373 diskPartition(Device *dev)
384 size_t bootmenu_size;
389 WINDOW *w = savescr();
390 Disk *d = (Disk *)dev->private;
393 size_unit = UNIT_BLOCKS;
395 keypad(stdscr, TRUE);
397 /* Flush both the dialog and curses library views of the screen
398 since we don't always know who called us */
399 dialog_clear_norefresh(), clear();
402 /* Set up the chunk array */
405 /* Give the user a chance to sanitize the disk geometry, if necessary */
409 char *val, geometry[80];
411 /* Now print our overall state */
413 print_chunks(d, size_unit);
414 print_command_summary();
416 attrset(title_attr); mvprintw(23, 0, msg); attrset(A_NORMAL);
425 /* Get command character */
427 switch (toupper(key)) {
428 case '\014': /* ^L (redraw) */
433 case '\020': /* ^P */
436 if (current_chunk != 0)
440 case '\016': /* ^N */
445 if (chunk_info[current_chunk + 1])
454 while (chunk_info[current_chunk + 1])
460 systemDisplayHelp("slice");
465 #if !defined(__i386__) && !defined(__amd64__)
467 #else /* The rest is only relevant on x86 */
471 variable_set2(DISK_PARTITIONED, "yes", 0);
477 if (chunk_info[current_chunk]->type != unused)
478 msg = "Slice in use, delete it first or move to an unused one.";
480 char *val, tmp[20], name[16], *cp;
484 chunk_e partitiontype;
486 snprintf(name, sizeof (name), "%s", "FreeBSD");
487 val = msgGetInput(name,
488 "Please specify the name for new FreeBSD slice.");
490 strncpy(name, val, sizeof (name));
494 snprintf(tmp, 20, "%jd", (intmax_t)chunk_info[current_chunk]->size);
495 val = msgGetInput(tmp, "Please specify the size for new FreeBSD slice in blocks\n"
496 "or append a trailing `M' for megabytes (e.g. 20M).");
497 if (val && (dsize = strtold(val, &cp)) > 0 && dsize < UINT32_MAX) {
498 if (*cp && toupper(*cp) == 'M')
499 size = (daddr_t) (dsize * ONE_MEG);
500 else if (*cp && toupper(*cp) == 'G')
501 size = (daddr_t) (dsize * ONE_GIG);
503 size = (daddr_t) dsize;
505 if (size < ONE_MEG) {
506 msgConfirm("The minimum slice size is 1MB");
511 sprintf(tmp, "%d", SUBTYPE_FREEBSD);
512 val = msgGetInput(tmp, "Enter type of partition to create:\n\n"
513 "Pressing Enter will choose the default, a native FreeBSD\n"
516 NON_FREEBSD_NOTE, SUBTYPE_FREEBSD);
517 if (val && (subtype = strtol(val, NULL, 0)) > 0) {
518 if (subtype == SUBTYPE_FREEBSD)
519 partitiontype = freebsd;
520 else if (subtype == SUBTYPE_FAT)
522 else if (subtype == SUBTYPE_EFI)
526 partitiontype = pc98;
530 Create_Chunk(d, chunk_info[current_chunk]->offset, size, partitiontype, subtype,
531 (chunk_info[current_chunk]->flags & CHUNK_ALIGN), name);
532 variable_set2(DISK_PARTITIONED, "yes", 0);
542 if (chunk_info[current_chunk]->type == unused)
543 msg = "Slice is already unused!";
545 Delete_Chunk(d, chunk_info[current_chunk]);
546 variable_set2(DISK_PARTITIONED, "yes", 0);
552 if (chunk_info[current_chunk]->type == unused)
553 msg = "Slice is currently unused (use create instead)";
557 chunk_e partitiontype;
559 sprintf(tmp, "%d", chunk_info[current_chunk]->subtype);
560 val = msgGetInput(tmp, "New partition type:\n\n"
561 "Pressing Enter will use the current type. To choose a native\n"
562 "FreeBSD slice enter %u. "
564 NON_FREEBSD_NOTE, SUBTYPE_FREEBSD);
565 if (val && (subtype = strtol(val, NULL, 0)) > 0) {
566 if (subtype == SUBTYPE_FREEBSD)
567 partitiontype = freebsd;
568 else if (subtype == SUBTYPE_FAT)
570 else if (subtype == SUBTYPE_EFI)
574 partitiontype = pc98;
578 chunk_info[current_chunk]->type = partitiontype;
579 chunk_info[current_chunk]->subtype = subtype;
585 snprintf(geometry, 80, "%lu/%lu/%lu", d->bios_cyl, d->bios_hd, d->bios_sect);
586 val = msgGetInput(geometry, "Please specify the new geometry in cyl/hd/sect format.\n"
587 "Don't forget to use the two slash (/) separator characters!\n"
588 "It's not possible to parse the field without them.");
591 nc = strtol(val, &val, 0);
592 nh = strtol(val + 1, &val, 0);
593 ns = strtol(val + 1, 0, 0);
594 Set_Bios_Geom(d, nc, nh, ns);
600 /* Clear active states so we won't have two */
601 for (i = 0; (chunk_info[i] != NULL) && (i < CHUNK_INFO_ENTRIES); i++)
602 chunk_info[i]->flags &= !CHUNK_ACTIVE;
605 chunk_info[current_chunk]->flags |= CHUNK_ACTIVE;
609 if (!variable_cmp(DISK_LABELLED, "written")) {
610 msgConfirm("You've already written this information out - you\n"
613 else if (!msgNoYes("Are you SURE you want to Undo everything?")) {
616 sstrncpy(cp, d->name, sizeof cp);
617 Free_Disk(dev->private);
620 msgConfirm("Can't reopen disk %s! Internal state is probably corrupted", cp);
622 variable_unset(DISK_PARTITIONED);
623 variable_unset(DISK_LABELLED);
631 if (!msgNoYes("WARNING: This should only be used when modifying an EXISTING\n"
632 "installation. If you are installing FreeBSD for the first time\n"
633 "then you should simply type Q when you're finished here and your\n"
634 "changes will be committed in one batch automatically at the end of\n"
635 "these questions. If you're adding a disk, you should NOT write\n"
636 "from this screen, you should do it from the label editor.\n\n"
637 "Are you absolutely sure you want to do this now?")) {
638 variable_set2(DISK_PARTITIONED, "yes", 0);
642 * Don't trash the IPL if the first (and therefore only) chunk
643 * is marked for a truly dedicated disk (i.e., the disklabel
644 * starts at sector 0), even in cases where the user has
645 * requested a FreeBSD Boot Manager -- both would be fatal in
649 * Don't offer to update the IPL on this disk if the first
650 * "real" chunk looks like a FreeBSD "all disk" partition,
651 * or the disk is entirely FreeBSD.
653 if ((d->chunks->part->type != freebsd) ||
654 (d->chunks->part->offset > 1))
655 getBootMgr(d->name, &bootipl, &bootipl_size,
656 &bootmenu, &bootmenu_size);
663 Set_Boot_Mgr(d, bootipl, bootipl_size, bootmenu, bootmenu_size);
666 * Don't trash the MBR if the first (and therefore only) chunk
667 * is marked for a truly dedicated disk (i.e., the disklabel
668 * starts at sector 0), even in cases where the user has
669 * requested booteasy or a "standard" MBR -- both would be
670 * fatal in this case.
673 * Don't offer to update the MBR on this disk if the first
674 * "real" chunk looks like a FreeBSD "all disk" partition,
675 * or the disk is entirely FreeBSD.
677 if ((d->chunks->part->type != freebsd) ||
678 (d->chunks->part->offset > 1))
679 getBootMgr(d->name, &mbrContents, &mbrSize);
684 Set_Boot_Mgr(d, mbrContents, mbrSize);
687 if (DITEM_STATUS(diskPartitionWrite(NULL)) != DITEM_SUCCESS)
688 msgConfirm("Disk partition write returned an error status!");
690 msgConfirm("Wrote FDISK partition information out successfully.");
696 if (!msgNoYes("Are you SURE you want to go into Expert mode?\n"
697 "No seat belts whatsoever are provided!")) {
701 variable_set2(DISK_PARTITIONED, "yes", 0);
705 msg = "Wise choice!";
709 case '\033': /* ESC */
714 * Don't trash the IPL if the first (and therefore only) chunk
715 * is marked for a truly dedicated disk (i.e., the disklabel
716 * starts at sector 0), even in cases where the user has requested
717 * a FreeBSD Boot Manager -- both would be fatal in this case.
720 * Don't offer to update the IPL on this disk if the first "real"
721 * chunk looks like a FreeBSD "all disk" partition, or the disk is
724 if ((d->chunks->part->type != freebsd) ||
725 (d->chunks->part->offset > 1)) {
726 if (variable_cmp(DISK_PARTITIONED, "written")) {
727 getBootMgr(d->name, &bootipl, &bootipl_size,
728 &bootmenu, &bootmenu_size);
729 if (bootipl != NULL && bootmenu != NULL)
730 Set_Boot_Mgr(d, bootipl, bootipl_size,
731 bootmenu, bootmenu_size);
736 * Don't trash the MBR if the first (and therefore only) chunk
737 * is marked for a truly dedicated disk (i.e., the disklabel
738 * starts at sector 0), even in cases where the user has requested
739 * booteasy or a "standard" MBR -- both would be fatal in this case.
742 * Don't offer to update the MBR on this disk if the first "real"
743 * chunk looks like a FreeBSD "all disk" partition, or the disk is
746 if ((d->chunks->part->type != freebsd) ||
747 (d->chunks->part->offset > 1)) {
748 if (variable_cmp(DISK_PARTITIONED, "written")) {
749 getBootMgr(d->name, &mbrContents, &mbrSize);
750 if (mbrContents != NULL)
751 Set_Boot_Mgr(d, mbrContents, mbrSize);
758 size_unit = (size_unit + 1) % UNIT_SIZE;
763 msg = "Type F1 or ? for help";
769 char buf[FILENAME_MAX];
771 use_helpline("Press F1 to read more about disk slices.");
772 use_helpfile(systemHelpFile("partition", buf));
773 if (!variable_get(VAR_NO_WARN))
774 dialog_mesgbox("Disk slicing warning:", p, -1, -1);
779 #endif /* WITH_SLICES */
783 partitionHook(dialogMenuItem *selected)
785 Device **devs = NULL;
787 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK);
789 msgConfirm("Unable to find disk %s!", selected->prompt);
790 return DITEM_FAILURE;
792 /* Toggle enabled status? */
793 if (!devs[0]->enabled) {
794 devs[0]->enabled = TRUE;
795 diskPartition(devs[0]);
798 devs[0]->enabled = FALSE;
799 return DITEM_SUCCESS;
803 partitionCheck(dialogMenuItem *selected)
805 Device **devs = NULL;
807 devs = deviceFind(selected->prompt, DEVICE_TYPE_DISK);
808 if (!devs || devs[0]->enabled == FALSE)
814 diskPartitionEditor(dialogMenuItem *self)
820 cnt = diskGetSelectCount(&devs);
821 devcnt = deviceCount(devs);
823 msgConfirm("No disks found! Please verify that your disk controller is being\n"
824 "properly probed at boot time. See the Hardware Guide on the\n"
825 "Documentation menu for clues on diagnosing this type of problem.");
826 return DITEM_FAILURE;
829 /* Some are already selected */
830 for (i = 0; i < devcnt; i++) {
831 if (devs[i]->enabled) {
832 if (variable_get(VAR_NONINTERACTIVE) &&
833 !variable_get(VAR_DISKINTERACTIVE))
834 diskPartitionNonInteractive(devs[i]);
836 diskPartition(devs[i]);
841 /* No disks are selected, fall-back case now */
843 devs[0]->enabled = TRUE;
844 if (variable_get(VAR_NONINTERACTIVE) &&
845 !variable_get(VAR_DISKINTERACTIVE))
846 diskPartitionNonInteractive(devs[0]);
848 diskPartition(devs[0]);
849 return DITEM_SUCCESS;
852 menu = deviceCreateMenu(&MenuDiskDevices, DEVICE_TYPE_DISK, partitionHook, partitionCheck);
854 msgConfirm("No devices suitable for installation found!\n\n"
855 "Please verify that your disk controller (and attached drives)\n"
856 "were detected properly. This can be done by pressing the\n"
857 "[Scroll Lock] key and using the Arrow keys to move back to\n"
858 "the boot messages. Press [Scroll Lock] again to return.");
859 return DITEM_FAILURE;
862 i = dmenuOpenSimple(menu, FALSE) ? DITEM_SUCCESS : DITEM_FAILURE;
868 return DITEM_SUCCESS;
870 #endif /* WITH_SLICES */
873 diskPartitionWrite(dialogMenuItem *self)
878 if (!variable_cmp(DISK_PARTITIONED, "written"))
879 return DITEM_SUCCESS;
881 devs = deviceFind(NULL, DEVICE_TYPE_DISK);
883 msgConfirm("Unable to find any disks to write to??");
884 return DITEM_FAILURE;
887 msgDebug("diskPartitionWrite: Examining %d devices\n", deviceCount(devs));
888 for (i = 0; devs[i]; i++) {
889 Disk *d = (Disk *)devs[i]->private;
890 #if !defined(__ia64__)
891 static u_char *boot1;
893 #if defined(__i386__) || defined(__amd64__)
894 static u_char *boot2;
897 if (!devs[i]->enabled)
900 #if defined(__i386__) || defined(__amd64__)
901 if (!boot1) boot1 = bootalloc("boot1", NULL);
902 if (!boot2) boot2 = bootalloc("boot2", NULL);
903 Set_Boot_Blocks(d, boot1, boot2);
904 #elif !defined(__ia64__)
905 if (!boot1) boot1 = bootalloc("boot1", NULL);
906 Set_Boot_Blocks(d, boot1, NULL);
909 msgNotify("Writing partition information to drive %s", d->name);
910 if (!Fake && Write_Disk(d)) {
912 msgConfirm("ERROR: Unable to write data to disk %s!", d->name);
914 msgConfirm("ERROR: Unable to write data to disk %s!\n\n"
915 "To edit the labels on a running system set\n"
916 "sysctl kern.geom.debugflags=16 and try again.", d->name);
918 return DITEM_FAILURE;
921 /* Now it's not "yes", but "written" */
922 variable_set2(DISK_PARTITIONED, "written", 0);
923 return DITEM_SUCCESS | DITEM_RESTORE;
927 /* Partition a disk based wholly on which variables are set */
929 diskPartitionNonInteractive(Device *dev)
939 size_t bootmenu_size;
944 Disk *d = (Disk *)dev->private;
947 cp = variable_get(VAR_GEOMETRY);
949 if (!strcasecmp(cp, "sane")) {
951 if (d->bios_cyl >= 65536 || d->bios_hd > 256 || d->bios_sect >= 256)
953 if (d->bios_cyl > 65536 || d->bios_hd > 256 || d->bios_sect >= 64)
956 msgDebug("Warning: A geometry of %lu/%lu/%lu for %s is incorrect.\n",
957 d->bios_cyl, d->bios_hd, d->bios_sect, d->name);
958 Sanitize_Bios_Geom(d);
959 msgDebug("Sanitized geometry for %s is %lu/%lu/%lu.\n",
960 d->name, d->bios_cyl, d->bios_hd, d->bios_sect);
963 msgDebug("Setting geometry from script to: %s\n", cp);
964 d->bios_cyl = strtol(cp, &cp, 0);
965 d->bios_hd = strtol(cp + 1, &cp, 0);
966 d->bios_sect = strtol(cp + 1, 0, 0);
970 cp = variable_get(VAR_PARTITION);
972 if (!strcmp(cp, "free")) {
973 /* Do free disk space case */
974 for (i = 0; chunk_info[i]; i++) {
975 /* If a chunk is at least 10MB in size, use it. */
976 if (chunk_info[i]->type == unused && chunk_info[i]->size > (10 * ONE_MEG)) {
977 Create_Chunk(d, chunk_info[i]->offset, chunk_info[i]->size,
978 freebsd, SUBTYPE_FREEBSD,
979 (chunk_info[i]->flags & CHUNK_ALIGN),
981 variable_set2(DISK_PARTITIONED, "yes", 0);
985 if (!chunk_info[i]) {
986 msgConfirm("Unable to find any free space on this disk!");
990 else if (!strcmp(cp, "all")) {
991 /* Do all disk space case */
992 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name);
994 All_FreeBSD(d, FALSE);
996 else if (!strcmp(cp, "exclusive")) {
997 /* Do really-all-the-disk-space case */
998 msgDebug("Warning: Devoting all of disk %s to FreeBSD.\n", d->name);
1000 All_FreeBSD(d, all_disk = TRUE);
1002 else if ((dsize = strtold(cp, &cp))) {
1003 if (*cp && toupper(*cp) == 'M')
1004 size *= (daddr_t) (dsize * ONE_MEG);
1005 else if (*cp && toupper(*cp) == 'G')
1006 size = (daddr_t) (dsize * ONE_GIG);
1008 size = (daddr_t) dsize;
1010 /* Look for size bytes free */
1011 for (i = 0; chunk_info[i]; i++) {
1012 /* If a chunk is at least sz MB, use it. */
1013 if (chunk_info[i]->type == unused && chunk_info[i]->size >= size) {
1014 Create_Chunk(d, chunk_info[i]->offset, size, freebsd, SUBTYPE_FREEBSD,
1015 (chunk_info[i]->flags & CHUNK_ALIGN),
1017 variable_set2(DISK_PARTITIONED, "yes", 0);
1021 if (!chunk_info[i]) {
1022 msgConfirm("Unable to find %jd free blocks on this disk!",
1027 else if (!strcmp(cp, "existing")) {
1028 /* Do existing FreeBSD case */
1029 for (i = 0; chunk_info[i]; i++) {
1030 if (chunk_info[i]->type == freebsd)
1033 if (!chunk_info[i]) {
1034 msgConfirm("Unable to find any existing FreeBSD partitions on this disk!");
1039 msgConfirm("`%s' is an invalid value for %s - is config file valid?", cp, VAR_PARTITION);
1044 getBootMgr(d->name, &bootipl, &bootipl_size,
1045 &bootmenu, &bootmenu_size);
1046 Set_Boot_Mgr(d, bootipl, bootipl_size, bootmenu, bootmenu_size);
1048 getBootMgr(d->name, &mbrContents, &mbrSize);
1049 Set_Boot_Mgr(d, mbrContents, mbrSize);
1052 variable_set2(DISK_PARTITIONED, "yes", 0);
1055 #endif /* WITH_SLICES */