--- trunk/grubby/grubby.c 2013/10/21 13:56:22 2250 +++ trunk/grubby/grubby.c 2014/07/16 10:41:38 2687 @@ -90,7 +90,10 @@ LT_SET_VARIABLE = 1 << 19, LT_KERNEL_EFI = 1 << 20, LT_INITRD_EFI = 1 << 21, - LT_UNKNOWN = 1 << 22, + LT_KERNEL_16 = 1 << 22, + LT_INITRD_16 = 1 << 23, + LT_DEVTREE = 1 << 24, + LT_UNKNOWN = 1 << 25, }; struct singleLine { @@ -119,6 +122,7 @@ #define NEED_ARGS (1 << 3) #define NEED_MB (1 << 4) #define NEED_END (1 << 5) +#define NEED_DEVTREE (1 << 6) #define MAIN_DEFAULT (1 << 0) #define DEFAULT_SAVED -2 @@ -136,16 +140,21 @@ typedef const char *(*findConfigFunc)(struct configFileInfo *); typedef const int (*writeLineFunc)(struct configFileInfo *, struct singleLine *line); +typedef char *(*getEnvFunc)(struct configFileInfo *, char *name); +typedef int (*setEnvFunc)(struct configFileInfo *, char *name, char *value); struct configFileInfo { char * defaultConfig; findConfigFunc findConfig; writeLineFunc writeLine; + getEnvFunc getEnv; + setEnvFunc setEnv; struct keywordTypes * keywords; int caseInsensitive; int defaultIsIndex; int defaultIsVariable; int defaultSupportSaved; + int defaultIsSaved; enum lineType_e entryStart; enum lineType_e entryEnd; int needsBootPrefix; @@ -157,6 +166,7 @@ int mbInitRdIsModule; int mbConcatArgs; int mbAllowExtraInitRds; + char *envFile; }; struct keywordTypes grubKeywords[] = { @@ -176,6 +186,8 @@ "/boot/grub/grub.conf", "/boot/grub/menu.lst", "/etc/grub.conf", + "/boot/grub2/grub.cfg", + "/boot/grub2-efi/grub.cfg", NULL }; static int i = -1; @@ -215,10 +227,13 @@ { "fallback", LT_FALLBACK, ' ' }, { "linux", LT_KERNEL, ' ' }, { "linuxefi", LT_KERNEL_EFI, ' ' }, + { "linux16", LT_KERNEL_16, ' ' }, { "initrd", LT_INITRD, ' ', ' ' }, { "initrdefi", LT_INITRD_EFI, ' ', ' ' }, + { "initrd16", LT_INITRD_16, ' ', ' ' }, { "module", LT_MBMODULE, ' ' }, { "kernel", LT_HYPER, ' ' }, + { "devicetree", LT_DEVTREE, ' ' }, { NULL, 0, 0 }, }; @@ -261,6 +276,105 @@ return configFiles[i]; } +/* kind of hacky. It'll give the first 1024 bytes, ish. */ +static char *grub2GetEnv(struct configFileInfo *info, char *name) +{ + static char buf[1025]; + char *s = NULL; + char *ret = NULL; + char *envFile = info->envFile ? info->envFile : "/boot/grub/grubenv"; + int rc = asprintf(&s, "grub-editenv %s list | grep '^%s='", envFile, name); + + if (rc < 0) + return NULL; + + FILE *f = popen(s, "r"); + if (!f) + goto out; + + memset(buf, '\0', sizeof (buf)); + ret = fgets(buf, 1024, f); + pclose(f); + + if (ret) { + ret += strlen(name) + 1; + ret[strlen(ret) - 1] = '\0'; + } + dbgPrintf("grub2GetEnv(%s): %s\n", name, ret); +out: + free(s); + return ret; +} + +static int sPopCount(const char *s, const char *c) +{ + int ret = 0; + if (!s) + return -1; + for (int i = 0; s[i] != '\0'; i++) + for (int j = 0; c[j] != '\0'; j++) + if (s[i] == c[j]) + ret++; + return ret; +} + +static char *shellEscape(const char *s) +{ + int l = strlen(s) + sPopCount(s, "'") * 2; + + char *ret = calloc(l+1, sizeof (*ret)); + if (!ret) + return NULL; + for (int i = 0, j = 0; s[i] != '\0'; i++, j++) { + if (s[i] == '\'') + ret[j++] = '\\'; + ret[j] = s[i]; + } + return ret; +} + +static void unquote(char *s) +{ + int l = strlen(s); + + if ((s[l-1] == '\'' && s[0] == '\'') || (s[l-1] == '"' && s[0] == '"')) { + memmove(s, s+1, l-2); + s[l-2] = '\0'; + } +} + +static int grub2SetEnv(struct configFileInfo *info, char *name, char *value) +{ + char *s = NULL; + int rc = 0; + char *envFile = info->envFile ? info->envFile : "/boot/grub/grubenv"; + + unquote(value); + value = shellEscape(value); + if (!value) + return -1; + + rc = asprintf(&s, "grub-editenv %s set '%s=%s'", envFile, name, value); + free(value); + if (rc <0) + return -1; + + dbgPrintf("grub2SetEnv(%s): %s\n", name, s); + rc = system(s); + free(s); + return rc; +} + +/* this is a gigantic hack to avoid clobbering grub2 variables... */ +static int is_special_grub2_variable(const char *name) +{ + if (!strcmp(name,"\"${next_entry}\"")) + return 1; + if (!strcmp(name,"\"${prev_saved_entry}\"")) + return 1; + return 0; +} + int sizeOfSingleLine(struct singleLine * line) { int count = 0; @@ -291,11 +405,11 @@ } static int iskernel(enum lineType_e type) { - return (type == LT_KERNEL || type == LT_KERNEL_EFI); + return (type == LT_KERNEL || type == LT_KERNEL_EFI || type == LT_KERNEL_16); } static int isinitrd(enum lineType_e type) { - return (type == LT_INITRD || type == LT_INITRD_EFI); + return (type == LT_INITRD || type == LT_INITRD_EFI || type == LT_INITRD_16); } char *grub2ExtractTitle(struct singleLine * line) { @@ -355,6 +469,8 @@ struct configFileInfo grub2ConfigType = { .findConfig = grub2FindConfig, + .getEnv = grub2GetEnv, + .setEnv = grub2SetEnv, .keywords = grub2Keywords, .defaultIsIndex = 1, .defaultSupportSaved = 1, @@ -534,6 +650,8 @@ struct singleEntry * findEntryByPath(struct grubConfig * cfg, const char * path, const char * prefix, int * index); +struct singleEntry * findEntryByTitle(struct grubConfig * cfg, char *title, + int * index); static int readFile(int fd, char ** bufPtr); static void lineInit(struct singleLine * line); struct singleLine * lineDup(struct singleLine * line); @@ -602,13 +720,31 @@ struct configFileInfo *cfi) { if (isEfi && cfi == &grub2ConfigType) { switch (type) { +#if defined(__aarch64__) + case LT_KERNEL: + return LT_KERNEL; + case LT_INITRD: + return LT_INITRD; +#else case LT_KERNEL: return LT_KERNEL_EFI; case LT_INITRD: return LT_INITRD_EFI; +#endif + default: + return type; + } +#if defined(__i386__) || defined(__x86_64__) + } else if (cfi == &grub2ConfigType) { + switch (type) { + case LT_KERNEL: + return LT_KERNEL_16; + case LT_INITRD: + return LT_INITRD_16; default: return type; } +#endif } return type; } @@ -691,10 +827,15 @@ /* extract the title from within brackets (for zipl) */ static char * extractTitle(struct singleLine * line) { /* bracketed title... let's extract it (leaks a byte) */ - char * title; - title = strdup(line->elements[0].item); - title++; - *(title + strlen(title) - 1) = '\0'; + char * title = NULL; + if (line->type == LT_TITLE) { + title = strdup(line->elements[0].item); + title++; + *(title + strlen(title) - 1) = '\0'; + } else if (line->type == LT_MENUENTRY) + title = strdup(line->elements[1].item); + else + return NULL; return title; } @@ -952,6 +1093,15 @@ return 0; } +static int isnumber(const char *s) +{ + int i; + for (i = 0; s[i] != '\0'; i++) + if (s[i] < '0' || s[i] > '9') + return 0; + return i; +} + static struct grubConfig * readConfig(const char * inName, struct configFileInfo * cfi) { int in; @@ -1036,7 +1186,8 @@ dbgPrintf("\n"); struct keywordTypes *kwType = getKeywordByType(LT_DEFAULT, cfi); if (kwType && line->numElements == 3 && - !strcmp(line->elements[1].item, kwType->key)) { + !strcmp(line->elements[1].item, kwType->key) && + !is_special_grub2_variable(line->elements[2].item)) { dbgPrintf("Line sets default config\n"); cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT; defaultLine = line; @@ -1241,7 +1392,22 @@ if (defaultLine->numElements > 2 && cfi->defaultSupportSaved && !strncmp(defaultLine->elements[2].item,"\"${saved_entry}\"", 16)) { - cfg->defaultImage = DEFAULT_SAVED_GRUB2; + cfg->cfi->defaultIsSaved = 1; + cfg->defaultImage = DEFAULT_SAVED_GRUB2; + if (cfg->cfi->getEnv) { + char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry"); + if (defTitle) { + int index = 0; + if (isnumber(defTitle)) { + index = atoi(defTitle); + entry = findEntryByIndex(cfg, index); + } else { + entry = findEntryByTitle(cfg, defTitle, &index); + } + if (entry) + cfg->defaultImage = index; + } + } } else if (cfi->defaultIsVariable) { char *value = defaultLine->elements[2].item; while (*value && (*value == '"' || *value == '\'' || @@ -1282,6 +1448,19 @@ cfg->defaultImage = -1; } } + } else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) { + char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry"); + if (defTitle) { + int index = 0; + if (isnumber(defTitle)) { + index = atoi(defTitle); + entry = findEntryByIndex(cfg, index); + } else { + entry = findEntryByTitle(cfg, defTitle, &index); + } + if (entry) + cfg->defaultImage = index; + } } else { cfg->defaultImage = 0; } @@ -1299,9 +1478,21 @@ if (cfg->defaultImage == DEFAULT_SAVED) fprintf(out, "%sdefault%ssaved\n", indent, separator); - else if (cfg->defaultImage == DEFAULT_SAVED_GRUB2) + else if (cfg->cfi->defaultIsSaved) { fprintf(out, "%sset default=\"${saved_entry}\"\n", indent); - else if (cfg->defaultImage > -1) { + if (cfg->defaultImage >= 0 && cfg->cfi->setEnv) { + char *title; + entry = findEntryByIndex(cfg, cfg->defaultImage); + line = getLineByType(LT_MENUENTRY, entry->lines); + if (!line) + line = getLineByType(LT_TITLE, entry->lines); + if (line) { + title = extractTitle(line); + if (title) + cfg->cfi->setEnv(cfg->cfi, "saved_entry", title); + } + } + } else if (cfg->defaultImage > -1) { if (cfg->cfi->defaultIsIndex) { if (cfg->cfi->defaultIsVariable) { fprintf(out, "%sset default=\"%d\"\n", indent, @@ -1404,7 +1595,8 @@ while (line) { if (line->type == LT_SET_VARIABLE && defaultKw && line->numElements == 3 && - !strcmp(line->elements[1].item, defaultKw->key)) { + !strcmp(line->elements[1].item, defaultKw->key) && + !is_special_grub2_variable(line->elements[2].item)) { writeDefault(out, line->indent, line->elements[0].indent, cfg); needs &= ~MAIN_DEFAULT; } else if (line->type == LT_DEFAULT) { @@ -1640,7 +1832,7 @@ return 0; } - line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI, entry->lines); + line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines); if (!line) { notSuitablePrintf(entry, 0, "no line found\n"); return 0; @@ -1774,7 +1966,7 @@ entry = findEntryByIndex(config, indexVars[i]); if (!entry) return NULL; - line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI, entry->lines); + line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines); if (!line) return NULL; if (index) *index = indexVars[i]; @@ -1825,9 +2017,9 @@ for (line = entry->lines; line; line = line->next) { enum lineType_e ct = checkType; if (entry->multiboot && checkType == LT_KERNEL) - ct = LT_KERNEL|LT_KERNEL_EFI|LT_MBMODULE|LT_HYPER; + ct = LT_KERNEL|LT_KERNEL_EFI|LT_MBMODULE|LT_HYPER|LT_KERNEL_16; else if (checkType & LT_KERNEL) - ct = checkType | LT_KERNEL_EFI; + ct = checkType | LT_KERNEL_EFI | LT_KERNEL_16; line = getLineByType(ct, line); if (!line) break; /* not found in this entry */ @@ -1849,7 +2041,7 @@ * non-Linux boot entries (could find netbsd etc, though, which is * unfortunate) */ - if (line && getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI, entry->lines)) + if (line && getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines)) break; /* found 'im! */ } @@ -1859,6 +2051,36 @@ return entry; } +struct singleEntry * findEntryByTitle(struct grubConfig * cfg, char *title, + int * index) { + struct singleEntry * entry; + struct singleLine * line; + int i; + char * newtitle; + + for (i = 0, entry = cfg->entries; entry; entry = entry->next, i++) { + if (index && i < *index) + continue; + line = getLineByType(LT_TITLE, entry->lines); + if (!line) + line = getLineByType(LT_MENUENTRY, entry->lines); + if (!line) + continue; + newtitle = grub2ExtractTitle(line); + if (!newtitle) + continue; + if (!strcmp(title, newtitle)) + break; + } + + if (!entry) + return NULL; + + if (index) + *index = i; + return entry; +} + struct singleEntry * findEntryByIndex(struct grubConfig * cfg, int index) { struct singleEntry * entry; @@ -1881,7 +2103,22 @@ struct singleEntry * entry, * entry2; int index; - if (cfg->defaultImage > -1) { + if (cfg->cfi->defaultIsSaved) { + if (cfg->cfi->getEnv) { + char *defTitle = cfg->cfi->getEnv(cfg->cfi, "saved_entry"); + if (defTitle) { + int index = 0; + if (isnumber(defTitle)) { + index = atoi(defTitle); + entry = findEntryByIndex(cfg, index); + } else { + entry = findEntryByTitle(cfg, defTitle, &index); + } + if (entry) + cfg->defaultImage = index; + } + } + } else if (cfg->defaultImage > -1) { entry = findEntryByIndex(cfg, cfg->defaultImage); if (entry && suitableImage(entry, prefix, skipRemoved, flags)) { if (indexPtr) *indexPtr = cfg->defaultImage; @@ -2038,7 +2275,7 @@ printf("index=%d\n", index); - line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI, entry->lines); + line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines); if (!line) { printf("non linux entry\n"); return; @@ -2103,7 +2340,7 @@ printf("root=%s\n", s); } - line = getLineByType(LT_INITRD|LT_INITRD_EFI, entry->lines); + line = getLineByType(LT_INITRD|LT_INITRD_EFI|LT_INITRD_16, entry->lines); if (line && line->numElements >= 2) { if (!strncmp(prefix, line->elements[1].item, strlen(prefix))) @@ -2520,7 +2757,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|LT_KERNEL_EFI|LT_INITRD_EFI)) { + if (tmplLine->type & (LT_HYPER|LT_KERNEL|LT_MBMODULE|LT_INITRD|LT_KERNEL_EFI|LT_INITRD_EFI|LT_KERNEL_16|LT_INITRD_16)) { char * rootspec = getRootSpecifier(tmplLine->elements[1].item); if (rootspec != NULL) { free(newLine->elements[1].item); @@ -2890,7 +3127,7 @@ firstElement = 2; } else { - line = getLineByType(LT_KERNEL|LT_MBMODULE|LT_KERNEL_EFI, entry->lines); + line = getLineByType(LT_KERNEL|LT_MBMODULE|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines); if (!line) { /* no LT_KERNEL or LT_MBMODULE in this entry? */ continue; @@ -3046,6 +3283,42 @@ return rc; } +int addMBInitrd(struct grubConfig * cfg, const char *newMBKernel, + const char * image, const char * prefix, const char * initrd) { + struct singleEntry * entry; + struct singleLine * line, * kernelLine, *endLine = NULL; + int index = 0; + + if (!image) return 0; + + for (; (entry = findEntryByPath(cfg, newMBKernel, prefix, &index)); index++) { + kernelLine = getLineByType(LT_MBMODULE, entry->lines); + if (!kernelLine) continue; + + if (prefix) { + int prefixLen = strlen(prefix); + if (!strncmp(initrd, prefix, prefixLen)) + initrd += prefixLen; + } + endLine = getLineByType(LT_ENTRY_END, entry->lines); + if (endLine) + removeLine(entry, endLine); + line = addLine(entry, cfg->cfi, preferredLineType(LT_MBMODULE,cfg->cfi), + kernelLine->indent, initrd); + if (!line) + return 1; + if (endLine) { + line = addLine(entry, cfg->cfi, LT_ENTRY_END, "", NULL); + if (!line) + return 1; + } + + break; + } + + return 0; +} + int updateInitrd(struct grubConfig * cfg, const char * image, const char * prefix, const char * initrd) { struct singleEntry * entry; @@ -3055,10 +3328,10 @@ if (!image) return 0; for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) { - kernelLine = getLineByType(LT_KERNEL|LT_KERNEL_EFI, entry->lines); + kernelLine = getLineByType(LT_KERNEL|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines); if (!kernelLine) continue; - line = getLineByType(LT_INITRD|LT_INITRD_EFI, entry->lines); + line = getLineByType(LT_INITRD|LT_INITRD_EFI|LT_INITRD_16, entry->lines); if (line) removeLine(entry, line); if (prefix) { @@ -3069,8 +3342,21 @@ endLine = getLineByType(LT_ENTRY_END, entry->lines); if (endLine) removeLine(entry, endLine); - line = addLine(entry, cfg->cfi, preferredLineType(LT_INITRD, cfg->cfi), - kernelLine->indent, initrd); + enum lineType_e lt; + switch(kernelLine->type) { + case LT_KERNEL: + lt = LT_INITRD; + break; + case LT_KERNEL_EFI: + lt = LT_INITRD_EFI; + break; + case LT_KERNEL_16: + lt = LT_INITRD_16; + break; + default: + lt = preferredLineType(LT_INITRD, cfg->cfi); + } + line = addLine(entry, cfg->cfi, lt, kernelLine->indent, initrd); if (!line) return 1; if (endLine) { @@ -3429,7 +3715,8 @@ const char * newKernelPath, const char * newKernelTitle, const char * newKernelArgs, const char * newKernelInitrd, const char ** extraInitrds, int extraInitrdCount, - const char * newMBKernel, const char * newMBKernelArgs) { + const char * newMBKernel, const char * newMBKernelArgs, + const char * newDevTreePath) { struct singleEntry * new; struct singleLine * newLine = NULL, * tmplLine = NULL, * masterLine = NULL; int needs; @@ -3470,6 +3757,8 @@ needs |= NEED_MB; new->multiboot = 1; } + if (newDevTreePath && getKeywordByType(LT_DEVTREE, config->cfi)) + needs |= NEED_DEVTREE; if (template) { for (masterLine = template->lines; @@ -3655,6 +3944,21 @@ newLine = addLineTmpl(new, tmplLine, newLine, NULL, config->cfi); } + } else if (tmplLine->type == LT_DEVTREE && + tmplLine->numElements == 2 && newDevTreePath) { + newLine = addLineTmpl(new, tmplLine, newLine, + newDevTreePath + strlen(prefix), + config->cfi); + needs &= ~NEED_DEVTREE; + } else if (tmplLine->type == LT_ENTRY_END && needs & NEED_DEVTREE) { + const char *ndtp = newDevTreePath; + if (!strncmp(newDevTreePath, prefix, strlen(prefix))) + ndtp += strlen(prefix); + newLine = addLine(new, config->cfi, LT_DEVTREE, + config->secondaryIndent, + ndtp); + needs &= ~NEED_DEVTREE; + newLine = addLineTmpl(new, tmplLine, newLine, NULL, config->cfi); } else { /* pass through other lines from the template */ newLine = addLineTmpl(new, tmplLine, newLine, NULL, config->cfi); @@ -3668,6 +3972,7 @@ switch (config->cfi->entryStart) { case LT_KERNEL: case LT_KERNEL_EFI: + case LT_KERNEL_16: if (new->multiboot && config->cfi->mbHyperFirst) { /* fall through to LT_HYPER */ } else { @@ -3774,12 +4079,19 @@ free(initrdVal); needs &= ~NEED_INITRD; } + if (needs & NEED_DEVTREE) { + newLine = addLine(new, config->cfi, LT_DEVTREE, + config->secondaryIndent, + newDevTreePath); + needs &= ~NEED_DEVTREE; + } + + /* NEEDS_END must be last on bootloaders that need it... */ if (needs & NEED_END) { newLine = addLine(new, config->cfi, LT_ENTRY_END, config->secondaryIndent, NULL); needs &= ~NEED_END; } - if (needs) { printf(_("grubby: needs=%d, aborting\n"), needs); abort(); @@ -3825,7 +4137,7 @@ char * newKernelArgs = NULL; char * newKernelInitrd = NULL; char * newKernelTitle = NULL; - char * newKernelVersion = NULL; + char * newDevTreePath = NULL; char * newMBKernel = NULL; char * newMBKernelArgs = NULL; char * removeMBKernelArgs = NULL; @@ -3835,6 +4147,7 @@ char * removeArgs = NULL; char * kernelInfo = NULL; char * extraInitrds[MAX_EXTRA_INITRDS] = { NULL }; + char * envPath = NULL; const char * chptr = NULL; struct configFileInfo * cfi = NULL; struct grubConfig * config; @@ -3882,10 +4195,15 @@ _("display the index of the default kernel") }, { "default-title", 0, 0, &displayDefaultTitle, 0, _("display the title of the default kernel") }, + { "devtree", 0, POPT_ARG_STRING, &newDevTreePath, 0, + _("device tree file for new stanza"), _("dtb-path") }, { "elilo", 0, POPT_ARG_NONE, &configureELilo, 0, _("configure elilo bootloader") }, { "efi", 0, POPT_ARG_NONE, &isEfi, 0, _("force grub2 stanzas to use efi") }, + { "env", 0, POPT_ARG_STRING, &envPath, 0, + _("path for environment data"), + _("path") }, { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0, _("configure extlinux bootloader (from syslinux)") }, { "grub", 0, POPT_ARG_NONE, &configureGrub, 0, @@ -3999,6 +4317,8 @@ return 1; } else if (configureGrub2) { cfi = &grub2ConfigType; + if (envPath) + cfi->envFile = envPath; } else if (configureLilo) { cfi = &liloConfigType; } else if (configureGrub) { @@ -4042,7 +4362,7 @@ grubConfig = cfi->defaultConfig; } - if (bootloaderProbe && (displayDefault || kernelInfo || newKernelVersion || + if (bootloaderProbe && (displayDefault || kernelInfo || newKernelPath || removeKernelPath || makeDefault || defaultKernel || displayDefaultIndex || displayDefaultTitle || (defaultIndex >= 0))) { @@ -4051,7 +4371,7 @@ return 1; } - if ((displayDefault || kernelInfo) && (newKernelVersion || newKernelPath || + if ((displayDefault || kernelInfo) && (newKernelPath || removeKernelPath)) { fprintf(stderr, _("grubby: --default-kernel and --info may not " "be used when adding or removing kernels\n")); @@ -4213,11 +4533,14 @@ char * rootspec; if (config->defaultImage == -1) return 0; + if (config->defaultImage == DEFAULT_SAVED_GRUB2 && + cfi->defaultIsSaved) + config->defaultImage = 0; entry = findEntryByIndex(config, config->defaultImage); if (!entry) return 0; if (!suitableImage(entry, bootPrefix, 0, flags)) return 0; - line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI, entry->lines); + line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines); if (!line) return 0; rootspec = getRootSpecifier(line->elements[1].item); @@ -4231,6 +4554,9 @@ struct singleEntry * entry; if (config->defaultImage == -1) return 0; + if (config->defaultImage == DEFAULT_SAVED_GRUB2 && + cfi->defaultIsSaved) + config->defaultImage = 0; entry = findEntryByIndex(config, config->defaultImage); if (!entry) return 0; @@ -4253,6 +4579,9 @@ } else if (displayDefaultIndex) { if (config->defaultImage == -1) return 0; + if (config->defaultImage == DEFAULT_SAVED_GRUB2 && + cfi->defaultIsSaved) + config->defaultImage = 0; printf("%i\n", config->defaultImage); return 0; @@ -4272,13 +4601,20 @@ if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs, removeArgs, newMBKernelArgs, removeMBKernelArgs)) return 1; if (updateKernelPath && newKernelInitrd) { - if (updateInitrd(config, updateKernelPath, bootPrefix, - newKernelInitrd)) return 1; + if (newMBKernel) { + if (addMBInitrd(config, newMBKernel, updateKernelPath, + bootPrefix, newKernelInitrd)) + return 1; + } else { + if (updateInitrd(config, updateKernelPath, bootPrefix, + newKernelInitrd)) + return 1; + } } if (addNewKernel(config, template, bootPrefix, newKernelPath, newKernelTitle, newKernelArgs, newKernelInitrd, (const char **)extraInitrds, extraInitrdCount, - newMBKernel, newMBKernelArgs)) return 1; + newMBKernel, newMBKernelArgs, newDevTreePath)) return 1; if (numEntries(config) == 0) {