#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(void) { char * argv[] = { "/sbin/mkinitrd", "/boot/initrd", "*", NULL }; int rc; #ifdef __sparc__ return 0; #endif if (loadModule("loop", DRIVER_OTHER, NULL)) return INST_ERROR; winStatus(32, 3, "LILO", "Creating initial ramdisk..."); rc = runProgramRoot(RUN_LOG, "/mnt", "/sbin/mkinitrd", argv); newtPopWindow(); removeModule("loop"); return rc; } #define SKIP_LILO 1000 static int liloWhere(char * hdName, char * rootDevice, char ** where) { newtComponent form, okay, listbox, cancel, answer, skip; char * format = "/dev/%-7s %s"; char buf[200]; void * which; #ifdef __sparc__ newtOpenWindow(12, 6, 55, 11, "Silo Installation"); #else newtOpenWindow(12, 6, 55, 11, "Lilo Installation"); #endif 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, rootDevice, "First sector of root 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 = rootDevice; break; case 3: *where = "fd0"; break; } return 0; } 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, struct partitionTable table) { char filename[100]; FILE * f; char * argv[] = { "/mnt/sbin/lilo", "-r", "/mnt", NULL }; int i; int rc; struct stat sb; int useInitrd = 0; struct partition * root = NULL; if (mkinitrd()) 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 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"); 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); fprintf(f, "\troot=/dev/%s\n", table.parts[i].device); if (useInitrd) fprintf(f, "\tinitrd=/boot/initrd\n"); fprintf(f, "\tread-only\n"); } 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); } } } fclose(f); winStatus(35, 3, "Running", "Installing boot loader..."); #ifdef __i386__ rc = runProgram(RUN_LOG, "/mnt/sbin/lilo", argv); #elif __sparc__ rc = runProgram(RUN_LOG, "/mnt/sbin/silo", argv); #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 && (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; } #define LILO_WHERE 2 #define LILO_LABELS 3 #define LILO_INSTALL 4 #define LILO_DONE 20 int installLilo(char * prefix, struct partitionTable table, struct fstab fstab) { char * rootDevice; char * hdName; char * where; int i; int rc; int stage = LILO_WHERE; /* why not? */ rename("/mnt/etc/lilo.conf", "/mnt/etc/lilo.conf.orig"); rename("/mnt/etc/silo.conf", "/mnt/etc/silo.conf.orig"); 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, "/")) break; } rootDevice = fstab.entries[i].device; for (i = 0; i < table.count; i++) { if (!strcmp(table.parts[i].device, rootDevice)) { table.parts[i].bootLabel = strdup("linux"); break; } } while (stage != LILO_DONE) { switch (stage) { case LILO_WHERE: rc = liloWhere(hdName, rootDevice, &where); if (rc == SKIP_LILO ) return 0; if (rc) return rc; stage = LILO_LABELS; break; case LILO_LABELS: rc = getBootLabels(table, fstab); if (rc == INST_ERROR) return INST_ERROR; if (rc == INST_CANCEL) stage = LILO_WHERE; else stage = LILO_INSTALL; break; case LILO_INSTALL: rc = doinstallLilo(prefix, where, table); if (rc == INST_ERROR) return INST_ERROR; stage = LILO_DONE; break; } } return 0; }