#include #include #include #include #include #include #include #include "devices.h" #include "install.h" #include "lilo.h" #include "log.h" #include "run.h" #include "windows.h" #ifdef __i386__ static char * kernelPath = "/boot/vmlinuz"; #elif __sparc__ static char * kernelPath = "/boot/vmlinux.gz"; #else #error unsupported architecture #endif static int mkinitrd(char * kernelVersion) { char * argv[] = { "/sbin/mkinitrd", "/boot/initrd", "--ifneeded", kernelVersion, NULL }; int rc; static alreadyHappened = 0; #ifdef __sparc__ return 0; #endif if (alreadyHappened) return 0; if (!access("/mnt/boot/initrd", X_OK)) { logMessage("/mnt/boot/initrd exists -- moving to " "/mnt/boot/initrd.orig"); rename("/mnt/boot/initrd", "/mnt/boot/initrd.orig"); } if (loadModule("loop", DRIVER_OTHER, DRIVER_MINOR_NONE, NULL)) return INST_ERROR; winStatus(32, 3, "LILO", "Creating initial ramdisk..."); rc = runProgramRoot(RUN_LOG, "/mnt", "/sbin/mkinitrd", argv); newtPopWindow(); removeModule("loop"); if (rc) { unlink("/mnt/boot/initrd"); } else { alreadyHappened = 1; } return rc; } #define SKIP_LILO 1000 #if defined(__i386__) static int liloWhere(char * hdName, char * bootDevice, char ** where) { newtComponent form, okay, listbox, cancel, answer, skip; char * format = "/dev/%-7s %s"; char buf[200]; void * which; newtOpenWindow(12, 6, 55, 11, "Lilo Installation"); form = newtForm(NULL, NULL, 0); newtFormAddComponent(form, newtLabel(1, 1, "Where do you want to install " "the bootloader?")); listbox = newtListbox(2, 3, 3, NEWT_LISTBOX_RETURNEXIT); sprintf(buf, format, hdName, "Master Boot Record"); newtListboxAddEntry(listbox, buf, (void *) 1); sprintf(buf, format, bootDevice, "First sector of boot partition"); newtListboxAddEntry(listbox, buf, (void *) 2); sprintf(buf, format, "fd0", "First sector of a floppy disk"); newtListboxAddEntry(listbox, buf, (void *) 3); okay = newtButton(6, 7, "Ok"); skip = newtButton(22, 7, "Skip"); cancel = newtButton(38, 7, "Cancel"); newtFormAddComponents(form, listbox, okay, skip, cancel, NULL); answer = newtRunForm(form); which = newtListboxGetCurrent(listbox); newtFormDestroy(form); newtPopWindow(); if (answer == cancel) return INST_CANCEL; if (answer == skip) return SKIP_LILO; switch ((int) which) { case 1: *where = hdName; break; case 2: *where = bootDevice; break; case 3: *where = "fd0"; break; } return 0; } #elif defined(__sparc__) static int liloWhere(char * hdName, char * bootDevice, char ** where) { newtComponent text, yes, no, cancel, f, answer; int rc; newtOpenWindow(18, 6, 42, 10, "SILO Installation"); text = newtTextbox(1, 1, 40, 3, NEWT_TEXTBOX_WRAP); newtTextboxSetText(text, "Would you like to install or configure the SILO bootloader on " "your system?"); yes = newtButton(3, 6, " Yes "); no = newtButton(16, 6, " No "); cancel = newtButton(29, 6, "Cancel"); f = newtForm(NULL, NULL, 0); newtFormAddComponents(f, text, yes, no, cancel, NULL); answer = newtRunForm(f); if (answer == f) answer = newtFormGetCurrent(f); newtPopWindow(); newtFormDestroy(f); if (answer == yes) { *where = bootDevice; rc = 0; } else if (answer == cancel) { rc = INST_CANCEL; return INST_CANCEL; } else { rc = SKIP_LILO; } return rc; } #endif static void editBootLabel(struct partition * item) { newtComponent form, entry, okay, cancel, clear, answer; char buf[50]; char * entryValue; newtOpenWindow(10, 7, 50, 10, "Edit Boot Label"); form = newtForm(NULL, NULL, 0); strcpy(buf,"Device : /dev/"); strcat(buf, item->device); newtFormAddComponent(form, newtLabel(1, 1, buf)); newtFormAddComponent(form, newtLabel(1, 3, "Boot label :")); entry = newtEntry(17, 3, item->bootLabel, 20, &entryValue, NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT); okay = newtButton(5, 6, "Ok"); clear = newtButton(20, 6, "Clear"); cancel = newtButton(35, 6, "Cancel"); newtFormAddComponents(form, entry, okay, clear, cancel, NULL); do { answer = newtRunForm(form); if (answer == clear) newtEntrySet(entry, "", 1); } while (answer == clear); if (answer != cancel) { if (item->bootLabel) free(item->bootLabel); if (strlen(entryValue)) item->bootLabel = strdup(entryValue); else item->bootLabel = NULL; } newtPopWindow(); } static int doinstallLilo(char * prefix, char * dev, char * rootdev, struct partitionTable table, char * append, char * kernelVersion, char * hdname, int linear) { char filename[100]; FILE * f; char * argv[] = { "/mnt/sbin/lilo", NULL }; int i; int rc; struct stat sb; int useInitrd = 0; struct partition * root = NULL; if (mkinitrd(kernelVersion)) return INST_ERROR; if (!stat("/mnt/boot/initrd", &sb)) useInitrd = 1; #ifdef __sparc__ sprintf(filename, "%s/silo.conf", prefix); #else sprintf(filename, "%s/lilo.conf", prefix); #endif /* why not? */ rename("/mnt/etc/lilo.conf", "/mnt/etc/lilo.conf.orig"); rename("/mnt/etc/silo.conf", "/mnt/etc/silo.conf.orig"); f = fopen(filename, "w"); if (!f) { errorWindow("cannot create [ls]ilo config file: %s"); return INST_ERROR; } logMessage("writing [sl]ilo config to %s", filename); for (i = 0; i < table.count; i++) { if (table.parts[i].bootLabel && table.parts[i].type == PART_EXT2) { root = table.parts + i; } } if (!root) { errorWindow("No ext2 partition is bootable"); return INST_ERROR; } #ifdef __i386__ fprintf(f, "boot=/dev/%s\n", dev); fprintf(f, "map=/boot/map\n"); fprintf(f, "install=/boot/boot.b\n"); fprintf(f, "prompt\n"); if (linear) fprintf(f, "linear\n"); fprintf(f, "timeout=50\n"); #elif __sparc__ fprintf(f, "timeout=50\n"); fprintf(f, "partition=%s\n", root->device + 3); fprintf(f, "root=/dev/%s\n", root->device); #else #error "unsupported architecture"; #endif for (i = 0; i < table.count; i++) { if (table.parts[i].bootLabel) { if (table.parts[i].type == PART_EXT2) { fprintf(f, "image=%s\n", kernelPath); fprintf(f, "\tlabel=%s\n", table.parts[i].bootLabel); /* we can setup a /boot on the fresh system if we need to */ if (!strcmp(table.parts[i].device, dev)) fprintf(f, "\troot=/dev/%s\n", rootdev); else fprintf(f, "\troot=/dev/%s\n", table.parts[i].device); if (useInitrd) fprintf(f, "\tinitrd=/boot/initrd\n"); if (append) fprintf(f, "\tappend=\"%s\"\n", append); fprintf(f, "\tread-only\n"); #ifdef __i386__ } else { fprintf(f, "other=/dev/%s\n", table.parts[i].device); fprintf(f, "\tlabel=%s\n", table.parts[i].bootLabel); fprintf(f, "\ttable=/dev/%.3s\n", table.parts[i].device); if (strncmp(table.parts[i].device, hdname, 3)) fprintf(f, "\tloader=/boot/any_d.b\n"); #endif } } } fclose(f); winStatus(35, 3, "Running", "Installing boot loader..."); #ifdef __i386__ rc = runProgramRoot(RUN_LOG, "/mnt", "sbin/lilo", argv); #elif __sparc__ rc = doMount("/proc", "/mnt/proc", "proc", 0, 0); if (rc) { newtPopWindow(); return rc; } rc = runProgramRoot(RUN_LOG, "/mnt", "sbin/silo", argv); umount("/mnt/proc"); #else #error unsupported architectures #endif newtPopWindow(); if (rc) return INST_ERROR; return 0; } static int getBootLabels(struct partitionTable table, struct fstab fstab) { newtComponent f, okay, text, listbox, label, cancel, edit, answer; char buf[80]; int i, j; int foundDos = 0; int mustAsk = 0; int * map; struct partition * curr; int * currNum; int count; f = newtForm(NULL, NULL, 0); text = newtTextbox(1, 1, 60, 4, NEWT_TEXTBOX_WRAP); newtTextboxSetText(text, "The boot manager Red Hat uses can boot other " "operating systems as well. You need to tell me " "what partitions you would like to be able to boot " "and what label you want to use for each of them."); sprintf(buf, "%-10s %-25s %-18s", "Device", "Partition type", "Boot label"); label = newtLabel(1, 6, buf); listbox = newtListbox(1, 7, 7, NEWT_LISTBOX_RETURNEXIT); map = alloca(sizeof(int) * table.count); for (i = 0, count = 0; i < table.count; i++) { if (table.parts[i].type != PART_SWAP && table.parts[i].type != PART_IGNORE && #ifdef __sparc__ table.parts[i].type != PART_OTHER && #endif (table.parts[i].type != PART_DOS || !foundDos)) { if (table.parts[i].type == PART_DOS) { table.parts[i].bootLabel = strdup("dos"); foundDos = 1; } if (table.parts[i].type == PART_EXT2) { for (j = 0; j < fstab.numEntries; j++) { if (!strcmp(table.parts[i].device, fstab.entries[j].device)) break; } if (j < fstab.numEntries && !table.parts[i].bootLabel) continue; } if (!table.parts[i].bootLabel || strcmp(table.parts[i].bootLabel, "linux")) mustAsk = 1; sprintf(buf, "/dev/%-5s %-25s %-18s", table.parts[i].device, table.parts[i].tagName, table.parts[i].bootLabel ? table.parts[i].bootLabel : ""); map[count] = i; newtListboxAddEntry(listbox, buf, map + count++); } } newtFormAddComponents(f, text, label, listbox, NULL); if (!mustAsk) { newtFormDestroy(f); return 0; } newtOpenWindow(8, 2, 64, 19, "Bootable Partitions"); okay = newtButton(8, 15, "Ok"); edit = newtButton(26, 15, "Edit"); cancel = newtButton(44, 15, "Cancel"); newtFormAddComponents(f, okay, edit, cancel, NULL); do { answer = newtRunForm(f); if (answer == edit || answer == listbox) { currNum = newtListboxGetCurrent(listbox); curr = table.parts + *currNum; editBootLabel(curr); sprintf(buf, "/dev/%-5s %-25s %-18s", curr->device, curr->tagName, curr->bootLabel ? curr->bootLabel : ""); newtListboxSetEntry(listbox, currNum - map, buf); } } while (answer == edit || answer == listbox); newtFormDestroy(f); newtPopWindow(); if (answer == cancel) return INST_CANCEL; else return 0; } static int getAppendLine(char ** line, int * linear) { newtComponent form, text, entry, okay, cancel, answer; newtComponent linearCheck; char * result = NULL; char linearChar = (*linear) ? '*' : ' '; int buttonLine = 9; #ifdef __sparc__ newtOpenWindow(12, 5, 55, 13, "Silo Installation"); #else /* this is bigger on the Intel to leave room for the linear checkbox */ newtOpenWindow(12, 5, 55, 15, "Lilo Installation"); #endif form = newtForm(NULL, NULL, 0); text = newtTextbox(1, 1, 53, 5, NEWT_TEXTBOX_WRAP); newtTextboxSetText(text, "A few systems will need to pass special options " "to the kernel at boot time for the system to function " "properly. If you need to pass boot options to the " "kernel, enter them now. If you don't need any or " "aren't sure, leave this blank."); entry = newtEntry(1, 7, *line, 48, &result, NEWT_ENTRY_SCROLL | NEWT_ENTRY_RETURNEXIT); #ifndef __sparc__ buttonLine = 11; linearCheck = newtCheckbox(1, 9, "Use linear mode (needed for some SCSI drives)", linearChar, NULL, &linearChar); #endif okay = newtButton(12, buttonLine, "Ok"); cancel = newtButton(35, buttonLine, "Cancel"); newtFormAddComponents(form, text, entry, NULL); #ifndef __sparc__ newtFormAddComponent(form, linearCheck); #endif newtFormAddComponents(form, okay, cancel, NULL); newtFormSetCurrent(form, okay); answer = newtRunForm(form); newtPopWindow(); if (answer == cancel) { newtFormDestroy(form); return INST_CANCEL; } *linear = linearChar != ' '; if (!strlen(result)) *line = NULL; else *line = strdup(result); newtFormDestroy(form); return 0; } #define LILO_WHERE 2 #define LILO_LABELS 3 #define LILO_INSTALL 4 #define LILO_APPEND 5 #define LILO_DONE 20 int installLilo(char * prefix, struct partitionTable table, struct fstab fstab, char * kernelVersion) { char * rootDevice, * bootDevice = NULL; char * hdName; char * where; char * append = NULL; char * chptr = NULL; int i; int rc; int stage = LILO_WHERE; static int linear = 0; hdName = alloca(4); strncpy(hdName, table.parts[0].device, 3); hdName[3] = '\0'; for (i = 0; i < fstab.numEntries; i++) { if (!strcmp(fstab.entries[i].mntpoint, "/boot")) break; } if (i < fstab.numEntries) bootDevice = fstab.entries[i].device; for (i = 0; i < fstab.numEntries; i++) { if (!strcmp(fstab.entries[i].mntpoint, "/")) break; } rootDevice = fstab.entries[i].device; if (!bootDevice) { bootDevice = rootDevice; } for (i = 0; i < table.count; i++) { if (!strcmp(table.parts[i].device, bootDevice)) { table.parts[i].bootLabel = strdup("linux"); break; } } while (stage != LILO_DONE) { switch (stage) { case LILO_WHERE: rc = liloWhere(hdName, bootDevice, &where); if (rc == SKIP_LILO ) return 0; if (rc) return rc; stage = LILO_APPEND; break; case LILO_APPEND: chptr = append; rc = getAppendLine(&chptr, &linear); if (rc == INST_ERROR) return INST_ERROR; if (rc == INST_CANCEL) stage = LILO_WHERE; else { stage = LILO_LABELS; if (append) free(append); if (chptr) { append = alloca(strlen(chptr) + 1); strcpy(append, chptr); free(chptr); } else { append = NULL; } } break; case LILO_LABELS: rc = getBootLabels(table, fstab); if (rc == INST_ERROR) return INST_ERROR; if (rc == INST_CANCEL) stage = LILO_APPEND; else stage = LILO_INSTALL; break; case LILO_INSTALL: rc = doinstallLilo(prefix, where, rootDevice, table, append, kernelVersion, hdName, linear); if (rc == INST_ERROR) return INST_ERROR; stage = LILO_DONE; break; } } return 0; }