Magellan Linux

Diff of /tags/grubby-8_40_20170627/grubby.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1931 by niro, Mon Oct 1 12:06:26 2012 UTC revision 2972 by niro, Thu Jun 30 10:17:00 2016 UTC
# Line 36  Line 36 
36  #include <signal.h>  #include <signal.h>
37  #include <blkid/blkid.h>  #include <blkid/blkid.h>
38    
39    #include "log.h"
40    
41  #ifndef DEBUG  #ifndef DEBUG
42  #define DEBUG 0  #define DEBUG 0
43  #endif  #endif
# Line 56  int debug = 0; /* Currently just for tem Line 58  int debug = 0; /* Currently just for tem
58  #define NOOP_OPCODE 0x90  #define NOOP_OPCODE 0x90
59  #define JMP_SHORT_OPCODE 0xeb  #define JMP_SHORT_OPCODE 0xeb
60    
61    int isEfi = 0;
62    
63    #if defined(__aarch64__)
64    #define isEfiOnly 1
65    #else
66    #define isEfiOnly 0
67    #endif
68    
69    char *saved_command_line = NULL;
70    
71  /* comments get lumped in with indention */  /* comments get lumped in with indention */
72  struct lineElement {  struct lineElement {
73      char * item;      char * item;
# Line 82  enum lineType_e { Line 94  enum lineType_e {
94      LT_MENUENTRY    = 1 << 17,      LT_MENUENTRY    = 1 << 17,
95      LT_ENTRY_END    = 1 << 18,      LT_ENTRY_END    = 1 << 18,
96      LT_SET_VARIABLE = 1 << 19,      LT_SET_VARIABLE = 1 << 19,
97      LT_UNKNOWN      = 1 << 20,      LT_KERNEL_EFI   = 1 << 20,
98        LT_INITRD_EFI   = 1 << 21,
99        LT_KERNEL_16    = 1 << 22,
100        LT_INITRD_16    = 1 << 23,
101        LT_DEVTREE      = 1 << 24,
102        LT_UNKNOWN      = 1 << 25,
103  };  };
104    
105  struct singleLine {  struct singleLine {
# Line 111  struct singleEntry { Line 128  struct singleEntry {
128  #define NEED_ARGS    (1 << 3)  #define NEED_ARGS    (1 << 3)
129  #define NEED_MB      (1 << 4)  #define NEED_MB      (1 << 4)
130  #define NEED_END     (1 << 5)  #define NEED_END     (1 << 5)
131    #define NEED_DEVTREE (1 << 6)
132    
133  #define MAIN_DEFAULT    (1 << 0)  #define MAIN_DEFAULT    (1 << 0)
134  #define DEFAULT_SAVED       -2  #define DEFAULT_SAVED       -2
# Line 128  struct configFileInfo; Line 146  struct configFileInfo;
146  typedef const char *(*findConfigFunc)(struct configFileInfo *);  typedef const char *(*findConfigFunc)(struct configFileInfo *);
147  typedef const int (*writeLineFunc)(struct configFileInfo *,  typedef const int (*writeLineFunc)(struct configFileInfo *,
148   struct singleLine *line);   struct singleLine *line);
149    typedef char *(*getEnvFunc)(struct configFileInfo *, char *name);
150    typedef int (*setEnvFunc)(struct configFileInfo *, char *name, char *value);
151    
152  struct configFileInfo {  struct configFileInfo {
153      char * defaultConfig;      char * defaultConfig;
154      findConfigFunc findConfig;      findConfigFunc findConfig;
155      writeLineFunc writeLine;      writeLineFunc writeLine;
156        getEnvFunc getEnv;
157        setEnvFunc setEnv;
158      struct keywordTypes * keywords;      struct keywordTypes * keywords;
159        int caseInsensitive;
160      int defaultIsIndex;      int defaultIsIndex;
161      int defaultIsVariable;      int defaultIsVariable;
162      int defaultSupportSaved;      int defaultSupportSaved;
163        int defaultIsSaved;
164        int defaultIsUnquoted;
165      enum lineType_e entryStart;      enum lineType_e entryStart;
166      enum lineType_e entryEnd;      enum lineType_e entryEnd;
167      int needsBootPrefix;      int needsBootPrefix;
# Line 148  struct configFileInfo { Line 173  struct configFileInfo {
173      int mbInitRdIsModule;      int mbInitRdIsModule;
174      int mbConcatArgs;      int mbConcatArgs;
175      int mbAllowExtraInitRds;      int mbAllowExtraInitRds;
176        char *envFile;
177  };  };
178    
179  struct keywordTypes grubKeywords[] = {  struct keywordTypes grubKeywords[] = {
# Line 167  const char *grubFindConfig(struct config Line 193  const char *grubFindConfig(struct config
193   "/boot/grub/grub.conf",   "/boot/grub/grub.conf",
194   "/boot/grub/menu.lst",   "/boot/grub/menu.lst",
195   "/etc/grub.conf",   "/etc/grub.conf",
196     "/boot/grub2/grub.cfg",
197     "/boot/grub2-efi/grub.cfg",
198   NULL   NULL
199      };      };
200      static int i = -1;      static int i = -1;
# Line 205  struct keywordTypes grub2Keywords[] = { Line 233  struct keywordTypes grub2Keywords[] = {
233      { "default",    LT_DEFAULT,     ' ' },      { "default",    LT_DEFAULT,     ' ' },
234      { "fallback",   LT_FALLBACK,    ' ' },      { "fallback",   LT_FALLBACK,    ' ' },
235      { "linux",      LT_KERNEL,      ' ' },      { "linux",      LT_KERNEL,      ' ' },
236      { "linuxefi",   LT_KERNEL,      ' ' },      { "linuxefi",   LT_KERNEL_EFI,  ' ' },
237        { "linux16",    LT_KERNEL_16,   ' ' },
238      { "initrd",     LT_INITRD,      ' ', ' ' },      { "initrd",     LT_INITRD,      ' ', ' ' },
239      { "initrdefi",  LT_INITRD,      ' ', ' ' },      { "initrdefi",  LT_INITRD_EFI,  ' ', ' ' },
240        { "initrd16",   LT_INITRD_16,   ' ', ' ' },
241      { "module",     LT_MBMODULE,    ' ' },      { "module",     LT_MBMODULE,    ' ' },
242      { "kernel",     LT_HYPER,       ' ' },      { "kernel",     LT_HYPER,       ' ' },
243        { "devicetree", LT_DEVTREE,  ' ' },
244      { NULL, 0, 0 },      { NULL, 0, 0 },
245  };  };
246    
# Line 221  const char *grub2FindConfig(struct confi Line 252  const char *grub2FindConfig(struct confi
252      };      };
253      static int i = -1;      static int i = -1;
254      static const char *grub_cfg = "/boot/grub/grub.cfg";      static const char *grub_cfg = "/boot/grub/grub.cfg";
255        int rc = -1;
256    
257      if (i == -1) {      if (i == -1) {
258   for (i = 0; configFiles[i] != NULL; i++) {   for (i = 0; configFiles[i] != NULL; i++) {
259      dbgPrintf("Checking \"%s\": ", configFiles[i]);      dbgPrintf("Checking \"%s\": ", configFiles[i]);
260      if (!access(configFiles[i], R_OK)) {      if ((rc = access(configFiles[i], R_OK))) {
261     if (errno == EACCES) {
262        printf("Unable to access bootloader configuration file "
263           "\"%s\": %m\n", configFiles[i]);
264        exit(1);
265     }
266     continue;
267        } else {
268   dbgPrintf("found\n");   dbgPrintf("found\n");
269   return configFiles[i];   return configFiles[i];
270      }      }
# Line 244  const char *grub2FindConfig(struct confi Line 283  const char *grub2FindConfig(struct confi
283      return configFiles[i];      return configFiles[i];
284  }  }
285    
286    /* kind of hacky.  It'll give the first 1024 bytes, ish. */
287    static char *grub2GetEnv(struct configFileInfo *info, char *name)
288    {
289        static char buf[1025];
290        char *s = NULL;
291        char *ret = NULL;
292        char *envFile = info->envFile ? info->envFile : "/boot/grub/grubenv";
293        int rc = asprintf(&s, "grub-editenv %s list | grep '^%s='", envFile, name);
294    
295        if (rc < 0)
296     return NULL;
297    
298        FILE *f = popen(s, "r");
299        if (!f)
300     goto out;
301    
302        memset(buf, '\0', sizeof (buf));
303        ret = fgets(buf, 1024, f);
304        pclose(f);
305    
306        if (ret) {
307     ret += strlen(name) + 1;
308     ret[strlen(ret) - 1] = '\0';
309        }
310        dbgPrintf("grub2GetEnv(%s): %s\n", name, ret);
311    out:
312        free(s);
313        return ret;
314    }
315    
316    static int sPopCount(const char *s, const char *c)
317    {
318        int ret = 0;
319        if (!s)
320     return -1;
321        for (int i = 0; s[i] != '\0'; i++)
322     for (int j = 0; c[j] != '\0'; j++)
323        if (s[i] == c[j])
324     ret++;
325        return ret;
326    }
327    
328    static char *shellEscape(const char *s)
329    {
330        int l = strlen(s) + sPopCount(s, "'") * 2;
331    
332        char *ret = calloc(l+1, sizeof (*ret));
333        if (!ret)
334     return NULL;
335        for (int i = 0, j = 0; s[i] != '\0'; i++, j++) {
336     if (s[i] == '\'')
337        ret[j++] = '\\';
338     ret[j] = s[i];
339        }
340        return ret;
341    }
342    
343    static void unquote(char *s)
344    {
345        int l = strlen(s);
346    
347        if ((s[l-1] == '\'' && s[0] == '\'') || (s[l-1] == '"' && s[0] == '"')) {
348     memmove(s, s+1, l-2);
349     s[l-2] = '\0';
350        }
351    }
352    
353    static int grub2SetEnv(struct configFileInfo *info, char *name, char *value)
354    {
355        char *s = NULL;
356        int rc = 0;
357        char *envFile = info->envFile ? info->envFile : "/boot/grub/grubenv";
358    
359        unquote(value);
360        value = shellEscape(value);
361        if (!value)
362        return -1;
363    
364        rc = asprintf(&s, "grub-editenv %s set '%s=%s'", envFile, name, value);
365        free(value);
366        if (rc <0)
367     return -1;
368    
369        dbgPrintf("grub2SetEnv(%s): %s\n", name, s);
370        rc = system(s);
371        free(s);
372        return rc;
373    }
374    
375    /* this is a gigantic hack to avoid clobbering grub2 variables... */
376    static int is_special_grub2_variable(const char *name)
377    {
378        if (!strcmp(name,"\"${next_entry}\""))
379     return 1;
380        if (!strcmp(name,"\"${prev_saved_entry}\""))
381     return 1;
382        return 0;
383    }
384    
385  int sizeOfSingleLine(struct singleLine * line) {  int sizeOfSingleLine(struct singleLine * line) {
386    int count = 0;    int count = 0;
387    
# Line 273  static int isquote(char q) Line 411  static int isquote(char q)
411      return 0;      return 0;
412  }  }
413    
414    static int iskernel(enum lineType_e type) {
415        return (type == LT_KERNEL || type == LT_KERNEL_EFI || type == LT_KERNEL_16);
416    }
417    
418    static int isinitrd(enum lineType_e type) {
419        return (type == LT_INITRD || type == LT_INITRD_EFI || type == LT_INITRD_16);
420    }
421    
422  char *grub2ExtractTitle(struct singleLine * line) {  char *grub2ExtractTitle(struct singleLine * line) {
423      char * current;      char * current;
424      char * current_indent;      char * current_indent;
# Line 330  char *grub2ExtractTitle(struct singleLin Line 476  char *grub2ExtractTitle(struct singleLin
476    
477  struct configFileInfo grub2ConfigType = {  struct configFileInfo grub2ConfigType = {
478      .findConfig = grub2FindConfig,      .findConfig = grub2FindConfig,
479        .getEnv = grub2GetEnv,
480        .setEnv = grub2SetEnv,
481      .keywords = grub2Keywords,      .keywords = grub2Keywords,
482      .defaultIsIndex = 1,      .defaultIsIndex = 1,
483      .defaultSupportSaved = 1,      .defaultSupportSaved = 1,
# Line 434  struct keywordTypes extlinuxKeywords[] = Line 582  struct keywordTypes extlinuxKeywords[] =
582      { "initrd",    LT_INITRD,      ' ', ',' },      { "initrd",    LT_INITRD,      ' ', ',' },
583      { "append",    LT_KERNELARGS,  ' ' },      { "append",    LT_KERNELARGS,  ' ' },
584      { "prompt",     LT_UNKNOWN,     ' ' },      { "prompt",     LT_UNKNOWN,     ' ' },
585        { "fdt",        LT_DEVTREE,     ' ' },
586        { "fdtdir",     LT_DEVTREE,     ' ' },
587      { NULL,    0, 0 },      { NULL,    0, 0 },
588  };  };
589  int useextlinuxmenu;  int useextlinuxmenu;
# Line 484  struct configFileInfo ziplConfigType = { Line 634  struct configFileInfo ziplConfigType = {
634  struct configFileInfo extlinuxConfigType = {  struct configFileInfo extlinuxConfigType = {
635      .defaultConfig = "/boot/extlinux/extlinux.conf",      .defaultConfig = "/boot/extlinux/extlinux.conf",
636      .keywords = extlinuxKeywords,      .keywords = extlinuxKeywords,
637        .caseInsensitive = 1,
638      .entryStart = LT_TITLE,      .entryStart = LT_TITLE,
639      .needsBootPrefix = 1,      .needsBootPrefix = 1,
640      .maxTitleLength = 255,      .maxTitleLength = 255,
641      .mbAllowExtraInitRds = 1,      .mbAllowExtraInitRds = 1,
642        .defaultIsUnquoted = 1,
643  };  };
644    
645  struct grubConfig {  struct grubConfig {
# Line 508  struct singleEntry * findEntryByIndex(st Line 660  struct singleEntry * findEntryByIndex(st
660  struct singleEntry * findEntryByPath(struct grubConfig * cfg,  struct singleEntry * findEntryByPath(struct grubConfig * cfg,
661       const char * path, const char * prefix,       const char * path, const char * prefix,
662       int * index);       int * index);
663    struct singleEntry * findEntryByTitle(struct grubConfig * cfg, char *title,
664          int * index);
665  static int readFile(int fd, char ** bufPtr);  static int readFile(int fd, char ** bufPtr);
666  static void lineInit(struct singleLine * line);  static void lineInit(struct singleLine * line);
667  struct singleLine * lineDup(struct singleLine * line);  struct singleLine * lineDup(struct singleLine * line);
# Line 572  static char * sdupprintf(const char *for Line 726  static char * sdupprintf(const char *for
726      return buf;      return buf;
727  }  }
728    
729    static enum lineType_e preferredLineType(enum lineType_e type,
730     struct configFileInfo *cfi) {
731        if (isEfi && cfi == &grub2ConfigType) {
732     switch (type) {
733     case LT_KERNEL:
734        return isEfiOnly ? LT_KERNEL : LT_KERNEL_EFI;
735     case LT_INITRD:
736        return isEfiOnly ? LT_INITRD : LT_INITRD_EFI;
737     default:
738        return type;
739     }
740    #if defined(__i386__) || defined(__x86_64__)
741        } else if (cfi == &grub2ConfigType) {
742     switch (type) {
743     case LT_KERNEL:
744        return LT_KERNEL_16;
745     case LT_INITRD:
746        return LT_INITRD_16;
747     default:
748        return type;
749     }
750    #endif
751        }
752        return type;
753    }
754    
755  static struct keywordTypes * getKeywordByType(enum lineType_e type,  static struct keywordTypes * getKeywordByType(enum lineType_e type,
756        struct configFileInfo * cfi) {        struct configFileInfo * cfi) {
757      for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) {      for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) {
# Line 605  static char * getuuidbydev(char *device) Line 785  static char * getuuidbydev(char *device)
785  static enum lineType_e getTypeByKeyword(char * keyword,  static enum lineType_e getTypeByKeyword(char * keyword,
786   struct configFileInfo * cfi) {   struct configFileInfo * cfi) {
787      for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) {      for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) {
788   if (!strcmp(keyword, kw->key))   if (cfi->caseInsensitive) {
789      return kw->type;      if (!strcasecmp(keyword, kw->key))
790                    return kw->type;
791     } else {
792        if (!strcmp(keyword, kw->key))
793            return kw->type;
794     }
795      }      }
796      return LT_UNKNOWN;      return LT_UNKNOWN;
797  }  }
# Line 645  static int isEntryStart(struct singleLin Line 830  static int isEntryStart(struct singleLin
830  /* extract the title from within brackets (for zipl) */  /* extract the title from within brackets (for zipl) */
831  static char * extractTitle(struct singleLine * line) {  static char * extractTitle(struct singleLine * line) {
832      /* bracketed title... let's extract it (leaks a byte) */      /* bracketed title... let's extract it (leaks a byte) */
833      char * title;      char * title = NULL;
834      title = strdup(line->elements[0].item);      if (line->type == LT_TITLE) {
835      title++;   title = strdup(line->elements[0].item);
836      *(title + strlen(title) - 1) = '\0';   title++;
837     *(title + strlen(title) - 1) = '\0';
838        } else if (line->type == LT_MENUENTRY)
839     title = strdup(line->elements[1].item);
840        else
841     return NULL;
842      return title;      return title;
843  }  }
844    
# Line 906  static int getNextLine(char ** bufPtr, s Line 1096  static int getNextLine(char ** bufPtr, s
1096      return 0;      return 0;
1097  }  }
1098    
1099    static int isnumber(const char *s)
1100    {
1101        int i;
1102        for (i = 0; s[i] != '\0'; i++)
1103     if (s[i] < '0' || s[i] > '9')
1104        return 0;
1105        return i;
1106    }
1107    
1108  static struct grubConfig * readConfig(const char * inName,  static struct grubConfig * readConfig(const char * inName,
1109        struct configFileInfo * cfi) {        struct configFileInfo * cfi) {
1110      int in;      int in;
# Line 920  static struct grubConfig * readConfig(co Line 1119  static struct grubConfig * readConfig(co
1119      int len;      int len;
1120      char * buf;      char * buf;
1121    
1122      if (!strcmp(inName, "-")) {      if (inName == NULL) {
1123            printf("Could not find bootloader configuration\n");
1124            exit(1);
1125        } else if (!strcmp(inName, "-")) {
1126   in = 0;   in = 0;
1127      } else {      } else {
1128   if ((in = open(inName, O_RDONLY)) < 0) {   if ((in = open(inName, O_RDONLY)) < 0) {
# Line 987  static struct grubConfig * readConfig(co Line 1189  static struct grubConfig * readConfig(co
1189      dbgPrintf("\n");      dbgPrintf("\n");
1190      struct keywordTypes *kwType = getKeywordByType(LT_DEFAULT, cfi);      struct keywordTypes *kwType = getKeywordByType(LT_DEFAULT, cfi);
1191      if (kwType && line->numElements == 3 &&      if (kwType && line->numElements == 3 &&
1192      !strcmp(line->elements[1].item, kwType->key)) {      !strcmp(line->elements[1].item, kwType->key) &&
1193        !is_special_grub2_variable(line->elements[2].item)) {
1194   dbgPrintf("Line sets default config\n");   dbgPrintf("Line sets default config\n");
1195   cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;   cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
1196   defaultLine = line;   defaultLine = line;
1197      }      }
  } else if (line->type == LT_DEFAULT && line->numElements == 2) {  
     cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;  
     defaultLine = line;  
1198    
1199          } else if (line->type == LT_KERNEL) {          } else if (iskernel(line->type)) {
1200      /* if by some freak chance this is multiboot and the "module"      /* if by some freak chance this is multiboot and the "module"
1201       * lines came earlier in the template, make sure to use LT_HYPER       * lines came earlier in the template, make sure to use LT_HYPER
1202       * instead of LT_KERNEL now       * instead of LT_KERNEL now
1203       */       */
1204      if (entry->multiboot)      if (entry && entry->multiboot)
1205   line->type = LT_HYPER;   line->type = LT_HYPER;
1206    
1207          } else if (line->type == LT_MBMODULE) {          } else if (line->type == LT_MBMODULE) {
# Line 1013  static struct grubConfig * readConfig(co Line 1213  static struct grubConfig * readConfig(co
1213      for (struct singleLine *l = entry->lines; l; l = l->next) {      for (struct singleLine *l = entry->lines; l; l = l->next) {
1214   if (l->type == LT_HYPER)   if (l->type == LT_HYPER)
1215      break;      break;
1216   else if (l->type == LT_KERNEL) {   else if (iskernel(l->type)) {
1217      l->type = LT_HYPER;      l->type = LT_HYPER;
1218      break;      break;
1219   }   }
# Line 1027  static struct grubConfig * readConfig(co Line 1227  static struct grubConfig * readConfig(co
1227      cfg->fallbackImage = strtol(line->elements[1].item, &end, 10);      cfg->fallbackImage = strtol(line->elements[1].item, &end, 10);
1228      if (*end) cfg->fallbackImage = -1;      if (*end) cfg->fallbackImage = -1;
1229    
1230   } else if (line->type == LT_TITLE && line->numElements > 1) {   } else if ((line->type == LT_DEFAULT && cfi->defaultIsUnquoted) ||
1231      /* make the title a single argument (undoing our parsing) */                  (line->type == LT_TITLE && line->numElements > 1)) {
1232        /* make the title/default a single argument (undoing our parsing) */
1233      len = 0;      len = 0;
1234      for (int i = 1; i < line->numElements; i++) {      for (int i = 1; i < line->numElements; i++) {
1235   len += strlen(line->elements[i].item);   len += strlen(line->elements[i].item);
# Line 1135  static struct grubConfig * readConfig(co Line 1336  static struct grubConfig * readConfig(co
1336      }      }
1337   }   }
1338    
1339     if (line->type == LT_DEFAULT && line->numElements == 2) {
1340        cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
1341        defaultLine = line;
1342     }
1343    
1344   /* If we find a generic config option which should live at the   /* If we find a generic config option which should live at the
1345     top of the file, move it there. Old versions of grubby were     top of the file, move it there. Old versions of grubby were
1346     probably responsible for putting new images in the wrong     probably responsible for putting new images in the wrong
# Line 1192  static struct grubConfig * readConfig(co Line 1398  static struct grubConfig * readConfig(co
1398          if (defaultLine->numElements > 2 &&          if (defaultLine->numElements > 2 &&
1399      cfi->defaultSupportSaved &&      cfi->defaultSupportSaved &&
1400      !strncmp(defaultLine->elements[2].item,"\"${saved_entry}\"", 16)) {      !strncmp(defaultLine->elements[2].item,"\"${saved_entry}\"", 16)) {
1401      cfg->defaultImage = DEFAULT_SAVED_GRUB2;   cfg->cfi->defaultIsSaved = 1;
1402     cfg->defaultImage = DEFAULT_SAVED_GRUB2;
1403     if (cfg->cfi->getEnv) {
1404        char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry");
1405        if (defTitle) {
1406     int index = 0;
1407     if (isnumber(defTitle)) {
1408        index = atoi(defTitle);
1409        entry = findEntryByIndex(cfg, index);
1410     } else {
1411        entry = findEntryByTitle(cfg, defTitle, &index);
1412     }
1413     if (entry)
1414        cfg->defaultImage = index;
1415        }
1416     }
1417   } else if (cfi->defaultIsVariable) {   } else if (cfi->defaultIsVariable) {
1418      char *value = defaultLine->elements[2].item;      char *value = defaultLine->elements[2].item;
1419      while (*value && (*value == '"' || *value == '\'' ||      while (*value && (*value == '"' || *value == '\'' ||
# Line 1233  static struct grubConfig * readConfig(co Line 1454  static struct grubConfig * readConfig(co
1454          cfg->defaultImage = -1;          cfg->defaultImage = -1;
1455      }      }
1456   }   }
1457        } else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) {
1458     char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry");
1459     if (defTitle) {
1460        int index = 0;
1461        if (isnumber(defTitle)) {
1462     index = atoi(defTitle);
1463     entry = findEntryByIndex(cfg, index);
1464        } else {
1465     entry = findEntryByTitle(cfg, defTitle, &index);
1466        }
1467        if (entry)
1468     cfg->defaultImage = index;
1469     }
1470      } else {      } else {
1471          cfg->defaultImage = 0;          cfg->defaultImage = 0;
1472      }      }
# Line 1250  static void writeDefault(FILE * out, cha Line 1484  static void writeDefault(FILE * out, cha
1484    
1485      if (cfg->defaultImage == DEFAULT_SAVED)      if (cfg->defaultImage == DEFAULT_SAVED)
1486   fprintf(out, "%sdefault%ssaved\n", indent, separator);   fprintf(out, "%sdefault%ssaved\n", indent, separator);
1487      else if (cfg->defaultImage == DEFAULT_SAVED_GRUB2)      else if (cfg->cfi->defaultIsSaved) {
1488   fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);   fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);
1489      else if (cfg->defaultImage > -1) {   if (cfg->defaultImage >= 0 && cfg->cfi->setEnv) {
1490        char *title;
1491        entry = findEntryByIndex(cfg, cfg->defaultImage);
1492        line = getLineByType(LT_MENUENTRY, entry->lines);
1493        if (!line)
1494     line = getLineByType(LT_TITLE, entry->lines);
1495        if (line) {
1496     title = extractTitle(line);
1497     if (title)
1498        cfg->cfi->setEnv(cfg->cfi, "saved_entry", title);
1499        }
1500     }
1501        } else if (cfg->defaultImage > -1) {
1502   if (cfg->cfi->defaultIsIndex) {   if (cfg->cfi->defaultIsIndex) {
1503      if (cfg->cfi->defaultIsVariable) {      if (cfg->cfi->defaultIsVariable) {
1504          fprintf(out, "%sset default=\"%d\"\n", indent,          fprintf(out, "%sset default=\"%d\"\n", indent,
# Line 1313  static int writeConfig(struct grubConfig Line 1559  static int writeConfig(struct grubConfig
1559      /* most likely the symlink is relative, so change our      /* most likely the symlink is relative, so change our
1560         directory to the dir of the symlink */         directory to the dir of the symlink */
1561      char *dir = strdupa(outName);      char *dir = strdupa(outName);
1562              rc = chdir(dirname(dir));      rc = chdir(dirname(dir));
     free(dir);  
1563      do {      do {
1564   buf = alloca(len + 1);   buf = alloca(len + 1);
1565   rc = readlink(basename(outName), buf, len);   rc = readlink(basename(outName), buf, len);
# Line 1356  static int writeConfig(struct grubConfig Line 1601  static int writeConfig(struct grubConfig
1601      while (line) {      while (line) {
1602          if (line->type == LT_SET_VARIABLE && defaultKw &&          if (line->type == LT_SET_VARIABLE && defaultKw &&
1603   line->numElements == 3 &&   line->numElements == 3 &&
1604   !strcmp(line->elements[1].item, defaultKw->key)) {   !strcmp(line->elements[1].item, defaultKw->key) &&
1605     !is_special_grub2_variable(line->elements[2].item)) {
1606      writeDefault(out, line->indent, line->elements[0].indent, cfg);      writeDefault(out, line->indent, line->elements[0].indent, cfg);
1607      needs &= ~MAIN_DEFAULT;      needs &= ~MAIN_DEFAULT;
1608   } else if (line->type == LT_DEFAULT) {   } else if (line->type == LT_DEFAULT) {
# Line 1501  static char *findDiskForRoot() Line 1747  static char *findDiskForRoot()
1747      return NULL;      return NULL;
1748  }  }
1749    
1750  void printEntry(struct singleEntry * entry) {  void printEntry(struct singleEntry * entry, FILE *f) {
1751      int i;      int i;
1752      struct singleLine * line;      struct singleLine * line;
1753    
1754      for (line = entry->lines; line; line = line->next) {      for (line = entry->lines; line; line = line->next) {
1755   fprintf(stderr, "DBG: %s", line->indent);   log_message(f, "DBG: %s", line->indent);
1756   for (i = 0; i < line->numElements; i++) {   for (i = 0; i < line->numElements; i++) {
1757      /* Need to handle this, because we strip the quotes from      /* Need to handle this, because we strip the quotes from
1758       * menuentry when read it. */       * menuentry when read it. */
1759      if (line->type == LT_MENUENTRY && i == 1) {      if (line->type == LT_MENUENTRY && i == 1) {
1760   if(!isquote(*line->elements[i].item))   if(!isquote(*line->elements[i].item))
1761      fprintf(stderr, "\'%s\'", line->elements[i].item);      log_message(f, "\'%s\'", line->elements[i].item);
1762   else   else
1763      fprintf(stderr, "%s", line->elements[i].item);      log_message(f, "%s", line->elements[i].item);
1764   fprintf(stderr, "%s", line->elements[i].indent);   log_message(f, "%s", line->elements[i].indent);
1765    
1766   continue;   continue;
1767      }      }
1768            
1769      fprintf(stderr, "%s%s",      log_message(f, "%s%s",
1770      line->elements[i].item, line->elements[i].indent);      line->elements[i].item, line->elements[i].indent);
1771   }   }
1772   fprintf(stderr, "\n");   log_message(f, "\n");
1773      }      }
1774  }  }
1775    
1776  void notSuitablePrintf(struct singleEntry * entry, const char *fmt, ...)  void notSuitablePrintf(struct singleEntry * entry, int okay, const char *fmt, ...)
1777  {  {
1778      va_list argp;      static int once;
1779        va_list argp, argq;
1780    
1781        va_start(argp, fmt);
1782    
1783        va_copy(argq, argp);
1784        if (!once) {
1785     log_time(NULL);
1786     log_message(NULL, "command line: %s\n", saved_command_line);
1787        }
1788        log_message(NULL, "DBG: Image entry %s: ", okay ? "succeeded" : "failed");
1789        log_vmessage(NULL, fmt, argq);
1790    
1791        printEntry(entry, NULL);
1792        va_end(argq);
1793    
1794      if (!debug)      if (!debug) {
1795     once = 1;
1796         va_end(argp);
1797   return;   return;
1798        }
1799    
1800      va_start(argp, fmt);      if (okay) {
1801     va_end(argp);
1802     return;
1803        }
1804    
1805        if (!once)
1806     log_message(stderr, "DBG: command line: %s\n", saved_command_line);
1807        once = 1;
1808      fprintf(stderr, "DBG: Image entry failed: ");      fprintf(stderr, "DBG: Image entry failed: ");
1809      vfprintf(stderr, fmt, argp);      vfprintf(stderr, fmt, argp);
1810      printEntry(entry);      printEntry(entry, stderr);
1811      va_end(argp);      va_end(argp);
1812  }  }
1813    
# Line 1564  int suitableImage(struct singleEntry * e Line 1834  int suitableImage(struct singleEntry * e
1834      char * rootdev;      char * rootdev;
1835    
1836      if (skipRemoved && entry->skip) {      if (skipRemoved && entry->skip) {
1837   notSuitablePrintf(entry, "marked to skip\n");   notSuitablePrintf(entry, 0, "marked to skip\n");
1838   return 0;   return 0;
1839      }      }
1840    
1841      line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines);      line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines);
1842      if (!line) {      if (!line) {
1843   notSuitablePrintf(entry, "no line found\n");   notSuitablePrintf(entry, 0, "no line found\n");
1844   return 0;   return 0;
1845      }      }
1846      if (line->numElements < 2) {      if (line->numElements < 2) {
1847   notSuitablePrintf(entry, "line has only %d elements\n",   notSuitablePrintf(entry, 0, "line has only %d elements\n",
1848      line->numElements);      line->numElements);
1849   return 0;   return 0;
1850      }      }
1851    
1852      if (flags & GRUBBY_BADIMAGE_OKAY) return 1;      if (flags & GRUBBY_BADIMAGE_OKAY) {
1853        notSuitablePrintf(entry, 1, "\n");
1854        return 1;
1855        }
1856    
1857      fullName = alloca(strlen(bootPrefix) +      fullName = alloca(strlen(bootPrefix) +
1858        strlen(line->elements[1].item) + 1);        strlen(line->elements[1].item) + 1);
# Line 1590  int suitableImage(struct singleEntry * e Line 1863  int suitableImage(struct singleEntry * e
1863      sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/",      sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/",
1864              line->elements[1].item + rootspec_offset);              line->elements[1].item + rootspec_offset);
1865      if (access(fullName, R_OK)) {      if (access(fullName, R_OK)) {
1866   notSuitablePrintf(entry, "access to %s failed\n", fullName);   notSuitablePrintf(entry, 0, "access to %s failed\n", fullName);
1867   return 0;   return 0;
1868      }      }
1869      for (i = 2; i < line->numElements; i++)      for (i = 2; i < line->numElements; i++)
# Line 1611  int suitableImage(struct singleEntry * e Line 1884  int suitableImage(struct singleEntry * e
1884    
1885              /* failed to find one */              /* failed to find one */
1886              if (!line) {              if (!line) {
1887   notSuitablePrintf(entry, "no line found\n");   notSuitablePrintf(entry, 0, "no line found\n");
1888   return 0;   return 0;
1889              }              }
1890    
# Line 1620  int suitableImage(struct singleEntry * e Line 1893  int suitableImage(struct singleEntry * e
1893      if (i < line->numElements)      if (i < line->numElements)
1894          dev = line->elements[i].item + 5;          dev = line->elements[i].item + 5;
1895      else {      else {
1896   notSuitablePrintf(entry, "no root= entry found\n");   notSuitablePrintf(entry, 0, "no root= entry found\n");
1897   /* it failed too...  can't find root= */   /* it failed too...  can't find root= */
1898          return 0;          return 0;
1899              }              }
# Line 1629  int suitableImage(struct singleEntry * e Line 1902  int suitableImage(struct singleEntry * e
1902    
1903      dev = getpathbyspec(dev);      dev = getpathbyspec(dev);
1904      if (!getpathbyspec(dev)) {      if (!getpathbyspec(dev)) {
1905          notSuitablePrintf(entry, "can't find blkid entry for %s\n", dev);          notSuitablePrintf(entry, 0, "can't find blkid entry for %s\n", dev);
1906          return 0;          return 0;
1907      } else      } else
1908   dev = getpathbyspec(dev);   dev = getpathbyspec(dev);
1909    
1910      rootdev = findDiskForRoot();      rootdev = findDiskForRoot();
1911      if (!rootdev) {      if (!rootdev) {
1912          notSuitablePrintf(entry, "can't find root device\n");          notSuitablePrintf(entry, 0, "can't find root device\n");
1913   return 0;   return 0;
1914      }      }
1915    
1916      if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) {      if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) {
1917          notSuitablePrintf(entry, "uuid missing: rootdev %s, dev %s\n",          notSuitablePrintf(entry, 0, "uuid missing: rootdev %s, dev %s\n",
1918   getuuidbydev(rootdev), getuuidbydev(dev));   getuuidbydev(rootdev), getuuidbydev(dev));
1919          free(rootdev);          free(rootdev);
1920          return 0;          return 0;
1921      }      }
1922    
1923      if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) {      if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) {
1924          notSuitablePrintf(entry, "uuid mismatch: rootdev %s, dev %s\n",          notSuitablePrintf(entry, 0, "uuid mismatch: rootdev %s, dev %s\n",
1925   getuuidbydev(rootdev), getuuidbydev(dev));   getuuidbydev(rootdev), getuuidbydev(dev));
1926   free(rootdev);   free(rootdev);
1927          return 0;          return 0;
1928      }      }
1929    
1930      free(rootdev);      free(rootdev);
1931        notSuitablePrintf(entry, 1, "\n");
1932    
1933      return 1;      return 1;
1934  }  }
# Line 1688  struct singleEntry * findEntryByPath(str Line 1962  struct singleEntry * findEntryByPath(str
1962   }   }
1963    
1964   indexVars[i + 1] = -1;   indexVars[i + 1] = -1;
1965    
1966   i = 0;   i = 0;
1967   if (index) {   if (index) {
1968      while (i < *index) i++;      while (i < *index) {
1969      if (indexVars[i] == -1) return NULL;   i++;
1970     if (indexVars[i] == -1) return NULL;
1971        }
1972   }   }
1973    
1974   entry = findEntryByIndex(config, indexVars[i]);   entry = findEntryByIndex(config, indexVars[i]);
1975   if (!entry) return NULL;   if (!entry) return NULL;
1976    
1977   line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines);   line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines);
1978   if (!line) return NULL;   if (!line) return NULL;
1979    
1980   if (index) *index = indexVars[i];   if (index) *index = indexVars[i];
# Line 1747  struct singleEntry * findEntryByPath(str Line 2023  struct singleEntry * findEntryByPath(str
2023    
2024      /* check all the lines matching checkType */      /* check all the lines matching checkType */
2025      for (line = entry->lines; line; line = line->next) {      for (line = entry->lines; line; line = line->next) {
2026   line = getLineByType(entry->multiboot && checkType == LT_KERNEL ?   enum lineType_e ct = checkType;
2027       LT_KERNEL|LT_MBMODULE|LT_HYPER :   if (entry->multiboot && checkType == LT_KERNEL)
2028       checkType, line);      ct = LT_KERNEL|LT_KERNEL_EFI|LT_MBMODULE|LT_HYPER|LT_KERNEL_16;
2029   if (!line) break;  /* not found in this entry */   else if (checkType & LT_KERNEL)
2030        ct = checkType | LT_KERNEL_EFI | LT_KERNEL_16;
2031     line = getLineByType(ct, line);
2032     if (!line)
2033        break;  /* not found in this entry */
2034    
2035   if (line && line->type != LT_MENUENTRY &&   if (line && line->type != LT_MENUENTRY &&
2036   line->numElements >= 2) {   line->numElements >= 2) {
# Line 1769  struct singleEntry * findEntryByPath(str Line 2049  struct singleEntry * findEntryByPath(str
2049       * non-Linux boot entries (could find netbsd etc, though, which is       * non-Linux boot entries (could find netbsd etc, though, which is
2050       * unfortunate)       * unfortunate)
2051       */       */
2052      if (line && getLineByType(LT_KERNEL|LT_HYPER, entry->lines))      if (line && getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines))
2053   break; /* found 'im! */   break; /* found 'im! */
2054   }   }
2055    
# Line 1779  struct singleEntry * findEntryByPath(str Line 2059  struct singleEntry * findEntryByPath(str
2059      return entry;      return entry;
2060  }  }
2061    
2062    struct singleEntry * findEntryByTitle(struct grubConfig * cfg, char *title,
2063          int * index) {
2064        struct singleEntry * entry;
2065        struct singleLine * line;
2066        int i;
2067        char * newtitle;
2068    
2069        for (i = 0, entry = cfg->entries; entry; entry = entry->next, i++) {
2070     if (index && i < *index)
2071        continue;
2072     line = getLineByType(LT_TITLE, entry->lines);
2073     if (!line)
2074        line = getLineByType(LT_MENUENTRY, entry->lines);
2075     if (!line)
2076        continue;
2077     newtitle = grub2ExtractTitle(line);
2078     if (!newtitle)
2079        continue;
2080     if (!strcmp(title, newtitle))
2081        break;
2082        }
2083    
2084        if (!entry)
2085     return NULL;
2086    
2087        if (index)
2088     *index = i;
2089        return entry;
2090    }
2091    
2092  struct singleEntry * findEntryByIndex(struct grubConfig * cfg, int index) {  struct singleEntry * findEntryByIndex(struct grubConfig * cfg, int index) {
2093      struct singleEntry * entry;      struct singleEntry * entry;
2094    
# Line 1801  struct singleEntry * findTemplate(struct Line 2111  struct singleEntry * findTemplate(struct
2111      struct singleEntry * entry, * entry2;      struct singleEntry * entry, * entry2;
2112      int index;      int index;
2113    
2114      if (cfg->defaultImage > -1) {      if (cfg->cfi->defaultIsSaved) {
2115     if (cfg->cfi->getEnv) {
2116        char *defTitle = cfg->cfi->getEnv(cfg->cfi, "saved_entry");
2117        if (defTitle) {
2118     int index = 0;
2119     if (isnumber(defTitle)) {
2120        index = atoi(defTitle);
2121        entry = findEntryByIndex(cfg, index);
2122     } else {
2123        entry = findEntryByTitle(cfg, defTitle, &index);
2124     }
2125     if (entry && suitableImage(entry, prefix, skipRemoved, flags)) {
2126        cfg->defaultImage = index;
2127        if (indexPtr)
2128     *indexPtr = index;
2129        return entry;
2130     }
2131        }
2132     }
2133        } else if (cfg->defaultImage > -1) {
2134   entry = findEntryByIndex(cfg, cfg->defaultImage);   entry = findEntryByIndex(cfg, cfg->defaultImage);
2135   if (entry && suitableImage(entry, prefix, skipRemoved, flags)) {   if (entry && suitableImage(entry, prefix, skipRemoved, flags)) {
2136      if (indexPtr) *indexPtr = cfg->defaultImage;      if (indexPtr) *indexPtr = cfg->defaultImage;
# Line 1955  void displayEntry(struct singleEntry * e Line 2284  void displayEntry(struct singleEntry * e
2284      struct singleLine * line;      struct singleLine * line;
2285      char * root = NULL;      char * root = NULL;
2286      int i;      int i;
2287        int j;
2288    
2289      printf("index=%d\n", index);      printf("index=%d\n", index);
2290    
2291      line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines);      line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines);
2292      if (!line) {      if (!line) {
2293          printf("non linux entry\n");          printf("non linux entry\n");
2294          return;          return;
# Line 2023  void displayEntry(struct singleEntry * e Line 2353  void displayEntry(struct singleEntry * e
2353   printf("root=%s\n", s);   printf("root=%s\n", s);
2354      }      }
2355    
2356      line = getLineByType(LT_INITRD, entry->lines);      line = getLineByType(LT_INITRD|LT_INITRD_EFI|LT_INITRD_16, entry->lines);
2357    
2358      if (line && line->numElements >= 2) {      if (line && line->numElements >= 2) {
2359   if (!strncmp(prefix, line->elements[1].item, strlen(prefix)))   if (!strncmp(prefix, line->elements[1].item, strlen(prefix)))
# Line 2042  void displayEntry(struct singleEntry * e Line 2372  void displayEntry(struct singleEntry * e
2372      } else {      } else {
2373   char * title;   char * title;
2374   line = getLineByType(LT_MENUENTRY, entry->lines);   line = getLineByType(LT_MENUENTRY, entry->lines);
2375   title = grub2ExtractTitle(line);   if (line) {
2376   if (title)      title = grub2ExtractTitle(line);
2377      printf("title=%s\n", title);      if (title)
2378     printf("title=%s\n", title);
2379     }
2380        }
2381    
2382        for (j = 0, line = entry->lines; line; line = line->next) {
2383     if ((line->type & LT_MBMODULE) && line->numElements >= 2) {
2384        if (!strncmp(prefix, line->elements[1].item, strlen(prefix)))
2385     printf("mbmodule%d=", j);
2386        else
2387     printf("mbmodule%d=%s", j, prefix);
2388    
2389        for (i = 1; i < line->numElements; i++)
2390     printf("%s%s", line->elements[i].item, line->elements[i].indent);
2391        printf("\n");
2392        j++;
2393     }
2394      }      }
2395  }  }
2396    
# Line 2424  struct singleLine * addLineTmpl(struct s Line 2770  struct singleLine * addLineTmpl(struct s
2770  {  {
2771      struct singleLine * newLine = lineDup(tmplLine);      struct singleLine * newLine = lineDup(tmplLine);
2772    
2773        if (isEfi && cfi == &grub2ConfigType) {
2774     enum lineType_e old = newLine->type;
2775     newLine->type = preferredLineType(newLine->type, cfi);
2776     if (old != newLine->type)
2777        newLine->elements[0].item = getKeyByType(newLine->type, cfi);
2778        }
2779    
2780      if (val) {      if (val) {
2781   /* override the inherited value with our own.   /* override the inherited value with our own.
2782   * This is a little weak because it only applies to elements[1]   * This is a little weak because it only applies to elements[1]
# Line 2433  struct singleLine * addLineTmpl(struct s Line 2786  struct singleLine * addLineTmpl(struct s
2786   insertElement(newLine, val, 1, cfi);   insertElement(newLine, val, 1, cfi);
2787    
2788   /* but try to keep the rootspec from the template... sigh */   /* but try to keep the rootspec from the template... sigh */
2789   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|LT_KERNEL_16|LT_INITRD_16)) {
2790      char * rootspec = getRootSpecifier(tmplLine->elements[1].item);      char * rootspec = getRootSpecifier(tmplLine->elements[1].item);
2791      if (rootspec != NULL) {      if (rootspec != NULL) {
2792   free(newLine->elements[1].item);   free(newLine->elements[1].item);
# Line 2470  struct singleLine *  addLine(struct sing Line 2823  struct singleLine *  addLine(struct sing
2823      /* NB: This function shouldn't allocate items on the heap, rather on the      /* NB: This function shouldn't allocate items on the heap, rather on the
2824       * stack since it calls addLineTmpl which will make copies.       * stack since it calls addLineTmpl which will make copies.
2825       */       */
   
2826      if (type == LT_TITLE && cfi->titleBracketed) {      if (type == LT_TITLE && cfi->titleBracketed) {
2827   /* we're doing a bracketed title (zipl) */   /* we're doing a bracketed title (zipl) */
2828   tmpl.type = type;   tmpl.type = type;
# Line 2804  int updateActualImage(struct grubConfig Line 3156  int updateActualImage(struct grubConfig
3156      firstElement = 2;      firstElement = 2;
3157    
3158   } else {   } else {
3159      line = getLineByType(LT_KERNEL|LT_MBMODULE, entry->lines);      line = getLineByType(LT_KERNEL|LT_MBMODULE|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines);
3160      if (!line) {      if (!line) {
3161   /* no LT_KERNEL or LT_MBMODULE in this entry? */   /* no LT_KERNEL or LT_MBMODULE in this entry? */
3162   continue;   continue;
# Line 2960  int updateImage(struct grubConfig * cfg, Line 3312  int updateImage(struct grubConfig * cfg,
3312      return rc;      return rc;
3313  }  }
3314    
3315    int addMBInitrd(struct grubConfig * cfg, const char *newMBKernel,
3316     const char * image, const char * prefix, const char * initrd,
3317     const char * title) {
3318        struct singleEntry * entry;
3319        struct singleLine * line, * kernelLine, *endLine = NULL;
3320        int index = 0;
3321    
3322        if (!image) return 0;
3323    
3324        for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {
3325            kernelLine = getLineByType(LT_MBMODULE, entry->lines);
3326            if (!kernelLine) continue;
3327    
3328     /* if title is supplied, the entry's title must match it. */
3329     if (title) {
3330        char *linetitle;
3331    
3332        line = getLineByType(LT_TITLE|LT_MENUENTRY, entry->lines);
3333        if (!line)
3334     continue;
3335    
3336        linetitle = extractTitle(line);
3337        if (!linetitle)
3338     continue;
3339        if (strcmp(title, linetitle)) {
3340     free(linetitle);
3341     continue;
3342        }
3343        free(linetitle);
3344     }
3345    
3346            if (prefix) {
3347                int prefixLen = strlen(prefix);
3348                if (!strncmp(initrd, prefix, prefixLen))
3349                    initrd += prefixLen;
3350            }
3351     endLine = getLineByType(LT_ENTRY_END, entry->lines);
3352     if (endLine)
3353        removeLine(entry, endLine);
3354            line = addLine(entry, cfg->cfi, preferredLineType(LT_MBMODULE,cfg->cfi),
3355     kernelLine->indent, initrd);
3356            if (!line)
3357        return 1;
3358     if (endLine) {
3359        line = addLine(entry, cfg->cfi, LT_ENTRY_END, "", NULL);
3360                if (!line)
3361     return 1;
3362     }
3363    
3364            break;
3365        }
3366    
3367        return 0;
3368    }
3369    
3370  int updateInitrd(struct grubConfig * cfg, const char * image,  int updateInitrd(struct grubConfig * cfg, const char * image,
3371                   const char * prefix, const char * initrd) {                   const char * prefix, const char * initrd, const char * title) {
3372      struct singleEntry * entry;      struct singleEntry * entry;
3373      struct singleLine * line, * kernelLine, *endLine = NULL;      struct singleLine * line, * kernelLine, *endLine = NULL;
3374      int index = 0;      int index = 0;
# Line 2969  int updateInitrd(struct grubConfig * cfg Line 3376  int updateInitrd(struct grubConfig * cfg
3376      if (!image) return 0;      if (!image) return 0;
3377    
3378      for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {      for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {
3379          kernelLine = getLineByType(LT_KERNEL, entry->lines);          kernelLine = getLineByType(LT_KERNEL|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines);
3380          if (!kernelLine) continue;          if (!kernelLine) continue;
3381    
3382          line = getLineByType(LT_INITRD, entry->lines);   /* if title is supplied, the entry's title must match it. */
3383     if (title) {
3384        char *linetitle;
3385    
3386        line = getLineByType(LT_TITLE|LT_MENUENTRY, entry->lines);
3387        if (!line)
3388     continue;
3389    
3390        linetitle = extractTitle(line);
3391        if (!linetitle)
3392     continue;
3393        if (strcmp(title, linetitle)) {
3394     free(linetitle);
3395     continue;
3396        }
3397        free(linetitle);
3398     }
3399    
3400            line = getLineByType(LT_INITRD|LT_INITRD_EFI|LT_INITRD_16, entry->lines);
3401          if (line)          if (line)
3402              removeLine(entry, line);              removeLine(entry, line);
3403          if (prefix) {          if (prefix) {
# Line 2983  int updateInitrd(struct grubConfig * cfg Line 3408  int updateInitrd(struct grubConfig * cfg
3408   endLine = getLineByType(LT_ENTRY_END, entry->lines);   endLine = getLineByType(LT_ENTRY_END, entry->lines);
3409   if (endLine)   if (endLine)
3410      removeLine(entry, endLine);      removeLine(entry, endLine);
3411          line = addLine(entry, cfg->cfi, LT_INITRD, kernelLine->indent, initrd);   enum lineType_e lt;
3412     switch(kernelLine->type) {
3413        case LT_KERNEL:
3414            lt = LT_INITRD;
3415     break;
3416        case LT_KERNEL_EFI:
3417            lt = LT_INITRD_EFI;
3418     break;
3419        case LT_KERNEL_16:
3420            lt = LT_INITRD_16;
3421     break;
3422        default:
3423            lt = preferredLineType(LT_INITRD, cfg->cfi);
3424     }
3425            line = addLine(entry, cfg->cfi, lt, kernelLine->indent, initrd);
3426          if (!line)          if (!line)
3427      return 1;      return 1;
3428   if (endLine) {   if (endLine) {
# Line 3342  int addNewKernel(struct grubConfig * con Line 3781  int addNewKernel(struct grubConfig * con
3781   const char * newKernelPath, const char * newKernelTitle,   const char * newKernelPath, const char * newKernelTitle,
3782   const char * newKernelArgs, const char * newKernelInitrd,   const char * newKernelArgs, const char * newKernelInitrd,
3783   const char ** extraInitrds, int extraInitrdCount,   const char ** extraInitrds, int extraInitrdCount,
3784                   const char * newMBKernel, const char * newMBKernelArgs) {                   const char * newMBKernel, const char * newMBKernelArgs,
3785     const char * newDevTreePath) {
3786      struct singleEntry * new;      struct singleEntry * new;
3787      struct singleLine * newLine = NULL, * tmplLine = NULL, * masterLine = NULL;      struct singleLine * newLine = NULL, * tmplLine = NULL, * masterLine = NULL;
3788      int needs;      int needs;
# Line 3383  int addNewKernel(struct grubConfig * con Line 3823  int addNewKernel(struct grubConfig * con
3823          needs |= NEED_MB;          needs |= NEED_MB;
3824          new->multiboot = 1;          new->multiboot = 1;
3825      }      }
3826        if (newDevTreePath && getKeywordByType(LT_DEVTREE, config->cfi))
3827     needs |= NEED_DEVTREE;
3828    
3829      if (template) {      if (template) {
3830   for (masterLine = template->lines;   for (masterLine = template->lines;
# Line 3396  int addNewKernel(struct grubConfig * con Line 3838  int addNewKernel(struct grubConfig * con
3838      while (*chptr && isspace(*chptr)) chptr++;      while (*chptr && isspace(*chptr)) chptr++;
3839      if (*chptr == '#') continue;      if (*chptr == '#') continue;
3840    
3841      if (tmplLine->type == LT_KERNEL &&      if (iskernel(tmplLine->type) && tmplLine->numElements >= 2) {
     tmplLine->numElements >= 2) {  
3842   if (!template->multiboot && (needs & NEED_MB)) {   if (!template->multiboot && (needs & NEED_MB)) {
3843      /* it's not a multiboot template and this is the kernel      /* it's not a multiboot template and this is the kernel
3844       * line.  Try to be intelligent about inserting the       * line.  Try to be intelligent about inserting the
# Line 3474  int addNewKernel(struct grubConfig * con Line 3915  int addNewKernel(struct grubConfig * con
3915      /* template is multi but new is not,      /* template is multi but new is not,
3916       * insert the kernel in the first module slot       * insert the kernel in the first module slot
3917       */       */
3918      tmplLine->type = LT_KERNEL;      tmplLine->type = preferredLineType(LT_KERNEL, config->cfi);
3919      free(tmplLine->elements[0].item);      free(tmplLine->elements[0].item);
3920      tmplLine->elements[0].item =      tmplLine->elements[0].item =
3921   strdup(getKeywordByType(LT_KERNEL, config->cfi)->key);   strdup(getKeywordByType(tmplLine->type,
3922     config->cfi)->key);
3923      newLine = addLineTmpl(new, tmplLine, newLine,      newLine = addLineTmpl(new, tmplLine, newLine,
3924    newKernelPath + strlen(prefix), config->cfi);    newKernelPath + strlen(prefix),
3925      config->cfi);
3926      needs &= ~NEED_KERNEL;      needs &= ~NEED_KERNEL;
3927   } else if (needs & NEED_INITRD) {   } else if (needs & NEED_INITRD) {
3928      char *initrdVal;      char *initrdVal;
3929      /* template is multi but new is not,      /* template is multi but new is not,
3930       * insert the initrd in the second module slot       * insert the initrd in the second module slot
3931       */       */
3932      tmplLine->type = LT_INITRD;      tmplLine->type = preferredLineType(LT_INITRD, config->cfi);
3933      free(tmplLine->elements[0].item);      free(tmplLine->elements[0].item);
3934      tmplLine->elements[0].item =      tmplLine->elements[0].item =
3935   strdup(getKeywordByType(LT_INITRD, config->cfi)->key);   strdup(getKeywordByType(tmplLine->type,
3936     config->cfi)->key);
3937      initrdVal = getInitrdVal(config, prefix, tmplLine, newKernelInitrd, extraInitrds, extraInitrdCount);      initrdVal = getInitrdVal(config, prefix, tmplLine, newKernelInitrd, extraInitrds, extraInitrdCount);
3938      newLine = addLineTmpl(new, tmplLine, newLine, initrdVal, config->cfi);      newLine = addLineTmpl(new, tmplLine, newLine, initrdVal, config->cfi);
3939      free(initrdVal);      free(initrdVal);
3940      needs &= ~NEED_INITRD;      needs &= ~NEED_INITRD;
3941   }   }
3942    
3943      } else if (tmplLine->type == LT_INITRD &&      } else if (isinitrd(tmplLine->type) && tmplLine->numElements >= 2) {
        tmplLine->numElements >= 2) {  
3944   if (needs & NEED_INITRD &&   if (needs & NEED_INITRD &&
3945      new->multiboot && !template->multiboot &&      new->multiboot && !template->multiboot &&
3946      config->cfi->mbInitRdIsModule) {      config->cfi->mbInitRdIsModule) {
# Line 3551  int addNewKernel(struct grubConfig * con Line 3994  int addNewKernel(struct grubConfig * con
3994      static const char *prefix = "'Loading ";      static const char *prefix = "'Loading ";
3995      if (tmplLine->numElements > 1 &&      if (tmplLine->numElements > 1 &&
3996      strstr(tmplLine->elements[1].item, prefix) &&      strstr(tmplLine->elements[1].item, prefix) &&
3997      masterLine->next && masterLine->next->type == LT_KERNEL) {      masterLine->next &&
3998        iskernel(masterLine->next->type)) {
3999   char *newTitle = malloc(strlen(prefix) +   char *newTitle = malloc(strlen(prefix) +
4000   strlen(newKernelTitle) + 2);   strlen(newKernelTitle) + 2);
4001    
# Line 3566  int addNewKernel(struct grubConfig * con Line 4010  int addNewKernel(struct grubConfig * con
4010   newLine = addLineTmpl(new, tmplLine, newLine, NULL,   newLine = addLineTmpl(new, tmplLine, newLine, NULL,
4011   config->cfi);   config->cfi);
4012      }      }
4013        } else if (tmplLine->type == LT_DEVTREE &&
4014           tmplLine->numElements == 2 && newDevTreePath) {
4015            newLine = addLineTmpl(new, tmplLine, newLine,
4016          newDevTreePath + strlen(prefix),
4017          config->cfi);
4018     needs &= ~NEED_DEVTREE;
4019        } else if (tmplLine->type == LT_ENTRY_END && needs & NEED_DEVTREE) {
4020     const char *ndtp = newDevTreePath;
4021     if (!strncmp(newDevTreePath, prefix, strlen(prefix)))
4022        ndtp += strlen(prefix);
4023     newLine = addLine(new, config->cfi, LT_DEVTREE,
4024      config->secondaryIndent,
4025      ndtp);
4026     needs &= ~NEED_DEVTREE;
4027     newLine = addLineTmpl(new, tmplLine, newLine, NULL, config->cfi);
4028      } else {      } else {
4029   /* pass through other lines from the template */   /* pass through other lines from the template */
4030   newLine = addLineTmpl(new, tmplLine, newLine, NULL, config->cfi);   newLine = addLineTmpl(new, tmplLine, newLine, NULL, config->cfi);
# Line 3578  int addNewKernel(struct grubConfig * con Line 4037  int addNewKernel(struct grubConfig * con
4037   */   */
4038   switch (config->cfi->entryStart) {   switch (config->cfi->entryStart) {
4039      case LT_KERNEL:      case LT_KERNEL:
4040        case LT_KERNEL_EFI:
4041        case LT_KERNEL_16:
4042   if (new->multiboot && config->cfi->mbHyperFirst) {   if (new->multiboot && config->cfi->mbHyperFirst) {
4043      /* fall through to LT_HYPER */      /* fall through to LT_HYPER */
4044   } else {   } else {
4045      newLine = addLine(new, config->cfi, LT_KERNEL,      newLine = addLine(new, config->cfi,
4046              preferredLineType(LT_KERNEL, config->cfi),
4047        config->primaryIndent,        config->primaryIndent,
4048        newKernelPath + strlen(prefix));        newKernelPath + strlen(prefix));
4049      needs &= ~NEED_KERNEL;      needs &= ~NEED_KERNEL;
# Line 3638  int addNewKernel(struct grubConfig * con Line 4100  int addNewKernel(struct grubConfig * con
4100   }   }
4101      }      }
4102    
4103        struct singleLine *endLine = NULL;
4104        endLine = getLineByType(LT_ENTRY_END, new->lines);
4105        if (endLine) {
4106        removeLine(new, endLine);
4107        needs |= NEED_END;
4108        }
4109    
4110      /* add the remainder of the lines, i.e. those that either      /* add the remainder of the lines, i.e. those that either
4111       * weren't present in the template, or in the case of no template,       * weren't present in the template, or in the case of no template,
4112       * all the lines following the entryStart.       * all the lines following the entryStart.
# Line 3657  int addNewKernel(struct grubConfig * con Line 4126  int addNewKernel(struct grubConfig * con
4126      if (needs & NEED_KERNEL) {      if (needs & NEED_KERNEL) {
4127   newLine = addLine(new, config->cfi,   newLine = addLine(new, config->cfi,
4128    (new->multiboot && getKeywordByType(LT_MBMODULE,    (new->multiboot && getKeywordByType(LT_MBMODULE,
4129        config->cfi)) ?        config->cfi))
4130    LT_MBMODULE : LT_KERNEL,     ? LT_MBMODULE
4131     : preferredLineType(LT_KERNEL, config->cfi),
4132    config->secondaryIndent,    config->secondaryIndent,
4133    newKernelPath + strlen(prefix));    newKernelPath + strlen(prefix));
4134   needs &= ~NEED_KERNEL;   needs &= ~NEED_KERNEL;
# Line 3674  int addNewKernel(struct grubConfig * con Line 4144  int addNewKernel(struct grubConfig * con
4144   initrdVal = getInitrdVal(config, prefix, NULL, newKernelInitrd, extraInitrds, extraInitrdCount);   initrdVal = getInitrdVal(config, prefix, NULL, newKernelInitrd, extraInitrds, extraInitrdCount);
4145   newLine = addLine(new, config->cfi,   newLine = addLine(new, config->cfi,
4146    (new->multiboot && getKeywordByType(LT_MBMODULE,    (new->multiboot && getKeywordByType(LT_MBMODULE,
4147        config->cfi)) ?        config->cfi))
4148    LT_MBMODULE : LT_INITRD,     ? LT_MBMODULE
4149       : preferredLineType(LT_INITRD, config->cfi),
4150    config->secondaryIndent,    config->secondaryIndent,
4151    initrdVal);    initrdVal);
4152   free(initrdVal);   free(initrdVal);
4153   needs &= ~NEED_INITRD;   needs &= ~NEED_INITRD;
4154      }      }
4155        if (needs & NEED_DEVTREE) {
4156     newLine = addLine(new, config->cfi, LT_DEVTREE,
4157      config->secondaryIndent,
4158      newDevTreePath);
4159     needs &= ~NEED_DEVTREE;
4160        }
4161    
4162        /* NEEDS_END must be last on bootloaders that need it... */
4163      if (needs & NEED_END) {      if (needs & NEED_END) {
4164   newLine = addLine(new, config->cfi, LT_ENTRY_END,   newLine = addLine(new, config->cfi, LT_ENTRY_END,
4165   config->secondaryIndent, NULL);   config->secondaryIndent, NULL);
# Line 3707  static void traceback(int signum) Line 4186  static void traceback(int signum)
4186      memset(array, '\0', sizeof (array));      memset(array, '\0', sizeof (array));
4187      size = backtrace(array, 40);      size = backtrace(array, 40);
4188    
4189      fprintf(stderr, "grubby recieved SIGSEGV!  Backtrace (%ld):\n",      fprintf(stderr, "grubby received SIGSEGV!  Backtrace (%ld):\n",
4190              (unsigned long)size);              (unsigned long)size);
4191      backtrace_symbols_fd(array, size, STDERR_FILENO);      backtrace_symbols_fd(array, size, STDERR_FILENO);
4192      exit(1);      exit(1);
# Line 3732  int main(int argc, const char ** argv) { Line 4211  int main(int argc, const char ** argv) {
4211      char * newKernelArgs = NULL;      char * newKernelArgs = NULL;
4212      char * newKernelInitrd = NULL;      char * newKernelInitrd = NULL;
4213      char * newKernelTitle = NULL;      char * newKernelTitle = NULL;
4214      char * newKernelVersion = NULL;      char * newDevTreePath = NULL;
4215      char * newMBKernel = NULL;      char * newMBKernel = NULL;
4216      char * newMBKernelArgs = NULL;      char * newMBKernelArgs = NULL;
4217      char * removeMBKernelArgs = NULL;      char * removeMBKernelArgs = NULL;
# Line 3742  int main(int argc, const char ** argv) { Line 4221  int main(int argc, const char ** argv) {
4221      char * removeArgs = NULL;      char * removeArgs = NULL;
4222      char * kernelInfo = NULL;      char * kernelInfo = NULL;
4223      char * extraInitrds[MAX_EXTRA_INITRDS] = { NULL };      char * extraInitrds[MAX_EXTRA_INITRDS] = { NULL };
4224        char * envPath = NULL;
4225      const char * chptr = NULL;      const char * chptr = NULL;
4226      struct configFileInfo * cfi = NULL;      struct configFileInfo * cfi = NULL;
4227      struct grubConfig * config;      struct grubConfig * config;
# Line 3789  int main(int argc, const char ** argv) { Line 4269  int main(int argc, const char ** argv) {
4269      _("display the index of the default kernel") },      _("display the index of the default kernel") },
4270   { "default-title", 0, 0, &displayDefaultTitle, 0,   { "default-title", 0, 0, &displayDefaultTitle, 0,
4271      _("display the title of the default kernel") },      _("display the title of the default kernel") },
4272     { "devtree", 0, POPT_ARG_STRING, &newDevTreePath, 0,
4273        _("device tree file for new stanza"), _("dtb-path") },
4274     { "devtreedir", 0, POPT_ARG_STRING, &newDevTreePath, 0,
4275        _("device tree directory for new stanza"), _("dtb-path") },
4276   { "elilo", 0, POPT_ARG_NONE, &configureELilo, 0,   { "elilo", 0, POPT_ARG_NONE, &configureELilo, 0,
4277      _("configure elilo bootloader") },      _("configure elilo bootloader") },
4278     { "efi", 0, POPT_ARG_NONE, &isEfi, 0,
4279        _("force grub2 stanzas to use efi") },
4280     { "env", 0, POPT_ARG_STRING, &envPath, 0,
4281        _("path for environment data"),
4282        _("path") },
4283   { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0,   { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0,
4284      _("configure extlinux bootloader (from syslinux)") },      _("configure extlinux bootloader (from syslinux)") },
4285   { "grub", 0, POPT_ARG_NONE, &configureGrub, 0,   { "grub", 0, POPT_ARG_NONE, &configureGrub, 0,
# Line 3803  int main(int argc, const char ** argv) { Line 4292  int main(int argc, const char ** argv) {
4292   { "initrd", 0, POPT_ARG_STRING, &newKernelInitrd, 0,   { "initrd", 0, POPT_ARG_STRING, &newKernelInitrd, 0,
4293      _("initrd image for the new kernel"), _("initrd-path") },      _("initrd image for the new kernel"), _("initrd-path") },
4294   { "extra-initrd", 'i', POPT_ARG_STRING, NULL, 'i',   { "extra-initrd", 'i', POPT_ARG_STRING, NULL, 'i',
4295      _("auxilliary initrd image for things other than the new kernel"), _("initrd-path") },      _("auxiliary initrd image for things other than the new kernel"), _("initrd-path") },
4296   { "lilo", 0, POPT_ARG_NONE, &configureLilo, 0,   { "lilo", 0, POPT_ARG_NONE, &configureLilo, 0,
4297      _("configure lilo bootloader") },      _("configure lilo bootloader") },
4298   { "make-default", 0, 0, &makeDefault, 0,   { "make-default", 0, 0, &makeDefault, 0,
# Line 3847  int main(int argc, const char ** argv) { Line 4336  int main(int argc, const char ** argv) {
4336    
4337      signal(SIGSEGV, traceback);      signal(SIGSEGV, traceback);
4338    
4339        int i = 0;
4340        for (int j = 1; j < argc; j++)
4341     i += strlen(argv[j]) + 1;
4342        saved_command_line = malloc(i);
4343        if (!saved_command_line) {
4344     fprintf(stderr, "grubby: %m\n");
4345     exit(1);
4346        }
4347        saved_command_line[0] = '\0';
4348        for (int j = 1; j < argc; j++) {
4349     strcat(saved_command_line, argv[j]);
4350     strncat(saved_command_line, j == argc -1 ? "" : " ", 1);
4351        }
4352    
4353      optCon = poptGetContext("grubby", argc, argv, options, 0);      optCon = poptGetContext("grubby", argc, argv, options, 0);
4354      poptReadDefaultConfig(optCon, 1);      poptReadDefaultConfig(optCon, 1);
4355    
# Line 3890  int main(int argc, const char ** argv) { Line 4393  int main(int argc, const char ** argv) {
4393   return 1;   return 1;
4394      } else if (configureGrub2) {      } else if (configureGrub2) {
4395   cfi = &grub2ConfigType;   cfi = &grub2ConfigType;
4396     if (envPath)
4397        cfi->envFile = envPath;
4398      } else if (configureLilo) {      } else if (configureLilo) {
4399   cfi = &liloConfigType;   cfi = &liloConfigType;
4400      } else if (configureGrub) {      } else if (configureGrub) {
# Line 3933  int main(int argc, const char ** argv) { Line 4438  int main(int argc, const char ** argv) {
4438      grubConfig = cfi->defaultConfig;      grubConfig = cfi->defaultConfig;
4439      }      }
4440    
4441      if (bootloaderProbe && (displayDefault || kernelInfo || newKernelVersion ||      if (bootloaderProbe && (displayDefault || kernelInfo ||
4442      newKernelPath || removeKernelPath || makeDefault ||      newKernelPath || removeKernelPath || makeDefault ||
4443      defaultKernel || displayDefaultIndex || displayDefaultTitle ||      defaultKernel || displayDefaultIndex || displayDefaultTitle ||
4444      (defaultIndex >= 0))) {      (defaultIndex >= 0))) {
# Line 3942  int main(int argc, const char ** argv) { Line 4447  int main(int argc, const char ** argv) {
4447   return 1;   return 1;
4448      }      }
4449    
4450      if ((displayDefault || kernelInfo) && (newKernelVersion || newKernelPath ||      if ((displayDefault || kernelInfo) && (newKernelPath ||
4451     removeKernelPath)) {     removeKernelPath)) {
4452   fprintf(stderr, _("grubby: --default-kernel and --info may not "   fprintf(stderr, _("grubby: --default-kernel and --info may not "
4453    "be used when adding or removing kernels\n"));    "be used when adding or removing kernels\n"));
# Line 3952  int main(int argc, const char ** argv) { Line 4457  int main(int argc, const char ** argv) {
4457      if (newKernelPath && !newKernelTitle) {      if (newKernelPath && !newKernelTitle) {
4458   fprintf(stderr, _("grubby: kernel title must be specified\n"));   fprintf(stderr, _("grubby: kernel title must be specified\n"));
4459   return 1;   return 1;
4460      } else if (!newKernelPath && (newKernelTitle  || copyDefault ||      } else if (!newKernelPath && (copyDefault ||
4461    (newKernelInitrd && !updateKernelPath)||    (newKernelInitrd && !updateKernelPath)||
4462    makeDefault || extraInitrdCount > 0)) {    makeDefault || extraInitrdCount > 0)) {
4463   fprintf(stderr, _("grubby: kernel path expected\n"));   fprintf(stderr, _("grubby: kernel path expected\n"));
# Line 4090  int main(int argc, const char ** argv) { Line 4595  int main(int argc, const char ** argv) {
4595   return 0;   return 0;
4596      }      }
4597    
4598        if (grubConfig == NULL) {
4599     printf("Could not find bootloader configuration file.\n");
4600     exit(1);
4601        }
4602    
4603      config = readConfig(grubConfig, cfi);      config = readConfig(grubConfig, cfi);
4604      if (!config) return 1;      if (!config) return 1;
4605    
# Line 4099  int main(int argc, const char ** argv) { Line 4609  int main(int argc, const char ** argv) {
4609          char * rootspec;          char * rootspec;
4610    
4611   if (config->defaultImage == -1) return 0;   if (config->defaultImage == -1) return 0;
4612     if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
4613     cfi->defaultIsSaved)
4614        config->defaultImage = 0;
4615   entry = findEntryByIndex(config, config->defaultImage);   entry = findEntryByIndex(config, config->defaultImage);
4616   if (!entry) return 0;   if (!entry) return 0;
4617   if (!suitableImage(entry, bootPrefix, 0, flags)) return 0;   if (!suitableImage(entry, bootPrefix, 0, flags)) return 0;
4618    
4619   line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines);   line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines);
4620   if (!line) return 0;   if (!line) return 0;
4621    
4622          rootspec = getRootSpecifier(line->elements[1].item);          rootspec = getRootSpecifier(line->elements[1].item);
# Line 4117  int main(int argc, const char ** argv) { Line 4630  int main(int argc, const char ** argv) {
4630   struct singleEntry * entry;   struct singleEntry * entry;
4631    
4632   if (config->defaultImage == -1) return 0;   if (config->defaultImage == -1) return 0;
4633     if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
4634     cfi->defaultIsSaved)
4635        config->defaultImage = 0;
4636   entry = findEntryByIndex(config, config->defaultImage);   entry = findEntryByIndex(config, config->defaultImage);
4637   if (!entry) return 0;   if (!entry) return 0;
4638    
# Line 4139  int main(int argc, const char ** argv) { Line 4655  int main(int argc, const char ** argv) {
4655    
4656      } else if (displayDefaultIndex) {      } else if (displayDefaultIndex) {
4657          if (config->defaultImage == -1) return 0;          if (config->defaultImage == -1) return 0;
4658     if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
4659     cfi->defaultIsSaved)
4660        config->defaultImage = 0;
4661          printf("%i\n", config->defaultImage);          printf("%i\n", config->defaultImage);
4662            return 0;
4663    
4664      } else if (kernelInfo)      } else if (kernelInfo)
4665   return displayInfo(config, kernelInfo, bootPrefix);   return displayInfo(config, kernelInfo, bootPrefix);
# Line 4157  int main(int argc, const char ** argv) { Line 4677  int main(int argc, const char ** argv) {
4677      if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,      if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,
4678                      removeArgs, newMBKernelArgs, removeMBKernelArgs)) return 1;                      removeArgs, newMBKernelArgs, removeMBKernelArgs)) return 1;
4679      if (updateKernelPath && newKernelInitrd) {      if (updateKernelPath && newKernelInitrd) {
4680              if (updateInitrd(config, updateKernelPath, bootPrefix,      if (newMBKernel) {
4681                               newKernelInitrd)) return 1;      if (addMBInitrd(config, newMBKernel, updateKernelPath,
4682     bootPrefix, newKernelInitrd,
4683     newKernelTitle))
4684        return 1;
4685        } else {
4686        if (updateInitrd(config, updateKernelPath, bootPrefix,
4687     newKernelInitrd, newKernelTitle))
4688     return 1;
4689        }
4690      }      }
4691      if (addNewKernel(config, template, bootPrefix, newKernelPath,      if (addNewKernel(config, template, bootPrefix, newKernelPath,
4692                       newKernelTitle, newKernelArgs, newKernelInitrd,                       newKernelTitle, newKernelArgs, newKernelInitrd,
4693                       (const char **)extraInitrds, extraInitrdCount,                       (const char **)extraInitrds, extraInitrdCount,
4694                       newMBKernel, newMBKernelArgs)) return 1;                       newMBKernel, newMBKernelArgs, newDevTreePath)) return 1;
4695            
4696    
4697      if (numEntries(config) == 0) {      if (numEntries(config) == 0) {

Legend:
Removed from v.1931  
changed lines
  Added in v.2972