Magellan Linux

Diff of /trunk/grubby/grubby.c

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

revision 2250 by niro, Mon Oct 21 13:56:22 2013 UTC revision 2983 by niro, Thu Jun 30 10:27:31 2016 UTC
# Line 60  int debug = 0; /* Currently just for tem Line 60  int debug = 0; /* Currently just for tem
60    
61  int isEfi = 0;  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;  char *saved_command_line = NULL;
70    
71  /* comments get lumped in with indention */  /* comments get lumped in with indention */
# Line 90  enum lineType_e { Line 96  enum lineType_e {
96      LT_SET_VARIABLE = 1 << 19,      LT_SET_VARIABLE = 1 << 19,
97      LT_KERNEL_EFI   = 1 << 20,      LT_KERNEL_EFI   = 1 << 20,
98      LT_INITRD_EFI   = 1 << 21,      LT_INITRD_EFI   = 1 << 21,
99      LT_UNKNOWN      = 1 << 22,      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 119  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 136  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;      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 157  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 176  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 203  struct configFileInfo grubConfigType = { Line 222  struct configFileInfo grubConfigType = {
222      .mbHyperFirst = 1,      .mbHyperFirst = 1,
223      .mbInitRdIsModule = 1,      .mbInitRdIsModule = 1,
224      .mbAllowExtraInitRds = 1,      .mbAllowExtraInitRds = 1,
225        .titlePosition = 1,
226  };  };
227    
228  struct keywordTypes grub2Keywords[] = {  struct keywordTypes grub2Keywords[] = {
# Line 215  struct keywordTypes grub2Keywords[] = { Line 235  struct keywordTypes grub2Keywords[] = {
235      { "fallback",   LT_FALLBACK,    ' ' },      { "fallback",   LT_FALLBACK,    ' ' },
236      { "linux",      LT_KERNEL,      ' ' },      { "linux",      LT_KERNEL,      ' ' },
237      { "linuxefi",   LT_KERNEL_EFI,  ' ' },      { "linuxefi",   LT_KERNEL_EFI,  ' ' },
238        { "linux16",    LT_KERNEL_16,   ' ' },
239      { "initrd",     LT_INITRD,      ' ', ' ' },      { "initrd",     LT_INITRD,      ' ', ' ' },
240      { "initrdefi",  LT_INITRD_EFI,  ' ', ' ' },      { "initrdefi",  LT_INITRD_EFI,  ' ', ' ' },
241        { "initrd16",   LT_INITRD_16,   ' ', ' ' },
242      { "module",     LT_MBMODULE,    ' ' },      { "module",     LT_MBMODULE,    ' ' },
243      { "kernel",     LT_HYPER,       ' ' },      { "kernel",     LT_HYPER,       ' ' },
244        { "devicetree", LT_DEVTREE,  ' ' },
245      { NULL, 0, 0 },      { NULL, 0, 0 },
246  };  };
247    
# Line 261  const char *grub2FindConfig(struct confi Line 284  const char *grub2FindConfig(struct confi
284      return configFiles[i];      return configFiles[i];
285  }  }
286    
287    /* kind of hacky.  It'll give the first 1024 bytes, ish. */
288    static char *grub2GetEnv(struct configFileInfo *info, char *name)
289    {
290        static char buf[1025];
291        char *s = NULL;
292        char *ret = NULL;
293        char *envFile = info->envFile ? info->envFile : "/boot/grub/grubenv";
294        int rc = asprintf(&s, "grub-editenv %s list | grep '^%s='", envFile, name);
295    
296        if (rc < 0)
297     return NULL;
298    
299        FILE *f = popen(s, "r");
300        if (!f)
301     goto out;
302    
303        memset(buf, '\0', sizeof (buf));
304        ret = fgets(buf, 1024, f);
305        pclose(f);
306    
307        if (ret) {
308     ret += strlen(name) + 1;
309     ret[strlen(ret) - 1] = '\0';
310        }
311        dbgPrintf("grub2GetEnv(%s): %s\n", name, ret);
312    out:
313        free(s);
314        return ret;
315    }
316    
317    static int sPopCount(const char *s, const char *c)
318    {
319        int ret = 0;
320        if (!s)
321     return -1;
322        for (int i = 0; s[i] != '\0'; i++)
323     for (int j = 0; c[j] != '\0'; j++)
324        if (s[i] == c[j])
325     ret++;
326        return ret;
327    }
328    
329    static char *shellEscape(const char *s)
330    {
331        int l = strlen(s) + sPopCount(s, "'") * 2;
332    
333        char *ret = calloc(l+1, sizeof (*ret));
334        if (!ret)
335     return NULL;
336        for (int i = 0, j = 0; s[i] != '\0'; i++, j++) {
337     if (s[i] == '\'')
338        ret[j++] = '\\';
339     ret[j] = s[i];
340        }
341        return ret;
342    }
343    
344    static void unquote(char *s)
345    {
346        int l = strlen(s);
347    
348        if ((s[l-1] == '\'' && s[0] == '\'') || (s[l-1] == '"' && s[0] == '"')) {
349     memmove(s, s+1, l-2);
350     s[l-2] = '\0';
351        }
352    }
353    
354    static int grub2SetEnv(struct configFileInfo *info, char *name, char *value)
355    {
356        char *s = NULL;
357        int rc = 0;
358        char *envFile = info->envFile ? info->envFile : "/boot/grub/grubenv";
359    
360        unquote(value);
361        value = shellEscape(value);
362        if (!value)
363        return -1;
364    
365        rc = asprintf(&s, "grub-editenv %s set '%s=%s'", envFile, name, value);
366        free(value);
367        if (rc <0)
368     return -1;
369    
370        dbgPrintf("grub2SetEnv(%s): %s\n", name, s);
371        rc = system(s);
372        free(s);
373        return rc;
374    }
375    
376    /* this is a gigantic hack to avoid clobbering grub2 variables... */
377    static int is_special_grub2_variable(const char *name)
378    {
379        if (!strcmp(name,"\"${next_entry}\""))
380     return 1;
381        if (!strcmp(name,"\"${prev_saved_entry}\""))
382     return 1;
383        return 0;
384    }
385    
386  int sizeOfSingleLine(struct singleLine * line) {  int sizeOfSingleLine(struct singleLine * line) {
387    int count = 0;    int count = 0;
388    
# Line 291  static int isquote(char q) Line 413  static int isquote(char q)
413  }  }
414    
415  static int iskernel(enum lineType_e type) {  static int iskernel(enum lineType_e type) {
416      return (type == LT_KERNEL || type == LT_KERNEL_EFI);      return (type == LT_KERNEL || type == LT_KERNEL_EFI || type == LT_KERNEL_16);
417  }  }
418    
419  static int isinitrd(enum lineType_e type) {  static int isinitrd(enum lineType_e type) {
420      return (type == LT_INITRD || type == LT_INITRD_EFI);      return (type == LT_INITRD || type == LT_INITRD_EFI || type == LT_INITRD_16);
421  }  }
422    
423  char *grub2ExtractTitle(struct singleLine * line) {  char *grub2ExtractTitle(struct singleLine * line) {
# Line 355  char *grub2ExtractTitle(struct singleLin Line 477  char *grub2ExtractTitle(struct singleLin
477    
478  struct configFileInfo grub2ConfigType = {  struct configFileInfo grub2ConfigType = {
479      .findConfig = grub2FindConfig,      .findConfig = grub2FindConfig,
480        .getEnv = grub2GetEnv,
481        .setEnv = grub2SetEnv,
482      .keywords = grub2Keywords,      .keywords = grub2Keywords,
483      .defaultIsIndex = 1,      .defaultIsIndex = 1,
484      .defaultSupportSaved = 1,      .defaultSupportSaved = 1,
# Line 459  struct keywordTypes extlinuxKeywords[] = Line 583  struct keywordTypes extlinuxKeywords[] =
583      { "initrd",    LT_INITRD,      ' ', ',' },      { "initrd",    LT_INITRD,      ' ', ',' },
584      { "append",    LT_KERNELARGS,  ' ' },      { "append",    LT_KERNELARGS,  ' ' },
585      { "prompt",     LT_UNKNOWN,     ' ' },      { "prompt",     LT_UNKNOWN,     ' ' },
586        { "fdt",        LT_DEVTREE,     ' ' },
587        { "fdtdir",     LT_DEVTREE,     ' ' },
588      { NULL,    0, 0 },      { NULL,    0, 0 },
589  };  };
590  int useextlinuxmenu;  int useextlinuxmenu;
# Line 469  struct configFileInfo eliloConfigType = Line 595  struct configFileInfo eliloConfigType =
595      .needsBootPrefix = 1,      .needsBootPrefix = 1,
596      .argsInQuotes = 1,      .argsInQuotes = 1,
597      .mbConcatArgs = 1,      .mbConcatArgs = 1,
598        .titlePosition = 1,
599  };  };
600    
601  struct configFileInfo liloConfigType = {  struct configFileInfo liloConfigType = {
# Line 477  struct configFileInfo liloConfigType = { Line 604  struct configFileInfo liloConfigType = {
604      .entryStart = LT_KERNEL,      .entryStart = LT_KERNEL,
605      .argsInQuotes = 1,      .argsInQuotes = 1,
606      .maxTitleLength = 15,      .maxTitleLength = 15,
607        .titlePosition = 1,
608  };  };
609    
610  struct configFileInfo yabootConfigType = {  struct configFileInfo yabootConfigType = {
# Line 487  struct configFileInfo yabootConfigType = Line 615  struct configFileInfo yabootConfigType =
615      .argsInQuotes = 1,      .argsInQuotes = 1,
616      .maxTitleLength = 15,      .maxTitleLength = 15,
617      .mbAllowExtraInitRds = 1,      .mbAllowExtraInitRds = 1,
618        .titlePosition = 1,
619  };  };
620    
621  struct configFileInfo siloConfigType = {  struct configFileInfo siloConfigType = {
# Line 496  struct configFileInfo siloConfigType = { Line 625  struct configFileInfo siloConfigType = {
625      .needsBootPrefix = 1,      .needsBootPrefix = 1,
626      .argsInQuotes = 1,      .argsInQuotes = 1,
627      .maxTitleLength = 15,      .maxTitleLength = 15,
628        .titlePosition = 1,
629  };  };
630    
631  struct configFileInfo ziplConfigType = {  struct configFileInfo ziplConfigType = {
# Line 514  struct configFileInfo extlinuxConfigType Line 644  struct configFileInfo extlinuxConfigType
644      .needsBootPrefix = 1,      .needsBootPrefix = 1,
645      .maxTitleLength = 255,      .maxTitleLength = 255,
646      .mbAllowExtraInitRds = 1,      .mbAllowExtraInitRds = 1,
647        .defaultIsUnquoted = 1,
648        .titlePosition = 1,
649  };  };
650    
651  struct grubConfig {  struct grubConfig {
# Line 534  struct singleEntry * findEntryByIndex(st Line 666  struct singleEntry * findEntryByIndex(st
666  struct singleEntry * findEntryByPath(struct grubConfig * cfg,  struct singleEntry * findEntryByPath(struct grubConfig * cfg,
667       const char * path, const char * prefix,       const char * path, const char * prefix,
668       int * index);       int * index);
669    struct singleEntry * findEntryByTitle(struct grubConfig * cfg, char *title,
670          int * index);
671  static int readFile(int fd, char ** bufPtr);  static int readFile(int fd, char ** bufPtr);
672  static void lineInit(struct singleLine * line);  static void lineInit(struct singleLine * line);
673  struct singleLine * lineDup(struct singleLine * line);  struct singleLine * lineDup(struct singleLine * line);
# Line 603  static enum lineType_e preferredLineType Line 737  static enum lineType_e preferredLineType
737      if (isEfi && cfi == &grub2ConfigType) {      if (isEfi && cfi == &grub2ConfigType) {
738   switch (type) {   switch (type) {
739   case LT_KERNEL:   case LT_KERNEL:
740      return LT_KERNEL_EFI;      return isEfiOnly ? LT_KERNEL : LT_KERNEL_EFI;
741   case LT_INITRD:   case LT_INITRD:
742      return LT_INITRD_EFI;      return isEfiOnly ? LT_INITRD : LT_INITRD_EFI;
743   default:   default:
744      return type;      return type;
745   }   }
746    #if defined(__i386__) || defined(__x86_64__)
747        } else if (cfi == &grub2ConfigType) {
748     switch (type) {
749     case LT_KERNEL:
750        return LT_KERNEL_16;
751     case LT_INITRD:
752        return LT_INITRD_16;
753     default:
754        return type;
755     }
756    #endif
757      }      }
758      return type;      return type;
759  }  }
# Line 689  static int isEntryStart(struct singleLin Line 834  static int isEntryStart(struct singleLin
834  }  }
835    
836  /* extract the title from within brackets (for zipl) */  /* extract the title from within brackets (for zipl) */
837  static char * extractTitle(struct singleLine * line) {  static char * extractTitle(struct grubConfig *cfg, struct singleLine * line) {
838      /* bracketed title... let's extract it (leaks a byte) */      /* bracketed title... let's extract it */
839      char * title;      char * title = NULL;
840      title = strdup(line->elements[0].item);      if (line->type == LT_TITLE) {
841      title++;   char *tmp = line->elements[cfg->cfi->titlePosition].item;
842      *(title + strlen(title) - 1) = '\0';   if (cfg->cfi->titleBracketed) {
843        tmp++;
844        title = strdup(tmp);
845        *(title + strlen(title) - 1) = '\0';
846     } else {
847        title = strdup(tmp);
848     }
849        } else if (line->type == LT_MENUENTRY)
850     title = strdup(line->elements[1].item);
851        else
852     return NULL;
853      return title;      return title;
854  }  }
855    
# Line 952  static int getNextLine(char ** bufPtr, s Line 1107  static int getNextLine(char ** bufPtr, s
1107      return 0;      return 0;
1108  }  }
1109    
1110    static int isnumber(const char *s)
1111    {
1112        int i;
1113        for (i = 0; s[i] != '\0'; i++)
1114     if (s[i] < '0' || s[i] > '9')
1115        return 0;
1116        return i;
1117    }
1118    
1119  static struct grubConfig * readConfig(const char * inName,  static struct grubConfig * readConfig(const char * inName,
1120        struct configFileInfo * cfi) {        struct configFileInfo * cfi) {
1121      int in;      int in;
# Line 1036  static struct grubConfig * readConfig(co Line 1200  static struct grubConfig * readConfig(co
1200      dbgPrintf("\n");      dbgPrintf("\n");
1201      struct keywordTypes *kwType = getKeywordByType(LT_DEFAULT, cfi);      struct keywordTypes *kwType = getKeywordByType(LT_DEFAULT, cfi);
1202      if (kwType && line->numElements == 3 &&      if (kwType && line->numElements == 3 &&
1203      !strcmp(line->elements[1].item, kwType->key)) {      !strcmp(line->elements[1].item, kwType->key) &&
1204        !is_special_grub2_variable(line->elements[2].item)) {
1205   dbgPrintf("Line sets default config\n");   dbgPrintf("Line sets default config\n");
1206   cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;   cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
1207   defaultLine = line;   defaultLine = line;
1208      }      }
  } else if (line->type == LT_DEFAULT && line->numElements == 2) {  
     cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;  
     defaultLine = line;  
1209    
1210          } else if (iskernel(line->type)) {          } else if (iskernel(line->type)) {
1211      /* if by some freak chance this is multiboot and the "module"      /* if by some freak chance this is multiboot and the "module"
1212       * lines came earlier in the template, make sure to use LT_HYPER       * lines came earlier in the template, make sure to use LT_HYPER
1213       * instead of LT_KERNEL now       * instead of LT_KERNEL now
1214       */       */
1215      if (entry->multiboot)      if (entry && entry->multiboot)
1216   line->type = LT_HYPER;   line->type = LT_HYPER;
1217    
1218          } else if (line->type == LT_MBMODULE) {          } else if (line->type == LT_MBMODULE) {
# Line 1076  static struct grubConfig * readConfig(co Line 1238  static struct grubConfig * readConfig(co
1238      cfg->fallbackImage = strtol(line->elements[1].item, &end, 10);      cfg->fallbackImage = strtol(line->elements[1].item, &end, 10);
1239      if (*end) cfg->fallbackImage = -1;      if (*end) cfg->fallbackImage = -1;
1240    
1241   } else if (line->type == LT_TITLE && line->numElements > 1) {   } else if ((line->type == LT_DEFAULT && cfi->defaultIsUnquoted) ||
1242      /* make the title a single argument (undoing our parsing) */                  (line->type == LT_TITLE && line->numElements > 1)) {
1243        /* make the title/default a single argument (undoing our parsing) */
1244      len = 0;      len = 0;
1245      for (int i = 1; i < line->numElements; i++) {      for (int i = 1; i < line->numElements; i++) {
1246   len += strlen(line->elements[i].item);   len += strlen(line->elements[i].item);
# Line 1184  static struct grubConfig * readConfig(co Line 1347  static struct grubConfig * readConfig(co
1347      }      }
1348   }   }
1349    
1350     if (line->type == LT_DEFAULT && line->numElements == 2) {
1351        cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
1352        defaultLine = line;
1353     }
1354    
1355   /* If we find a generic config option which should live at the   /* If we find a generic config option which should live at the
1356     top of the file, move it there. Old versions of grubby were     top of the file, move it there. Old versions of grubby were
1357     probably responsible for putting new images in the wrong     probably responsible for putting new images in the wrong
# Line 1241  static struct grubConfig * readConfig(co Line 1409  static struct grubConfig * readConfig(co
1409          if (defaultLine->numElements > 2 &&          if (defaultLine->numElements > 2 &&
1410      cfi->defaultSupportSaved &&      cfi->defaultSupportSaved &&
1411      !strncmp(defaultLine->elements[2].item,"\"${saved_entry}\"", 16)) {      !strncmp(defaultLine->elements[2].item,"\"${saved_entry}\"", 16)) {
1412      cfg->defaultImage = DEFAULT_SAVED_GRUB2;   cfg->cfi->defaultIsSaved = 1;
1413     cfg->defaultImage = DEFAULT_SAVED_GRUB2;
1414     if (cfg->cfi->getEnv) {
1415        char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry");
1416        if (defTitle) {
1417     int index = 0;
1418     if (isnumber(defTitle)) {
1419        index = atoi(defTitle);
1420        entry = findEntryByIndex(cfg, index);
1421     } else {
1422        entry = findEntryByTitle(cfg, defTitle, &index);
1423     }
1424     if (entry)
1425        cfg->defaultImage = index;
1426        }
1427     }
1428   } else if (cfi->defaultIsVariable) {   } else if (cfi->defaultIsVariable) {
1429      char *value = defaultLine->elements[2].item;      char *value = defaultLine->elements[2].item;
1430      while (*value && (*value == '"' || *value == '\'' ||      while (*value && (*value == '"' || *value == '\'' ||
# Line 1270  static struct grubConfig * readConfig(co Line 1453  static struct grubConfig * readConfig(co
1453                                  line->elements[1].item)) break;                                  line->elements[1].item)) break;
1454                  } else if (line) {                  } else if (line) {
1455                      if (!strcmp(defaultLine->elements[1].item,                      if (!strcmp(defaultLine->elements[1].item,
1456                                  extractTitle(line))) break;                                  extractTitle(cfg, line))) break;
1457                  }                  }
1458   i++;   i++;
1459   entry = NULL;   entry = NULL;
# Line 1282  static struct grubConfig * readConfig(co Line 1465  static struct grubConfig * readConfig(co
1465          cfg->defaultImage = -1;          cfg->defaultImage = -1;
1466      }      }
1467   }   }
1468        } else if (cfg->cfi->defaultIsSaved && cfg->cfi->getEnv) {
1469     char *defTitle = cfi->getEnv(cfg->cfi, "saved_entry");
1470     if (defTitle) {
1471        int index = 0;
1472        if (isnumber(defTitle)) {
1473     index = atoi(defTitle);
1474     entry = findEntryByIndex(cfg, index);
1475        } else {
1476     entry = findEntryByTitle(cfg, defTitle, &index);
1477        }
1478        if (entry)
1479     cfg->defaultImage = index;
1480     }
1481      } else {      } else {
1482          cfg->defaultImage = 0;          cfg->defaultImage = 0;
1483      }      }
# Line 1299  static void writeDefault(FILE * out, cha Line 1495  static void writeDefault(FILE * out, cha
1495    
1496      if (cfg->defaultImage == DEFAULT_SAVED)      if (cfg->defaultImage == DEFAULT_SAVED)
1497   fprintf(out, "%sdefault%ssaved\n", indent, separator);   fprintf(out, "%sdefault%ssaved\n", indent, separator);
1498      else if (cfg->defaultImage == DEFAULT_SAVED_GRUB2)      else if (cfg->cfi->defaultIsSaved) {
1499   fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);   fprintf(out, "%sset default=\"${saved_entry}\"\n", indent);
1500      else if (cfg->defaultImage > -1) {   if (cfg->defaultImage >= 0 && cfg->cfi->setEnv) {
1501        char *title;
1502        entry = findEntryByIndex(cfg, cfg->defaultImage);
1503        line = getLineByType(LT_MENUENTRY, entry->lines);
1504        if (!line)
1505     line = getLineByType(LT_TITLE, entry->lines);
1506        if (line) {
1507     title = extractTitle(cfg, line);
1508     if (title)
1509        cfg->cfi->setEnv(cfg->cfi, "saved_entry", title);
1510        }
1511     }
1512        } else if (cfg->defaultImage > -1) {
1513   if (cfg->cfi->defaultIsIndex) {   if (cfg->cfi->defaultIsIndex) {
1514      if (cfg->cfi->defaultIsVariable) {      if (cfg->cfi->defaultIsVariable) {
1515          fprintf(out, "%sset default=\"%d\"\n", indent,          fprintf(out, "%sset default=\"%d\"\n", indent,
# Line 1334  static void writeDefault(FILE * out, cha Line 1542  static void writeDefault(FILE * out, cha
1542              else if (line && (line->numElements == 1) &&              else if (line && (line->numElements == 1) &&
1543                       cfg->cfi->titleBracketed) {                       cfg->cfi->titleBracketed) {
1544   fprintf(out, "%sdefault%s%s\n", indent, separator,   fprintf(out, "%sdefault%s%s\n", indent, separator,
1545                          extractTitle(line));                          extractTitle(cfg, line));
1546              }              }
1547   }   }
1548      }      }
# Line 1404  static int writeConfig(struct grubConfig Line 1612  static int writeConfig(struct grubConfig
1612      while (line) {      while (line) {
1613          if (line->type == LT_SET_VARIABLE && defaultKw &&          if (line->type == LT_SET_VARIABLE && defaultKw &&
1614   line->numElements == 3 &&   line->numElements == 3 &&
1615   !strcmp(line->elements[1].item, defaultKw->key)) {   !strcmp(line->elements[1].item, defaultKw->key) &&
1616     !is_special_grub2_variable(line->elements[2].item)) {
1617      writeDefault(out, line->indent, line->elements[0].indent, cfg);      writeDefault(out, line->indent, line->elements[0].indent, cfg);
1618      needs &= ~MAIN_DEFAULT;      needs &= ~MAIN_DEFAULT;
1619   } else if (line->type == LT_DEFAULT) {   } else if (line->type == LT_DEFAULT) {
# Line 1640  int suitableImage(struct singleEntry * e Line 1849  int suitableImage(struct singleEntry * e
1849   return 0;   return 0;
1850      }      }
1851    
1852      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);
1853      if (!line) {      if (!line) {
1854   notSuitablePrintf(entry, 0, "no line found\n");   notSuitablePrintf(entry, 0, "no line found\n");
1855   return 0;   return 0;
# Line 1764  struct singleEntry * findEntryByPath(str Line 1973  struct singleEntry * findEntryByPath(str
1973   }   }
1974    
1975   indexVars[i + 1] = -1;   indexVars[i + 1] = -1;
1976    
1977   i = 0;   i = 0;
1978   if (index) {   if (index) {
1979      while (i < *index) i++;      while (i < *index) {
1980      if (indexVars[i] == -1) return NULL;   i++;
1981     if (indexVars[i] == -1) return NULL;
1982        }
1983   }   }
1984    
1985   entry = findEntryByIndex(config, indexVars[i]);   entry = findEntryByIndex(config, indexVars[i]);
1986   if (!entry) return NULL;   if (!entry) return NULL;
1987    
1988   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);
1989   if (!line) return NULL;   if (!line) return NULL;
1990    
1991   if (index) *index = indexVars[i];   if (index) *index = indexVars[i];
# Line 1825  struct singleEntry * findEntryByPath(str Line 2036  struct singleEntry * findEntryByPath(str
2036      for (line = entry->lines; line; line = line->next) {      for (line = entry->lines; line; line = line->next) {
2037   enum lineType_e ct = checkType;   enum lineType_e ct = checkType;
2038   if (entry->multiboot && checkType == LT_KERNEL)   if (entry->multiboot && checkType == LT_KERNEL)
2039      ct = LT_KERNEL|LT_KERNEL_EFI|LT_MBMODULE|LT_HYPER;      ct = LT_KERNEL|LT_KERNEL_EFI|LT_MBMODULE|LT_HYPER|LT_KERNEL_16;
2040   else if (checkType & LT_KERNEL)   else if (checkType & LT_KERNEL)
2041      ct = checkType | LT_KERNEL_EFI;      ct = checkType | LT_KERNEL_EFI | LT_KERNEL_16;
2042   line = getLineByType(ct, line);   line = getLineByType(ct, line);
2043   if (!line)   if (!line)
2044      break;  /* not found in this entry */      break;  /* not found in this entry */
# Line 1849  struct singleEntry * findEntryByPath(str Line 2060  struct singleEntry * findEntryByPath(str
2060       * non-Linux boot entries (could find netbsd etc, though, which is       * non-Linux boot entries (could find netbsd etc, though, which is
2061       * unfortunate)       * unfortunate)
2062       */       */
2063      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))
2064   break; /* found 'im! */   break; /* found 'im! */
2065   }   }
2066    
# Line 1859  struct singleEntry * findEntryByPath(str Line 2070  struct singleEntry * findEntryByPath(str
2070      return entry;      return entry;
2071  }  }
2072    
2073    struct singleEntry * findEntryByTitle(struct grubConfig * cfg, char *title,
2074          int * index) {
2075        struct singleEntry * entry;
2076        struct singleLine * line;
2077        int i;
2078        char * newtitle;
2079    
2080        for (i = 0, entry = cfg->entries; entry; entry = entry->next, i++) {
2081     if (index && i < *index)
2082        continue;
2083     line = getLineByType(LT_TITLE, entry->lines);
2084     if (!line)
2085        line = getLineByType(LT_MENUENTRY, entry->lines);
2086     if (!line)
2087        continue;
2088     newtitle = grub2ExtractTitle(line);
2089     if (!newtitle)
2090        continue;
2091     if (!strcmp(title, newtitle))
2092        break;
2093        }
2094    
2095        if (!entry)
2096     return NULL;
2097    
2098        if (index)
2099     *index = i;
2100        return entry;
2101    }
2102    
2103  struct singleEntry * findEntryByIndex(struct grubConfig * cfg, int index) {  struct singleEntry * findEntryByIndex(struct grubConfig * cfg, int index) {
2104      struct singleEntry * entry;      struct singleEntry * entry;
2105    
# Line 1881  struct singleEntry * findTemplate(struct Line 2122  struct singleEntry * findTemplate(struct
2122      struct singleEntry * entry, * entry2;      struct singleEntry * entry, * entry2;
2123      int index;      int index;
2124    
2125      if (cfg->defaultImage > -1) {      if (cfg->cfi->defaultIsSaved) {
2126     if (cfg->cfi->getEnv) {
2127        char *defTitle = cfg->cfi->getEnv(cfg->cfi, "saved_entry");
2128        if (defTitle) {
2129     int index = 0;
2130     if (isnumber(defTitle)) {
2131        index = atoi(defTitle);
2132        entry = findEntryByIndex(cfg, index);
2133     } else {
2134        entry = findEntryByTitle(cfg, defTitle, &index);
2135     }
2136     if (entry && suitableImage(entry, prefix, skipRemoved, flags)) {
2137        cfg->defaultImage = index;
2138        if (indexPtr)
2139     *indexPtr = index;
2140        return entry;
2141     }
2142        }
2143     }
2144        } else if (cfg->defaultImage > -1) {
2145   entry = findEntryByIndex(cfg, cfg->defaultImage);   entry = findEntryByIndex(cfg, cfg->defaultImage);
2146   if (entry && suitableImage(entry, prefix, skipRemoved, flags)) {   if (entry && suitableImage(entry, prefix, skipRemoved, flags)) {
2147      if (indexPtr) *indexPtr = cfg->defaultImage;      if (indexPtr) *indexPtr = cfg->defaultImage;
# Line 2035  void displayEntry(struct singleEntry * e Line 2295  void displayEntry(struct singleEntry * e
2295      struct singleLine * line;      struct singleLine * line;
2296      char * root = NULL;      char * root = NULL;
2297      int i;      int i;
2298        int j;
2299    
2300      printf("index=%d\n", index);      printf("index=%d\n", index);
2301    
2302      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);
2303      if (!line) {      if (!line) {
2304          printf("non linux entry\n");          printf("non linux entry\n");
2305          return;          return;
# Line 2103  void displayEntry(struct singleEntry * e Line 2364  void displayEntry(struct singleEntry * e
2364   printf("root=%s\n", s);   printf("root=%s\n", s);
2365      }      }
2366    
2367      line = getLineByType(LT_INITRD|LT_INITRD_EFI, entry->lines);      line = getLineByType(LT_INITRD|LT_INITRD_EFI|LT_INITRD_16, entry->lines);
2368    
2369      if (line && line->numElements >= 2) {      if (line && line->numElements >= 2) {
2370   if (!strncmp(prefix, line->elements[1].item, strlen(prefix)))   if (!strncmp(prefix, line->elements[1].item, strlen(prefix)))
# Line 2122  void displayEntry(struct singleEntry * e Line 2383  void displayEntry(struct singleEntry * e
2383      } else {      } else {
2384   char * title;   char * title;
2385   line = getLineByType(LT_MENUENTRY, entry->lines);   line = getLineByType(LT_MENUENTRY, entry->lines);
2386   title = grub2ExtractTitle(line);   if (line) {
2387   if (title)      title = grub2ExtractTitle(line);
2388      printf("title=%s\n", title);      if (title)
2389     printf("title=%s\n", title);
2390     }
2391        }
2392    
2393        for (j = 0, line = entry->lines; line; line = line->next) {
2394     if ((line->type & LT_MBMODULE) && line->numElements >= 2) {
2395        if (!strncmp(prefix, line->elements[1].item, strlen(prefix)))
2396     printf("mbmodule%d=", j);
2397        else
2398     printf("mbmodule%d=%s", j, prefix);
2399    
2400        for (i = 1; i < line->numElements; i++)
2401     printf("%s%s", line->elements[i].item, line->elements[i].indent);
2402        printf("\n");
2403        j++;
2404     }
2405      }      }
2406  }  }
2407    
# Line 2520  struct singleLine * addLineTmpl(struct s Line 2797  struct singleLine * addLineTmpl(struct s
2797   insertElement(newLine, val, 1, cfi);   insertElement(newLine, val, 1, cfi);
2798    
2799   /* but try to keep the rootspec from the template... sigh */   /* but try to keep the rootspec from the template... sigh */
2800   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)) {
2801      char * rootspec = getRootSpecifier(tmplLine->elements[1].item);      char * rootspec = getRootSpecifier(tmplLine->elements[1].item);
2802      if (rootspec != NULL) {      if (rootspec != NULL) {
2803   free(newLine->elements[1].item);   free(newLine->elements[1].item);
# Line 2890  int updateActualImage(struct grubConfig Line 3167  int updateActualImage(struct grubConfig
3167      firstElement = 2;      firstElement = 2;
3168    
3169   } else {   } else {
3170      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);
3171      if (!line) {      if (!line) {
3172   /* no LT_KERNEL or LT_MBMODULE in this entry? */   /* no LT_KERNEL or LT_MBMODULE in this entry? */
3173   continue;   continue;
# Line 3046  int updateImage(struct grubConfig * cfg, Line 3323  int updateImage(struct grubConfig * cfg,
3323      return rc;      return rc;
3324  }  }
3325    
3326    int addMBInitrd(struct grubConfig * cfg, const char *newMBKernel,
3327     const char * image, const char * prefix, const char * initrd,
3328     const char * title) {
3329        struct singleEntry * entry;
3330        struct singleLine * line, * kernelLine, *endLine = NULL;
3331        int index = 0;
3332    
3333        if (!image) return 0;
3334    
3335        for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {
3336            kernelLine = getLineByType(LT_MBMODULE, entry->lines);
3337            if (!kernelLine) continue;
3338    
3339     /* if title is supplied, the entry's title must match it. */
3340     if (title) {
3341        char *linetitle;
3342    
3343        line = getLineByType(LT_TITLE|LT_MENUENTRY, entry->lines);
3344        if (!line)
3345     continue;
3346    
3347        linetitle = extractTitle(cfg, line);
3348        if (!linetitle)
3349     continue;
3350        if (strcmp(title, linetitle)) {
3351     free(linetitle);
3352     continue;
3353        }
3354        free(linetitle);
3355     }
3356    
3357            if (prefix) {
3358                int prefixLen = strlen(prefix);
3359                if (!strncmp(initrd, prefix, prefixLen))
3360                    initrd += prefixLen;
3361            }
3362     endLine = getLineByType(LT_ENTRY_END, entry->lines);
3363     if (endLine)
3364        removeLine(entry, endLine);
3365            line = addLine(entry, cfg->cfi, preferredLineType(LT_MBMODULE,cfg->cfi),
3366     kernelLine->indent, initrd);
3367            if (!line)
3368        return 1;
3369     if (endLine) {
3370        line = addLine(entry, cfg->cfi, LT_ENTRY_END, "", NULL);
3371                if (!line)
3372     return 1;
3373     }
3374    
3375            break;
3376        }
3377    
3378        return 0;
3379    }
3380    
3381  int updateInitrd(struct grubConfig * cfg, const char * image,  int updateInitrd(struct grubConfig * cfg, const char * image,
3382                   const char * prefix, const char * initrd) {                   const char * prefix, const char * initrd, const char * title) {
3383      struct singleEntry * entry;      struct singleEntry * entry;
3384      struct singleLine * line, * kernelLine, *endLine = NULL;      struct singleLine * line, * kernelLine, *endLine = NULL;
3385      int index = 0;      int index = 0;
# Line 3055  int updateInitrd(struct grubConfig * cfg Line 3387  int updateInitrd(struct grubConfig * cfg
3387      if (!image) return 0;      if (!image) return 0;
3388    
3389      for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {      for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {
3390          kernelLine = getLineByType(LT_KERNEL|LT_KERNEL_EFI, entry->lines);          kernelLine = getLineByType(LT_KERNEL|LT_KERNEL_EFI|LT_KERNEL_16, entry->lines);
3391          if (!kernelLine) continue;          if (!kernelLine) continue;
3392    
3393          line = getLineByType(LT_INITRD|LT_INITRD_EFI, entry->lines);   /* if title is supplied, the entry's title must match it. */
3394     if (title) {
3395        char *linetitle;
3396    
3397        line = getLineByType(LT_TITLE|LT_MENUENTRY, entry->lines);
3398        if (!line)
3399     continue;
3400    
3401        linetitle = extractTitle(cfg, line);
3402        if (!linetitle)
3403     continue;
3404        if (strcmp(title, linetitle)) {
3405     free(linetitle);
3406     continue;
3407        }
3408        free(linetitle);
3409     }
3410    
3411            line = getLineByType(LT_INITRD|LT_INITRD_EFI|LT_INITRD_16, entry->lines);
3412          if (line)          if (line)
3413              removeLine(entry, line);              removeLine(entry, line);
3414          if (prefix) {          if (prefix) {
# Line 3069  int updateInitrd(struct grubConfig * cfg Line 3419  int updateInitrd(struct grubConfig * cfg
3419   endLine = getLineByType(LT_ENTRY_END, entry->lines);   endLine = getLineByType(LT_ENTRY_END, entry->lines);
3420   if (endLine)   if (endLine)
3421      removeLine(entry, endLine);      removeLine(entry, endLine);
3422          line = addLine(entry, cfg->cfi, preferredLineType(LT_INITRD, cfg->cfi),   enum lineType_e lt;
3423   kernelLine->indent, initrd);   switch(kernelLine->type) {
3424        case LT_KERNEL:
3425            lt = LT_INITRD;
3426     break;
3427        case LT_KERNEL_EFI:
3428            lt = LT_INITRD_EFI;
3429     break;
3430        case LT_KERNEL_16:
3431            lt = LT_INITRD_16;
3432     break;
3433        default:
3434            lt = preferredLineType(LT_INITRD, cfg->cfi);
3435     }
3436            line = addLine(entry, cfg->cfi, lt, kernelLine->indent, initrd);
3437          if (!line)          if (!line)
3438      return 1;      return 1;
3439   if (endLine) {   if (endLine) {
# Line 3429  int addNewKernel(struct grubConfig * con Line 3792  int addNewKernel(struct grubConfig * con
3792   const char * newKernelPath, const char * newKernelTitle,   const char * newKernelPath, const char * newKernelTitle,
3793   const char * newKernelArgs, const char * newKernelInitrd,   const char * newKernelArgs, const char * newKernelInitrd,
3794   const char ** extraInitrds, int extraInitrdCount,   const char ** extraInitrds, int extraInitrdCount,
3795                   const char * newMBKernel, const char * newMBKernelArgs) {                   const char * newMBKernel, const char * newMBKernelArgs,
3796     const char * newDevTreePath) {
3797      struct singleEntry * new;      struct singleEntry * new;
3798      struct singleLine * newLine = NULL, * tmplLine = NULL, * masterLine = NULL;      struct singleLine * newLine = NULL, * tmplLine = NULL, * masterLine = NULL;
3799      int needs;      int needs;
# Line 3470  int addNewKernel(struct grubConfig * con Line 3834  int addNewKernel(struct grubConfig * con
3834          needs |= NEED_MB;          needs |= NEED_MB;
3835          new->multiboot = 1;          new->multiboot = 1;
3836      }      }
3837        if (newDevTreePath && getKeywordByType(LT_DEVTREE, config->cfi))
3838     needs |= NEED_DEVTREE;
3839    
3840      if (template) {      if (template) {
3841   for (masterLine = template->lines;   for (masterLine = template->lines;
# Line 3655  int addNewKernel(struct grubConfig * con Line 4021  int addNewKernel(struct grubConfig * con
4021   newLine = addLineTmpl(new, tmplLine, newLine, NULL,   newLine = addLineTmpl(new, tmplLine, newLine, NULL,
4022   config->cfi);   config->cfi);
4023      }      }
4024        } else if (tmplLine->type == LT_DEVTREE &&
4025           tmplLine->numElements == 2 && newDevTreePath) {
4026            newLine = addLineTmpl(new, tmplLine, newLine,
4027          newDevTreePath + strlen(prefix),
4028          config->cfi);
4029     needs &= ~NEED_DEVTREE;
4030        } else if (tmplLine->type == LT_ENTRY_END && needs & NEED_DEVTREE) {
4031     const char *ndtp = newDevTreePath;
4032     if (!strncmp(newDevTreePath, prefix, strlen(prefix)))
4033        ndtp += strlen(prefix);
4034     newLine = addLine(new, config->cfi, LT_DEVTREE,
4035      config->secondaryIndent,
4036      ndtp);
4037     needs &= ~NEED_DEVTREE;
4038     newLine = addLineTmpl(new, tmplLine, newLine, NULL, config->cfi);
4039      } else {      } else {
4040   /* pass through other lines from the template */   /* pass through other lines from the template */
4041   newLine = addLineTmpl(new, tmplLine, newLine, NULL, config->cfi);   newLine = addLineTmpl(new, tmplLine, newLine, NULL, config->cfi);
# Line 3668  int addNewKernel(struct grubConfig * con Line 4049  int addNewKernel(struct grubConfig * con
4049   switch (config->cfi->entryStart) {   switch (config->cfi->entryStart) {
4050      case LT_KERNEL:      case LT_KERNEL:
4051      case LT_KERNEL_EFI:      case LT_KERNEL_EFI:
4052        case LT_KERNEL_16:
4053   if (new->multiboot && config->cfi->mbHyperFirst) {   if (new->multiboot && config->cfi->mbHyperFirst) {
4054      /* fall through to LT_HYPER */      /* fall through to LT_HYPER */
4055   } else {   } else {
# Line 3729  int addNewKernel(struct grubConfig * con Line 4111  int addNewKernel(struct grubConfig * con
4111   }   }
4112      }      }
4113    
4114        struct singleLine *endLine = NULL;
4115        endLine = getLineByType(LT_ENTRY_END, new->lines);
4116        if (endLine) {
4117        removeLine(new, endLine);
4118        needs |= NEED_END;
4119        }
4120    
4121      /* add the remainder of the lines, i.e. those that either      /* add the remainder of the lines, i.e. those that either
4122       * 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,
4123       * all the lines following the entryStart.       * all the lines following the entryStart.
# Line 3774  int addNewKernel(struct grubConfig * con Line 4163  int addNewKernel(struct grubConfig * con
4163   free(initrdVal);   free(initrdVal);
4164   needs &= ~NEED_INITRD;   needs &= ~NEED_INITRD;
4165      }      }
4166        if (needs & NEED_DEVTREE) {
4167     newLine = addLine(new, config->cfi, LT_DEVTREE,
4168      config->secondaryIndent,
4169      newDevTreePath);
4170     needs &= ~NEED_DEVTREE;
4171        }
4172    
4173        /* NEEDS_END must be last on bootloaders that need it... */
4174      if (needs & NEED_END) {      if (needs & NEED_END) {
4175   newLine = addLine(new, config->cfi, LT_ENTRY_END,   newLine = addLine(new, config->cfi, LT_ENTRY_END,
4176   config->secondaryIndent, NULL);   config->secondaryIndent, NULL);
# Line 3825  int main(int argc, const char ** argv) { Line 4222  int main(int argc, const char ** argv) {
4222      char * newKernelArgs = NULL;      char * newKernelArgs = NULL;
4223      char * newKernelInitrd = NULL;      char * newKernelInitrd = NULL;
4224      char * newKernelTitle = NULL;      char * newKernelTitle = NULL;
4225      char * newKernelVersion = NULL;      char * newDevTreePath = NULL;
4226      char * newMBKernel = NULL;      char * newMBKernel = NULL;
4227      char * newMBKernelArgs = NULL;      char * newMBKernelArgs = NULL;
4228      char * removeMBKernelArgs = NULL;      char * removeMBKernelArgs = NULL;
# Line 3835  int main(int argc, const char ** argv) { Line 4232  int main(int argc, const char ** argv) {
4232      char * removeArgs = NULL;      char * removeArgs = NULL;
4233      char * kernelInfo = NULL;      char * kernelInfo = NULL;
4234      char * extraInitrds[MAX_EXTRA_INITRDS] = { NULL };      char * extraInitrds[MAX_EXTRA_INITRDS] = { NULL };
4235        char * envPath = NULL;
4236      const char * chptr = NULL;      const char * chptr = NULL;
4237      struct configFileInfo * cfi = NULL;      struct configFileInfo * cfi = NULL;
4238      struct grubConfig * config;      struct grubConfig * config;
# Line 3882  int main(int argc, const char ** argv) { Line 4280  int main(int argc, const char ** argv) {
4280      _("display the index of the default kernel") },      _("display the index of the default kernel") },
4281   { "default-title", 0, 0, &displayDefaultTitle, 0,   { "default-title", 0, 0, &displayDefaultTitle, 0,
4282      _("display the title of the default kernel") },      _("display the title of the default kernel") },
4283     { "devtree", 0, POPT_ARG_STRING, &newDevTreePath, 0,
4284        _("device tree file for new stanza"), _("dtb-path") },
4285     { "devtreedir", 0, POPT_ARG_STRING, &newDevTreePath, 0,
4286        _("device tree directory for new stanza"), _("dtb-path") },
4287   { "elilo", 0, POPT_ARG_NONE, &configureELilo, 0,   { "elilo", 0, POPT_ARG_NONE, &configureELilo, 0,
4288      _("configure elilo bootloader") },      _("configure elilo bootloader") },
4289   { "efi", 0, POPT_ARG_NONE, &isEfi, 0,   { "efi", 0, POPT_ARG_NONE, &isEfi, 0,
4290      _("force grub2 stanzas to use efi") },      _("force grub2 stanzas to use efi") },
4291     { "env", 0, POPT_ARG_STRING, &envPath, 0,
4292        _("path for environment data"),
4293        _("path") },
4294   { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0,   { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0,
4295      _("configure extlinux bootloader (from syslinux)") },      _("configure extlinux bootloader (from syslinux)") },
4296   { "grub", 0, POPT_ARG_NONE, &configureGrub, 0,   { "grub", 0, POPT_ARG_NONE, &configureGrub, 0,
# Line 3999  int main(int argc, const char ** argv) { Line 4404  int main(int argc, const char ** argv) {
4404   return 1;   return 1;
4405      } else if (configureGrub2) {      } else if (configureGrub2) {
4406   cfi = &grub2ConfigType;   cfi = &grub2ConfigType;
4407     if (envPath)
4408        cfi->envFile = envPath;
4409      } else if (configureLilo) {      } else if (configureLilo) {
4410   cfi = &liloConfigType;   cfi = &liloConfigType;
4411      } else if (configureGrub) {      } else if (configureGrub) {
# Line 4042  int main(int argc, const char ** argv) { Line 4449  int main(int argc, const char ** argv) {
4449      grubConfig = cfi->defaultConfig;      grubConfig = cfi->defaultConfig;
4450      }      }
4451    
4452      if (bootloaderProbe && (displayDefault || kernelInfo || newKernelVersion ||      if (bootloaderProbe && (displayDefault || kernelInfo ||
4453      newKernelPath || removeKernelPath || makeDefault ||      newKernelPath || removeKernelPath || makeDefault ||
4454      defaultKernel || displayDefaultIndex || displayDefaultTitle ||      defaultKernel || displayDefaultIndex || displayDefaultTitle ||
4455      (defaultIndex >= 0))) {      (defaultIndex >= 0))) {
# Line 4051  int main(int argc, const char ** argv) { Line 4458  int main(int argc, const char ** argv) {
4458   return 1;   return 1;
4459      }      }
4460    
4461      if ((displayDefault || kernelInfo) && (newKernelVersion || newKernelPath ||      if ((displayDefault || kernelInfo) && (newKernelPath ||
4462     removeKernelPath)) {     removeKernelPath)) {
4463   fprintf(stderr, _("grubby: --default-kernel and --info may not "   fprintf(stderr, _("grubby: --default-kernel and --info may not "
4464    "be used when adding or removing kernels\n"));    "be used when adding or removing kernels\n"));
# Line 4061  int main(int argc, const char ** argv) { Line 4468  int main(int argc, const char ** argv) {
4468      if (newKernelPath && !newKernelTitle) {      if (newKernelPath && !newKernelTitle) {
4469   fprintf(stderr, _("grubby: kernel title must be specified\n"));   fprintf(stderr, _("grubby: kernel title must be specified\n"));
4470   return 1;   return 1;
4471      } else if (!newKernelPath && (newKernelTitle  || copyDefault ||      } else if (!newKernelPath && (copyDefault ||
4472    (newKernelInitrd && !updateKernelPath)||    (newKernelInitrd && !updateKernelPath)||
4473    makeDefault || extraInitrdCount > 0)) {    makeDefault || extraInitrdCount > 0)) {
4474   fprintf(stderr, _("grubby: kernel path expected\n"));   fprintf(stderr, _("grubby: kernel path expected\n"));
# Line 4213  int main(int argc, const char ** argv) { Line 4620  int main(int argc, const char ** argv) {
4620          char * rootspec;          char * rootspec;
4621    
4622   if (config->defaultImage == -1) return 0;   if (config->defaultImage == -1) return 0;
4623     if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
4624     cfi->defaultIsSaved)
4625        config->defaultImage = 0;
4626   entry = findEntryByIndex(config, config->defaultImage);   entry = findEntryByIndex(config, config->defaultImage);
4627   if (!entry) return 0;   if (!entry) return 0;
4628   if (!suitableImage(entry, bootPrefix, 0, flags)) return 0;   if (!suitableImage(entry, bootPrefix, 0, flags)) return 0;
4629    
4630   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);
4631   if (!line) return 0;   if (!line) return 0;
4632    
4633          rootspec = getRootSpecifier(line->elements[1].item);          rootspec = getRootSpecifier(line->elements[1].item);
# Line 4231  int main(int argc, const char ** argv) { Line 4641  int main(int argc, const char ** argv) {
4641   struct singleEntry * entry;   struct singleEntry * entry;
4642    
4643   if (config->defaultImage == -1) return 0;   if (config->defaultImage == -1) return 0;
4644     if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
4645     cfi->defaultIsSaved)
4646        config->defaultImage = 0;
4647   entry = findEntryByIndex(config, config->defaultImage);   entry = findEntryByIndex(config, config->defaultImage);
4648   if (!entry) return 0;   if (!entry) return 0;
4649    
# Line 4253  int main(int argc, const char ** argv) { Line 4666  int main(int argc, const char ** argv) {
4666    
4667      } else if (displayDefaultIndex) {      } else if (displayDefaultIndex) {
4668          if (config->defaultImage == -1) return 0;          if (config->defaultImage == -1) return 0;
4669     if (config->defaultImage == DEFAULT_SAVED_GRUB2 &&
4670     cfi->defaultIsSaved)
4671        config->defaultImage = 0;
4672          printf("%i\n", config->defaultImage);          printf("%i\n", config->defaultImage);
4673          return 0;          return 0;
4674    
# Line 4272  int main(int argc, const char ** argv) { Line 4688  int main(int argc, const char ** argv) {
4688      if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,      if (updateImage(config, updateKernelPath, bootPrefix, newKernelArgs,
4689                      removeArgs, newMBKernelArgs, removeMBKernelArgs)) return 1;                      removeArgs, newMBKernelArgs, removeMBKernelArgs)) return 1;
4690      if (updateKernelPath && newKernelInitrd) {      if (updateKernelPath && newKernelInitrd) {
4691              if (updateInitrd(config, updateKernelPath, bootPrefix,      if (newMBKernel) {
4692                               newKernelInitrd)) return 1;      if (addMBInitrd(config, newMBKernel, updateKernelPath,
4693     bootPrefix, newKernelInitrd,
4694     newKernelTitle))
4695        return 1;
4696        } else {
4697        if (updateInitrd(config, updateKernelPath, bootPrefix,
4698     newKernelInitrd, newKernelTitle))
4699     return 1;
4700        }
4701      }      }
4702      if (addNewKernel(config, template, bootPrefix, newKernelPath,      if (addNewKernel(config, template, bootPrefix, newKernelPath,
4703                       newKernelTitle, newKernelArgs, newKernelInitrd,                       newKernelTitle, newKernelArgs, newKernelInitrd,
4704                       (const char **)extraInitrds, extraInitrdCount,                       (const char **)extraInitrds, extraInitrdCount,
4705                       newMBKernel, newMBKernelArgs)) return 1;                       newMBKernel, newMBKernelArgs, newDevTreePath)) return 1;
4706            
4707    
4708      if (numEntries(config) == 0) {      if (numEntries(config) == 0) {

Legend:
Removed from v.2250  
changed lines
  Added in v.2983