--- trunk/grubby/grubby.c 2012/07/02 13:08:29 1849 +++ tags/grubby-8_20/grubby.c 2013/02/20 14:02:40 2055 @@ -56,6 +56,8 @@ #define NOOP_OPCODE 0x90 #define JMP_SHORT_OPCODE 0xeb +int isEfi = 0; + /* comments get lumped in with indention */ struct lineElement { char * item; @@ -82,7 +84,9 @@ LT_MENUENTRY = 1 << 17, LT_ENTRY_END = 1 << 18, LT_SET_VARIABLE = 1 << 19, - LT_UNKNOWN = 1 << 20, + LT_KERNEL_EFI = 1 << 20, + LT_INITRD_EFI = 1 << 21, + LT_UNKNOWN = 1 << 22, }; struct singleLine { @@ -164,9 +168,9 @@ const char *grubFindConfig(struct configFileInfo *cfi) { static const char *configFiles[] = { - "/etc/grub.conf", "/boot/grub/grub.conf", "/boot/grub/menu.lst", + "/etc/grub.conf", NULL }; static int i = -1; @@ -205,7 +209,9 @@ { "default", LT_DEFAULT, ' ' }, { "fallback", LT_FALLBACK, ' ' }, { "linux", LT_KERNEL, ' ' }, + { "linuxefi", LT_KERNEL_EFI, ' ' }, { "initrd", LT_INITRD, ' ', ' ' }, + { "initrdefi", LT_INITRD_EFI, ' ', ' ' }, { "module", LT_MBMODULE, ' ' }, { "kernel", LT_HYPER, ' ' }, { NULL, 0, 0 }, @@ -271,6 +277,14 @@ return 0; } +static int iskernel(enum lineType_e type) { + return (type == LT_KERNEL || type == LT_KERNEL_EFI); +} + +static int isinitrd(enum lineType_e type) { + return (type == LT_INITRD || type == LT_INITRD_EFI); +} + char *grub2ExtractTitle(struct singleLine * line) { char * current; char * current_indent; @@ -570,6 +584,21 @@ return buf; } +static enum lineType_e preferredLineType(enum lineType_e type, + struct configFileInfo *cfi) { + if (isEfi && cfi == &grub2ConfigType) { + switch (type) { + case LT_KERNEL: + return LT_KERNEL_EFI; + case LT_INITRD: + return LT_INITRD_EFI; + default: + return type; + } + } + return type; +} + static struct keywordTypes * getKeywordByType(enum lineType_e type, struct configFileInfo * cfi) { for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) { @@ -994,7 +1023,7 @@ cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT; defaultLine = line; - } else if (line->type == LT_KERNEL) { + } else if (iskernel(line->type)) { /* if by some freak chance this is multiboot and the "module" * lines came earlier in the template, make sure to use LT_HYPER * instead of LT_KERNEL now @@ -1011,7 +1040,7 @@ for (struct singleLine *l = entry->lines; l; l = l->next) { if (l->type == LT_HYPER) break; - else if (l->type == LT_KERNEL) { + else if (iskernel(l->type)) { l->type = LT_HYPER; break; } @@ -1310,7 +1339,8 @@ /* most likely the symlink is relative, so change our directory to the dir of the symlink */ - rc = chdir(dirname(outName)); + char *dir = strdupa(outName); + rc = chdir(dirname(dir)); do { buf = alloca(len + 1); rc = readlink(basename(outName), buf, len); @@ -1564,7 +1594,7 @@ return 0; } - line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines); + line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI, entry->lines); if (!line) { notSuitablePrintf(entry, "no line found\n"); return 0; @@ -1694,7 +1724,7 @@ entry = findEntryByIndex(config, indexVars[i]); if (!entry) return NULL; - line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines); + line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI, entry->lines); if (!line) return NULL; if (index) *index = indexVars[i]; @@ -1743,10 +1773,14 @@ /* check all the lines matching checkType */ for (line = entry->lines; line; line = line->next) { - line = getLineByType(entry->multiboot && checkType == LT_KERNEL ? - LT_KERNEL|LT_MBMODULE|LT_HYPER : - checkType, line); - if (!line) break; /* not found in this entry */ + enum lineType_e ct = checkType; + if (entry->multiboot && checkType == LT_KERNEL) + ct = LT_KERNEL|LT_KERNEL_EFI|LT_MBMODULE|LT_HYPER; + else if (checkType & LT_KERNEL) + ct = checkType | LT_KERNEL_EFI; + line = getLineByType(ct, line); + if (!line) + break; /* not found in this entry */ if (line && line->type != LT_MENUENTRY && line->numElements >= 2) { @@ -1765,7 +1799,7 @@ * non-Linux boot entries (could find netbsd etc, though, which is * unfortunate) */ - if (line && getLineByType(LT_KERNEL|LT_HYPER, entry->lines)) + if (line && getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI, entry->lines)) break; /* found 'im! */ } @@ -1867,13 +1901,19 @@ void setDefaultImage(struct grubConfig * config, int hasNew, const char * defaultKernelPath, int newIsDefault, - const char * prefix, int flags) { + const char * prefix, int flags, int index) { struct singleEntry * entry, * entry2, * newDefault; int i, j; if (newIsDefault) { config->defaultImage = 0; return; + } else if ((index >= 0) && config->cfi->defaultIsIndex) { + if (findEntryByIndex(config, index)) + config->defaultImage = index; + else + config->defaultImage = -1; + return; } else if (defaultKernelPath) { i = 0; if (findEntryByPath(config, defaultKernelPath, prefix, &i)) { @@ -1948,7 +1988,7 @@ printf("index=%d\n", index); - line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines); + line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI, entry->lines); if (!line) { printf("non linux entry\n"); return; @@ -2013,7 +2053,7 @@ printf("root=%s\n", s); } - line = getLineByType(LT_INITRD, entry->lines); + line = getLineByType(LT_INITRD|LT_INITRD_EFI, entry->lines); if (line && line->numElements >= 2) { if (!strncmp(prefix, line->elements[1].item, strlen(prefix))) @@ -2038,6 +2078,267 @@ } } +int isSuseSystem(void) { + const char * path; + const static char default_path[] = "/etc/SuSE-release"; + + if ((path = getenv("GRUBBY_SUSE_RELEASE")) == NULL) + path = default_path; + + if (!access(path, R_OK)) + return 1; + return 0; +} + +int isSuseGrubConf(const char * path) { + FILE * grubConf; + char * line = NULL; + size_t len = 0, res = 0; + + grubConf = fopen(path, "r"); + if (!grubConf) { + dbgPrintf("Could not open SuSE configuration file '%s'\n", path); + return 0; + } + + while ((res = getline(&line, &len, grubConf)) != -1) { + if (!strncmp(line, "setup", 5)) { + fclose(grubConf); + free(line); + return 1; + } + } + + dbgPrintf("SuSE configuration file '%s' does not appear to be valid\n", + path); + + fclose(grubConf); + free(line); + return 0; +} + +int suseGrubConfGetLba(const char * path, int * lbaPtr) { + FILE * grubConf; + char * line = NULL; + size_t res = 0, len = 0; + + if (!path) return 1; + if (!lbaPtr) return 1; + + grubConf = fopen(path, "r"); + if (!grubConf) return 1; + + while ((res = getline(&line, &len, grubConf)) != -1) { + if (line[res - 1] == '\n') + line[res - 1] = '\0'; + else if (len > res) + line[res] = '\0'; + else { + line = realloc(line, res + 1); + line[res] = '\0'; + } + + if (!strncmp(line, "setup", 5)) { + if (strstr(line, "--force-lba")) { + *lbaPtr = 1; + } else { + *lbaPtr = 0; + } + dbgPrintf("lba: %i\n", *lbaPtr); + break; + } + } + + free(line); + fclose(grubConf); + return 0; +} + +int suseGrubConfGetInstallDevice(const char * path, char ** devicePtr) { + FILE * grubConf; + char * line = NULL; + size_t res = 0, len = 0; + char * lastParamPtr = NULL; + char * secLastParamPtr = NULL; + char installDeviceNumber = '\0'; + char * bounds = NULL; + + if (!path) return 1; + if (!devicePtr) return 1; + + grubConf = fopen(path, "r"); + if (!grubConf) return 1; + + while ((res = getline(&line, &len, grubConf)) != -1) { + if (strncmp(line, "setup", 5)) + continue; + + if (line[res - 1] == '\n') + line[res - 1] = '\0'; + else if (len > res) + line[res] = '\0'; + else { + line = realloc(line, res + 1); + line[res] = '\0'; + } + + lastParamPtr = bounds = line + res; + + /* Last parameter in grub may be an optional IMAGE_DEVICE */ + while (!isspace(*lastParamPtr)) + lastParamPtr--; + lastParamPtr++; + + secLastParamPtr = lastParamPtr - 2; + dbgPrintf("lastParamPtr: %s\n", lastParamPtr); + + if (lastParamPtr + 3 > bounds) { + dbgPrintf("lastParamPtr going over boundary"); + fclose(grubConf); + free(line); + return 1; + } + if (!strncmp(lastParamPtr, "(hd", 3)) + lastParamPtr += 3; + dbgPrintf("lastParamPtr: %c\n", *lastParamPtr); + + /* + * Second last parameter will decide wether last parameter is + * an IMAGE_DEVICE or INSTALL_DEVICE + */ + while (!isspace(*secLastParamPtr)) + secLastParamPtr--; + secLastParamPtr++; + + if (secLastParamPtr + 3 > bounds) { + dbgPrintf("secLastParamPtr going over boundary"); + fclose(grubConf); + free(line); + return 1; + } + dbgPrintf("secLastParamPtr: %s\n", secLastParamPtr); + if (!strncmp(secLastParamPtr, "(hd", 3)) { + secLastParamPtr += 3; + dbgPrintf("secLastParamPtr: %c\n", *secLastParamPtr); + installDeviceNumber = *secLastParamPtr; + } else { + installDeviceNumber = *lastParamPtr; + } + + *devicePtr = malloc(6); + snprintf(*devicePtr, 6, "(hd%c)", installDeviceNumber); + dbgPrintf("installDeviceNumber: %c\n", installDeviceNumber); + fclose(grubConf); + free(line); + return 0; + } + + free(line); + fclose(grubConf); + return 1; +} + +int grubGetBootFromDeviceMap(const char * device, + char ** bootPtr) { + FILE * deviceMap; + char * line = NULL; + size_t res = 0, len = 0; + char * devicePtr; + char * bounds = NULL; + const char * path; + const static char default_path[] = "/boot/grub/device.map"; + + if (!device) return 1; + if (!bootPtr) return 1; + + if ((path = getenv("GRUBBY_GRUB_DEVICE_MAP")) == NULL) + path = default_path; + + dbgPrintf("opening grub device.map file from: %s\n", path); + deviceMap = fopen(path, "r"); + if (!deviceMap) + return 1; + + while ((res = getline(&line, &len, deviceMap)) != -1) { + if (!strncmp(line, "#", 1)) + continue; + + if (line[res - 1] == '\n') + line[res - 1] = '\0'; + else if (len > res) + line[res] = '\0'; + else { + line = realloc(line, res + 1); + line[res] = '\0'; + } + + devicePtr = line; + bounds = line + res; + + while ((isspace(*line) && ((devicePtr + 1) <= bounds))) + devicePtr++; + dbgPrintf("device: %s\n", devicePtr); + + if (!strncmp(devicePtr, device, strlen(device))) { + devicePtr += strlen(device); + while (isspace(*devicePtr) && ((devicePtr + 1) <= bounds)) + devicePtr++; + + *bootPtr = strdup(devicePtr); + break; + } + } + + free(line); + fclose(deviceMap); + return 0; +} + +int suseGrubConfGetBoot(const char * path, char ** bootPtr) { + char * grubDevice; + + if (suseGrubConfGetInstallDevice(path, &grubDevice)) + dbgPrintf("error looking for grub installation device\n"); + else + dbgPrintf("grubby installation device: %s\n", grubDevice); + + if (grubGetBootFromDeviceMap(grubDevice, bootPtr)) + dbgPrintf("error looking for grub boot device\n"); + else + dbgPrintf("grubby boot device: %s\n", *bootPtr); + + free(grubDevice); + return 0; +} + +int parseSuseGrubConf(int * lbaPtr, char ** bootPtr) { + /* + * This SuSE grub configuration file at this location is not your average + * grub configuration file, but instead the grub commands used to setup + * grub on that system. + */ + const char * path; + const static char default_path[] = "/etc/grub.conf"; + + if ((path = getenv("GRUBBY_SUSE_GRUB_CONF")) == NULL) + path = default_path; + + if (!isSuseGrubConf(path)) return 1; + + if (lbaPtr) { + *lbaPtr = 0; + if (suseGrubConfGetLba(path, lbaPtr)) + return 1; + } + + if (bootPtr) { + *bootPtr = NULL; + suseGrubConfGetBoot(path, bootPtr); + } + + return 0; +} + int parseSysconfigGrub(int * lbaPtr, char ** bootPtr) { FILE * in; char buf[1024]; @@ -2086,12 +2387,25 @@ } void dumpSysconfigGrub(void) { - char * boot; + char * boot = NULL; int lba; - if (!parseSysconfigGrub(&lba, &boot)) { - if (lba) printf("lba\n"); - if (boot) printf("boot=%s\n", boot); + if (isSuseSystem()) { + if (parseSuseGrubConf(&lba, &boot)) { + free(boot); + return; + } + } else { + if (parseSysconfigGrub(&lba, &boot)) { + free(boot); + return; + } + } + + if (lba) printf("lba\n"); + if (boot) { + printf("boot=%s\n", boot); + free(boot); } } @@ -2140,6 +2454,13 @@ { struct singleLine * newLine = lineDup(tmplLine); + if (isEfi && cfi == &grub2ConfigType) { + enum lineType_e old = newLine->type; + newLine->type = preferredLineType(newLine->type, cfi); + if (old != newLine->type) + newLine->elements[0].item = getKeyByType(newLine->type, cfi); + } + if (val) { /* override the inherited value with our own. * This is a little weak because it only applies to elements[1] @@ -2149,7 +2470,7 @@ insertElement(newLine, val, 1, cfi); /* but try to keep the rootspec from the template... sigh */ - if (tmplLine->type & (LT_HYPER|LT_KERNEL|LT_MBMODULE|LT_INITRD)) { + if (tmplLine->type & (LT_HYPER|LT_KERNEL|LT_MBMODULE|LT_INITRD|LT_KERNEL_EFI|LT_INITRD_EFI)) { char * rootspec = getRootSpecifier(tmplLine->elements[1].item); if (rootspec != NULL) { free(newLine->elements[1].item); @@ -2186,7 +2507,6 @@ /* NB: This function shouldn't allocate items on the heap, rather on the * stack since it calls addLineTmpl which will make copies. */ - if (type == LT_TITLE && cfi->titleBracketed) { /* we're doing a bracketed title (zipl) */ tmpl.type = type; @@ -2520,7 +2840,7 @@ firstElement = 2; } else { - line = getLineByType(LT_KERNEL|LT_MBMODULE, entry->lines); + line = getLineByType(LT_KERNEL|LT_MBMODULE|LT_KERNEL_EFI, entry->lines); if (!line) { /* no LT_KERNEL or LT_MBMODULE in this entry? */ continue; @@ -2685,10 +3005,10 @@ if (!image) return 0; for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) { - kernelLine = getLineByType(LT_KERNEL, entry->lines); + kernelLine = getLineByType(LT_KERNEL|LT_KERNEL_EFI, entry->lines); if (!kernelLine) continue; - line = getLineByType(LT_INITRD, entry->lines); + line = getLineByType(LT_INITRD|LT_INITRD_EFI, entry->lines); if (line) removeLine(entry, line); if (prefix) { @@ -2699,7 +3019,8 @@ endLine = getLineByType(LT_ENTRY_END, entry->lines); if (endLine) removeLine(entry, endLine); - line = addLine(entry, cfg->cfi, LT_INITRD, kernelLine->indent, initrd); + line = addLine(entry, cfg->cfi, preferredLineType(LT_INITRD, cfg->cfi), + kernelLine->indent, initrd); if (!line) return 1; if (endLine) { @@ -2905,9 +3226,16 @@ int fd; unsigned char bootSect[512]; char * boot; + int onSuse = isSuseSystem(); - if (parseSysconfigGrub(NULL, &boot)) - return 0; + + if (onSuse) { + if (parseSuseGrubConf(NULL, &boot)) + return 0; + } else { + if (parseSysconfigGrub(NULL, &boot)) + return 0; + } /* assume grub is not installed -- not an error condition */ if (!boot) @@ -2926,6 +3254,12 @@ } close(fd); + /* The more elaborate checks do not work on SuSE. The checks done + * seem to be reasonble (at least for now), so just return success + */ + if (onSuse) + return 2; + return checkDeviceBootloader(boot, bootSect); } @@ -2959,6 +3293,30 @@ return checkDeviceBootloader(boot, bootSect); } +int checkForYaboot(struct grubConfig * config) { + /* + * This is a simplistic check that we consider good enough for own puporses + * + * If we were to properly check if yaboot is *installed* we'd need to: + * 1) get the system boot device (LT_BOOT) + * 2) considering it's a raw filesystem, check if the yaboot binary matches + * the content on the boot device + * 3) if not, copy the binary to a temporary file and run "addnote" on it + * 4) check again if binary and boot device contents match + */ + if (!access("/etc/yaboot.conf", R_OK)) + return 2; + + return 1; +} + +int checkForElilo(struct grubConfig * config) { + if (!access("/etc/elilo.conf", R_OK)) + return 2; + + return 1; +} + static char * getRootSpecifier(char * str) { char * idx, * rootspec = NULL; @@ -3075,8 +3433,7 @@ while (*chptr && isspace(*chptr)) chptr++; if (*chptr == '#') continue; - if (tmplLine->type == LT_KERNEL && - tmplLine->numElements >= 2) { + if (iskernel(tmplLine->type) && tmplLine->numElements >= 2) { if (!template->multiboot && (needs & NEED_MB)) { /* it's not a multiboot template and this is the kernel * line. Try to be intelligent about inserting the @@ -3153,30 +3510,32 @@ /* template is multi but new is not, * insert the kernel in the first module slot */ - tmplLine->type = LT_KERNEL; + tmplLine->type = preferredLineType(LT_KERNEL, config->cfi); free(tmplLine->elements[0].item); tmplLine->elements[0].item = - strdup(getKeywordByType(LT_KERNEL, config->cfi)->key); + strdup(getKeywordByType(tmplLine->type, + config->cfi)->key); newLine = addLineTmpl(new, tmplLine, newLine, - newKernelPath + strlen(prefix), config->cfi); + newKernelPath + strlen(prefix), + config->cfi); needs &= ~NEED_KERNEL; } else if (needs & NEED_INITRD) { char *initrdVal; /* template is multi but new is not, * insert the initrd in the second module slot */ - tmplLine->type = LT_INITRD; + tmplLine->type = preferredLineType(LT_INITRD, config->cfi); free(tmplLine->elements[0].item); tmplLine->elements[0].item = - strdup(getKeywordByType(LT_INITRD, config->cfi)->key); + strdup(getKeywordByType(tmplLine->type, + config->cfi)->key); initrdVal = getInitrdVal(config, prefix, tmplLine, newKernelInitrd, extraInitrds, extraInitrdCount); newLine = addLineTmpl(new, tmplLine, newLine, initrdVal, config->cfi); free(initrdVal); needs &= ~NEED_INITRD; } - } else if (tmplLine->type == LT_INITRD && - tmplLine->numElements >= 2) { + } else if (isinitrd(tmplLine->type) && tmplLine->numElements >= 2) { if (needs & NEED_INITRD && new->multiboot && !template->multiboot && config->cfi->mbInitRdIsModule) { @@ -3230,7 +3589,8 @@ static const char *prefix = "'Loading "; if (tmplLine->numElements > 1 && strstr(tmplLine->elements[1].item, prefix) && - masterLine->next && masterLine->next->type == LT_KERNEL) { + masterLine->next && + iskernel(masterLine->next->type)) { char *newTitle = malloc(strlen(prefix) + strlen(newKernelTitle) + 2); @@ -3257,10 +3617,12 @@ */ switch (config->cfi->entryStart) { case LT_KERNEL: + case LT_KERNEL_EFI: if (new->multiboot && config->cfi->mbHyperFirst) { /* fall through to LT_HYPER */ } else { - newLine = addLine(new, config->cfi, LT_KERNEL, + newLine = addLine(new, config->cfi, + preferredLineType(LT_KERNEL, config->cfi), config->primaryIndent, newKernelPath + strlen(prefix)); needs &= ~NEED_KERNEL; @@ -3336,8 +3698,9 @@ if (needs & NEED_KERNEL) { newLine = addLine(new, config->cfi, (new->multiboot && getKeywordByType(LT_MBMODULE, - config->cfi)) ? - LT_MBMODULE : LT_KERNEL, + config->cfi)) + ? LT_MBMODULE + : preferredLineType(LT_KERNEL, config->cfi), config->secondaryIndent, newKernelPath + strlen(prefix)); needs &= ~NEED_KERNEL; @@ -3353,8 +3716,9 @@ initrdVal = getInitrdVal(config, prefix, NULL, newKernelInitrd, extraInitrds, extraInitrdCount); newLine = addLine(new, config->cfi, (new->multiboot && getKeywordByType(LT_MBMODULE, - config->cfi)) ? - LT_MBMODULE : LT_INITRD, + config->cfi)) + ? LT_MBMODULE + : preferredLineType(LT_INITRD, config->cfi), config->secondaryIndent, initrdVal); free(initrdVal); @@ -3429,6 +3793,7 @@ int displayDefault = 0; int displayDefaultIndex = 0; int displayDefaultTitle = 0; + int defaultIndex = -1; struct poptOption options[] = { { "add-kernel", 0, POPT_ARG_STRING, &newKernelPath, 0, _("add an entry for the specified kernel"), _("kernel-path") }, @@ -3446,9 +3811,9 @@ { "boot-filesystem", 0, POPT_ARG_STRING, &bootPrefix, 0, _("filestystem which contains /boot directory (for testing only)"), _("bootfs") }, -#if defined(__i386__) || defined(__x86_64__) +#if defined(__i386__) || defined(__x86_64__) || defined (__powerpc64__) || defined (__ia64__) { "bootloader-probe", 0, POPT_ARG_NONE, &bootloaderProbe, 0, - _("check if lilo is installed on lilo.conf boot sector") }, + _("check which bootloader is installed on boot sector") }, #endif { "config-file", 'c', POPT_ARG_STRING, &grubConfig, 0, _("path to grub config file to update (\"-\" for stdin)"), @@ -3469,6 +3834,8 @@ _("display the title of the default kernel") }, { "elilo", 0, POPT_ARG_NONE, &configureELilo, 0, _("configure elilo bootloader") }, + { "efi", 0, POPT_ARG_NONE, &isEfi, 0, + _("force grub2 stanzas to use efi") }, { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0, _("configure extlinux bootloader (from syslinux)") }, { "grub", 0, POPT_ARG_NONE, &configureGrub, 0, @@ -3501,6 +3868,9 @@ { "set-default", 0, POPT_ARG_STRING, &defaultKernel, 0, _("make the first entry referencing the specified kernel " "the default"), _("kernel-path") }, + { "set-default-index", 0, POPT_ARG_INT, &defaultIndex, 0, + _("make the given entry index the default entry"), + _("entry-index") }, { "silo", 0, POPT_ARG_NONE, &configureSilo, 0, _("configure silo bootloader") }, { "title", 0, POPT_ARG_STRING, &newKernelTitle, 0, @@ -3609,8 +3979,9 @@ } if (bootloaderProbe && (displayDefault || kernelInfo || newKernelVersion || - newKernelPath || removeKernelPath || makeDefault || - defaultKernel || displayDefaultIndex || displayDefaultTitle)) { + newKernelPath || removeKernelPath || makeDefault || + defaultKernel || displayDefaultIndex || displayDefaultTitle || + (defaultIndex >= 0))) { fprintf(stderr, _("grubby: --bootloader-probe may not be used with " "specified option")); return 1; @@ -3652,6 +4023,11 @@ makeDefault = 1; defaultKernel = NULL; } + else if (defaultKernel && (defaultIndex >= 0)) { + fprintf(stderr, _("grubby: --set-default and --set-default-index " + "may not be used together\n")); + return 1; + } if (grubConfig && !strcmp(grubConfig, "-") && !outputFile) { fprintf(stderr, _("grubby: output file must be specified if stdin " @@ -3660,8 +4036,9 @@ } if (!removeKernelPath && !newKernelPath && !displayDefault && !defaultKernel - && !kernelInfo && !bootloaderProbe && !updateKernelPath - && !removeMBKernel && !displayDefaultIndex && !displayDefaultTitle) { + && !kernelInfo && !bootloaderProbe && !updateKernelPath + && !removeMBKernel && !displayDefaultIndex && !displayDefaultTitle + && (defaultIndex == -1)) { fprintf(stderr, _("grubby: no action specified\n")); return 1; } @@ -3688,8 +4065,8 @@ } if (bootloaderProbe) { - int lrc = 0, grc = 0, gr2c = 0, erc = 0; - struct grubConfig * lconfig, * gconfig; + int lrc = 0, grc = 0, gr2c = 0, extrc = 0, yrc = 0, erc = 0; + struct grubConfig * lconfig, * gconfig, * yconfig, * econfig; const char *grub2config = grub2FindConfig(&grub2ConfigType); if (grub2config) { @@ -3717,20 +4094,43 @@ lrc = checkForLilo(lconfig); } + if (!access(eliloConfigType.defaultConfig, F_OK)) { + econfig = readConfig(eliloConfigType.defaultConfig, + &eliloConfigType); + if (!econfig) + erc = 1; + else + erc = checkForElilo(econfig); + } + if (!access(extlinuxConfigType.defaultConfig, F_OK)) { lconfig = readConfig(extlinuxConfigType.defaultConfig, &extlinuxConfigType); if (!lconfig) - erc = 1; + extrc = 1; else - erc = checkForExtLinux(lconfig); + extrc = checkForExtLinux(lconfig); } - if (lrc == 1 || grc == 1 || gr2c == 1) return 1; + + if (!access(yabootConfigType.defaultConfig, F_OK)) { + yconfig = readConfig(yabootConfigType.defaultConfig, + &yabootConfigType); + if (!yconfig) + yrc = 1; + else + yrc = checkForYaboot(yconfig); + } + + if (lrc == 1 || grc == 1 || gr2c == 1 || extrc == 1 || yrc == 1 || + erc == 1) + return 1; if (lrc == 2) printf("lilo\n"); if (gr2c == 2) printf("grub2\n"); if (grc == 2) printf("grub\n"); - if (erc == 2) printf("extlinux\n"); + if (extrc == 2) printf("extlinux\n"); + if (yrc == 2) printf("yaboot\n"); + if (erc == 2) printf("elilo\n"); return 0; } @@ -3748,7 +4148,7 @@ if (!entry) return 0; if (!suitableImage(entry, bootPrefix, 0, flags)) return 0; - line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines); + line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI, entry->lines); if (!line) return 0; rootspec = getRootSpecifier(line->elements[1].item); @@ -3797,7 +4197,7 @@ markRemovedImage(config, removeKernelPath, bootPrefix); markRemovedImage(config, removeMBKernel, bootPrefix); setDefaultImage(config, newKernelPath != NULL, defaultKernel, makeDefault, - bootPrefix, flags); + bootPrefix, flags, defaultIndex); setFallbackImage(config, newKernelPath != NULL); if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs, removeArgs, newMBKernelArgs, removeMBKernelArgs)) return 1;