Magellan Linux

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

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

revision 1859 by niro, Mon Jul 2 13:15:20 2012 UTC revision 2250 by niro, Mon Oct 21 13:56:22 2013 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    char *saved_command_line = NULL;
64    
65  /* comments get lumped in with indention */  /* comments get lumped in with indention */
66  struct lineElement {  struct lineElement {
67      char * item;      char * item;
# Line 82  enum lineType_e { Line 88  enum lineType_e {
88      LT_MENUENTRY    = 1 << 17,      LT_MENUENTRY    = 1 << 17,
89      LT_ENTRY_END    = 1 << 18,      LT_ENTRY_END    = 1 << 18,
90      LT_SET_VARIABLE = 1 << 19,      LT_SET_VARIABLE = 1 << 19,
91      LT_UNKNOWN      = 1 << 20,      LT_KERNEL_EFI   = 1 << 20,
92        LT_INITRD_EFI   = 1 << 21,
93        LT_UNKNOWN      = 1 << 22,
94  };  };
95    
96  struct singleLine {  struct singleLine {
# Line 134  struct configFileInfo { Line 142  struct configFileInfo {
142      findConfigFunc findConfig;      findConfigFunc findConfig;
143      writeLineFunc writeLine;      writeLineFunc writeLine;
144      struct keywordTypes * keywords;      struct keywordTypes * keywords;
145        int caseInsensitive;
146      int defaultIsIndex;      int defaultIsIndex;
147      int defaultIsVariable;      int defaultIsVariable;
148      int defaultSupportSaved;      int defaultSupportSaved;
# Line 205  struct keywordTypes grub2Keywords[] = { Line 214  struct keywordTypes grub2Keywords[] = {
214      { "default",    LT_DEFAULT,     ' ' },      { "default",    LT_DEFAULT,     ' ' },
215      { "fallback",   LT_FALLBACK,    ' ' },      { "fallback",   LT_FALLBACK,    ' ' },
216      { "linux",      LT_KERNEL,      ' ' },      { "linux",      LT_KERNEL,      ' ' },
217        { "linuxefi",   LT_KERNEL_EFI,  ' ' },
218      { "initrd",     LT_INITRD,      ' ', ' ' },      { "initrd",     LT_INITRD,      ' ', ' ' },
219        { "initrdefi",  LT_INITRD_EFI,  ' ', ' ' },
220      { "module",     LT_MBMODULE,    ' ' },      { "module",     LT_MBMODULE,    ' ' },
221      { "kernel",     LT_HYPER,       ' ' },      { "kernel",     LT_HYPER,       ' ' },
222      { NULL, 0, 0 },      { NULL, 0, 0 },
# Line 219  const char *grub2FindConfig(struct confi Line 230  const char *grub2FindConfig(struct confi
230      };      };
231      static int i = -1;      static int i = -1;
232      static const char *grub_cfg = "/boot/grub/grub.cfg";      static const char *grub_cfg = "/boot/grub/grub.cfg";
233        int rc = -1;
234    
235      if (i == -1) {      if (i == -1) {
236   for (i = 0; configFiles[i] != NULL; i++) {   for (i = 0; configFiles[i] != NULL; i++) {
237      dbgPrintf("Checking \"%s\": ", configFiles[i]);      dbgPrintf("Checking \"%s\": ", configFiles[i]);
238      if (!access(configFiles[i], R_OK)) {      if ((rc = access(configFiles[i], R_OK))) {
239     if (errno == EACCES) {
240        printf("Unable to access bootloader configuration file "
241           "\"%s\": %m\n", configFiles[i]);
242        exit(1);
243     }
244     continue;
245        } else {
246   dbgPrintf("found\n");   dbgPrintf("found\n");
247   return configFiles[i];   return configFiles[i];
248      }      }
# Line 271  static int isquote(char q) Line 290  static int isquote(char q)
290      return 0;      return 0;
291  }  }
292    
293    static int iskernel(enum lineType_e type) {
294        return (type == LT_KERNEL || type == LT_KERNEL_EFI);
295    }
296    
297    static int isinitrd(enum lineType_e type) {
298        return (type == LT_INITRD || type == LT_INITRD_EFI);
299    }
300    
301  char *grub2ExtractTitle(struct singleLine * line) {  char *grub2ExtractTitle(struct singleLine * line) {
302      char * current;      char * current;
303      char * current_indent;      char * current_indent;
# Line 482  struct configFileInfo ziplConfigType = { Line 509  struct configFileInfo ziplConfigType = {
509  struct configFileInfo extlinuxConfigType = {  struct configFileInfo extlinuxConfigType = {
510      .defaultConfig = "/boot/extlinux/extlinux.conf",      .defaultConfig = "/boot/extlinux/extlinux.conf",
511      .keywords = extlinuxKeywords,      .keywords = extlinuxKeywords,
512        .caseInsensitive = 1,
513      .entryStart = LT_TITLE,      .entryStart = LT_TITLE,
514      .needsBootPrefix = 1,      .needsBootPrefix = 1,
515      .maxTitleLength = 255,      .maxTitleLength = 255,
# Line 570  static char * sdupprintf(const char *for Line 598  static char * sdupprintf(const char *for
598      return buf;      return buf;
599  }  }
600    
601    static enum lineType_e preferredLineType(enum lineType_e type,
602     struct configFileInfo *cfi) {
603        if (isEfi && cfi == &grub2ConfigType) {
604     switch (type) {
605     case LT_KERNEL:
606        return LT_KERNEL_EFI;
607     case LT_INITRD:
608        return LT_INITRD_EFI;
609     default:
610        return type;
611     }
612        }
613        return type;
614    }
615    
616  static struct keywordTypes * getKeywordByType(enum lineType_e type,  static struct keywordTypes * getKeywordByType(enum lineType_e type,
617        struct configFileInfo * cfi) {        struct configFileInfo * cfi) {
618      for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) {      for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) {
# Line 603  static char * getuuidbydev(char *device) Line 646  static char * getuuidbydev(char *device)
646  static enum lineType_e getTypeByKeyword(char * keyword,  static enum lineType_e getTypeByKeyword(char * keyword,
647   struct configFileInfo * cfi) {   struct configFileInfo * cfi) {
648      for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) {      for (struct keywordTypes *kw = cfi->keywords; kw->key; kw++) {
649   if (!strcmp(keyword, kw->key))   if (cfi->caseInsensitive) {
650      return kw->type;      if (!strcasecmp(keyword, kw->key))
651                    return kw->type;
652     } else {
653        if (!strcmp(keyword, kw->key))
654            return kw->type;
655     }
656      }      }
657      return LT_UNKNOWN;      return LT_UNKNOWN;
658  }  }
# Line 918  static struct grubConfig * readConfig(co Line 966  static struct grubConfig * readConfig(co
966      int len;      int len;
967      char * buf;      char * buf;
968    
969      if (!strcmp(inName, "-")) {      if (inName == NULL) {
970            printf("Could not find bootloader configuration\n");
971            exit(1);
972        } else if (!strcmp(inName, "-")) {
973   in = 0;   in = 0;
974      } else {      } else {
975   if ((in = open(inName, O_RDONLY)) < 0) {   if ((in = open(inName, O_RDONLY)) < 0) {
# Line 994  static struct grubConfig * readConfig(co Line 1045  static struct grubConfig * readConfig(co
1045      cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;      cfg->flags &= ~GRUB_CONFIG_NO_DEFAULT;
1046      defaultLine = line;      defaultLine = line;
1047    
1048          } else if (line->type == LT_KERNEL) {          } else if (iskernel(line->type)) {
1049      /* if by some freak chance this is multiboot and the "module"      /* if by some freak chance this is multiboot and the "module"
1050       * lines came earlier in the template, make sure to use LT_HYPER       * lines came earlier in the template, make sure to use LT_HYPER
1051       * instead of LT_KERNEL now       * instead of LT_KERNEL now
# Line 1011  static struct grubConfig * readConfig(co Line 1062  static struct grubConfig * readConfig(co
1062      for (struct singleLine *l = entry->lines; l; l = l->next) {      for (struct singleLine *l = entry->lines; l; l = l->next) {
1063   if (l->type == LT_HYPER)   if (l->type == LT_HYPER)
1064      break;      break;
1065   else if (l->type == LT_KERNEL) {   else if (iskernel(l->type)) {
1066      l->type = LT_HYPER;      l->type = LT_HYPER;
1067      break;      break;
1068   }   }
# Line 1310  static int writeConfig(struct grubConfig Line 1361  static int writeConfig(struct grubConfig
1361    
1362      /* most likely the symlink is relative, so change our      /* most likely the symlink is relative, so change our
1363         directory to the dir of the symlink */         directory to the dir of the symlink */
1364              rc = chdir(dirname(outName));      char *dir = strdupa(outName);
1365        rc = chdir(dirname(dir));
1366      do {      do {
1367   buf = alloca(len + 1);   buf = alloca(len + 1);
1368   rc = readlink(basename(outName), buf, len);   rc = readlink(basename(outName), buf, len);
# Line 1497  static char *findDiskForRoot() Line 1549  static char *findDiskForRoot()
1549      return NULL;      return NULL;
1550  }  }
1551    
1552  void printEntry(struct singleEntry * entry) {  void printEntry(struct singleEntry * entry, FILE *f) {
1553      int i;      int i;
1554      struct singleLine * line;      struct singleLine * line;
1555    
1556      for (line = entry->lines; line; line = line->next) {      for (line = entry->lines; line; line = line->next) {
1557   fprintf(stderr, "DBG: %s", line->indent);   log_message(f, "DBG: %s", line->indent);
1558   for (i = 0; i < line->numElements; i++) {   for (i = 0; i < line->numElements; i++) {
1559      /* Need to handle this, because we strip the quotes from      /* Need to handle this, because we strip the quotes from
1560       * menuentry when read it. */       * menuentry when read it. */
1561      if (line->type == LT_MENUENTRY && i == 1) {      if (line->type == LT_MENUENTRY && i == 1) {
1562   if(!isquote(*line->elements[i].item))   if(!isquote(*line->elements[i].item))
1563      fprintf(stderr, "\'%s\'", line->elements[i].item);      log_message(f, "\'%s\'", line->elements[i].item);
1564   else   else
1565      fprintf(stderr, "%s", line->elements[i].item);      log_message(f, "%s", line->elements[i].item);
1566   fprintf(stderr, "%s", line->elements[i].indent);   log_message(f, "%s", line->elements[i].indent);
1567    
1568   continue;   continue;
1569      }      }
1570            
1571      fprintf(stderr, "%s%s",      log_message(f, "%s%s",
1572      line->elements[i].item, line->elements[i].indent);      line->elements[i].item, line->elements[i].indent);
1573   }   }
1574   fprintf(stderr, "\n");   log_message(f, "\n");
1575      }      }
1576  }  }
1577    
1578  void notSuitablePrintf(struct singleEntry * entry, const char *fmt, ...)  void notSuitablePrintf(struct singleEntry * entry, int okay, const char *fmt, ...)
1579  {  {
1580      va_list argp;      static int once;
1581        va_list argp, argq;
1582    
1583        va_start(argp, fmt);
1584    
1585        va_copy(argq, argp);
1586        if (!once) {
1587     log_time(NULL);
1588     log_message(NULL, "command line: %s\n", saved_command_line);
1589        }
1590        log_message(NULL, "DBG: Image entry %s: ", okay ? "succeeded" : "failed");
1591        log_vmessage(NULL, fmt, argq);
1592    
1593        printEntry(entry, NULL);
1594        va_end(argq);
1595    
1596      if (!debug)      if (!debug) {
1597     once = 1;
1598         va_end(argp);
1599   return;   return;
1600        }
1601    
1602      va_start(argp, fmt);      if (okay) {
1603     va_end(argp);
1604     return;
1605        }
1606    
1607        if (!once)
1608     log_message(stderr, "DBG: command line: %s\n", saved_command_line);
1609        once = 1;
1610      fprintf(stderr, "DBG: Image entry failed: ");      fprintf(stderr, "DBG: Image entry failed: ");
1611      vfprintf(stderr, fmt, argp);      vfprintf(stderr, fmt, argp);
1612      printEntry(entry);      printEntry(entry, stderr);
1613      va_end(argp);      va_end(argp);
1614  }  }
1615    
# Line 1560  int suitableImage(struct singleEntry * e Line 1636  int suitableImage(struct singleEntry * e
1636      char * rootdev;      char * rootdev;
1637    
1638      if (skipRemoved && entry->skip) {      if (skipRemoved && entry->skip) {
1639   notSuitablePrintf(entry, "marked to skip\n");   notSuitablePrintf(entry, 0, "marked to skip\n");
1640   return 0;   return 0;
1641      }      }
1642    
1643      line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines);      line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI, entry->lines);
1644      if (!line) {      if (!line) {
1645   notSuitablePrintf(entry, "no line found\n");   notSuitablePrintf(entry, 0, "no line found\n");
1646   return 0;   return 0;
1647      }      }
1648      if (line->numElements < 2) {      if (line->numElements < 2) {
1649   notSuitablePrintf(entry, "line has only %d elements\n",   notSuitablePrintf(entry, 0, "line has only %d elements\n",
1650      line->numElements);      line->numElements);
1651   return 0;   return 0;
1652      }      }
1653    
1654      if (flags & GRUBBY_BADIMAGE_OKAY) return 1;      if (flags & GRUBBY_BADIMAGE_OKAY) {
1655        notSuitablePrintf(entry, 1, "\n");
1656        return 1;
1657        }
1658    
1659      fullName = alloca(strlen(bootPrefix) +      fullName = alloca(strlen(bootPrefix) +
1660        strlen(line->elements[1].item) + 1);        strlen(line->elements[1].item) + 1);
# Line 1586  int suitableImage(struct singleEntry * e Line 1665  int suitableImage(struct singleEntry * e
1665      sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/",      sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/",
1666              line->elements[1].item + rootspec_offset);              line->elements[1].item + rootspec_offset);
1667      if (access(fullName, R_OK)) {      if (access(fullName, R_OK)) {
1668   notSuitablePrintf(entry, "access to %s failed\n", fullName);   notSuitablePrintf(entry, 0, "access to %s failed\n", fullName);
1669   return 0;   return 0;
1670      }      }
1671      for (i = 2; i < line->numElements; i++)      for (i = 2; i < line->numElements; i++)
# Line 1607  int suitableImage(struct singleEntry * e Line 1686  int suitableImage(struct singleEntry * e
1686    
1687              /* failed to find one */              /* failed to find one */
1688              if (!line) {              if (!line) {
1689   notSuitablePrintf(entry, "no line found\n");   notSuitablePrintf(entry, 0, "no line found\n");
1690   return 0;   return 0;
1691              }              }
1692    
# Line 1616  int suitableImage(struct singleEntry * e Line 1695  int suitableImage(struct singleEntry * e
1695      if (i < line->numElements)      if (i < line->numElements)
1696          dev = line->elements[i].item + 5;          dev = line->elements[i].item + 5;
1697      else {      else {
1698   notSuitablePrintf(entry, "no root= entry found\n");   notSuitablePrintf(entry, 0, "no root= entry found\n");
1699   /* it failed too...  can't find root= */   /* it failed too...  can't find root= */
1700          return 0;          return 0;
1701              }              }
# Line 1625  int suitableImage(struct singleEntry * e Line 1704  int suitableImage(struct singleEntry * e
1704    
1705      dev = getpathbyspec(dev);      dev = getpathbyspec(dev);
1706      if (!getpathbyspec(dev)) {      if (!getpathbyspec(dev)) {
1707          notSuitablePrintf(entry, "can't find blkid entry for %s\n", dev);          notSuitablePrintf(entry, 0, "can't find blkid entry for %s\n", dev);
1708          return 0;          return 0;
1709      } else      } else
1710   dev = getpathbyspec(dev);   dev = getpathbyspec(dev);
1711    
1712      rootdev = findDiskForRoot();      rootdev = findDiskForRoot();
1713      if (!rootdev) {      if (!rootdev) {
1714          notSuitablePrintf(entry, "can't find root device\n");          notSuitablePrintf(entry, 0, "can't find root device\n");
1715   return 0;   return 0;
1716      }      }
1717    
1718      if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) {      if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) {
1719          notSuitablePrintf(entry, "uuid missing: rootdev %s, dev %s\n",          notSuitablePrintf(entry, 0, "uuid missing: rootdev %s, dev %s\n",
1720   getuuidbydev(rootdev), getuuidbydev(dev));   getuuidbydev(rootdev), getuuidbydev(dev));
1721          free(rootdev);          free(rootdev);
1722          return 0;          return 0;
1723      }      }
1724    
1725      if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) {      if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) {
1726          notSuitablePrintf(entry, "uuid mismatch: rootdev %s, dev %s\n",          notSuitablePrintf(entry, 0, "uuid mismatch: rootdev %s, dev %s\n",
1727   getuuidbydev(rootdev), getuuidbydev(dev));   getuuidbydev(rootdev), getuuidbydev(dev));
1728   free(rootdev);   free(rootdev);
1729          return 0;          return 0;
1730      }      }
1731    
1732      free(rootdev);      free(rootdev);
1733        notSuitablePrintf(entry, 1, "\n");
1734    
1735      return 1;      return 1;
1736  }  }
# Line 1694  struct singleEntry * findEntryByPath(str Line 1774  struct singleEntry * findEntryByPath(str
1774   entry = findEntryByIndex(config, indexVars[i]);   entry = findEntryByIndex(config, indexVars[i]);
1775   if (!entry) return NULL;   if (!entry) return NULL;
1776    
1777   line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines);   line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI, entry->lines);
1778   if (!line) return NULL;   if (!line) return NULL;
1779    
1780   if (index) *index = indexVars[i];   if (index) *index = indexVars[i];
# Line 1743  struct singleEntry * findEntryByPath(str Line 1823  struct singleEntry * findEntryByPath(str
1823    
1824      /* check all the lines matching checkType */      /* check all the lines matching checkType */
1825      for (line = entry->lines; line; line = line->next) {      for (line = entry->lines; line; line = line->next) {
1826   line = getLineByType(entry->multiboot && checkType == LT_KERNEL ?   enum lineType_e ct = checkType;
1827       LT_KERNEL|LT_MBMODULE|LT_HYPER :   if (entry->multiboot && checkType == LT_KERNEL)
1828       checkType, line);      ct = LT_KERNEL|LT_KERNEL_EFI|LT_MBMODULE|LT_HYPER;
1829   if (!line) break;  /* not found in this entry */   else if (checkType & LT_KERNEL)
1830        ct = checkType | LT_KERNEL_EFI;
1831     line = getLineByType(ct, line);
1832     if (!line)
1833        break;  /* not found in this entry */
1834    
1835   if (line && line->type != LT_MENUENTRY &&   if (line && line->type != LT_MENUENTRY &&
1836   line->numElements >= 2) {   line->numElements >= 2) {
# Line 1765  struct singleEntry * findEntryByPath(str Line 1849  struct singleEntry * findEntryByPath(str
1849       * non-Linux boot entries (could find netbsd etc, though, which is       * non-Linux boot entries (could find netbsd etc, though, which is
1850       * unfortunate)       * unfortunate)
1851       */       */
1852      if (line && getLineByType(LT_KERNEL|LT_HYPER, entry->lines))      if (line && getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI, entry->lines))
1853   break; /* found 'im! */   break; /* found 'im! */
1854   }   }
1855    
# Line 1954  void displayEntry(struct singleEntry * e Line 2038  void displayEntry(struct singleEntry * e
2038    
2039      printf("index=%d\n", index);      printf("index=%d\n", index);
2040    
2041      line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines);      line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI, entry->lines);
2042      if (!line) {      if (!line) {
2043          printf("non linux entry\n");          printf("non linux entry\n");
2044          return;          return;
# Line 2019  void displayEntry(struct singleEntry * e Line 2103  void displayEntry(struct singleEntry * e
2103   printf("root=%s\n", s);   printf("root=%s\n", s);
2104      }      }
2105    
2106      line = getLineByType(LT_INITRD, entry->lines);      line = getLineByType(LT_INITRD|LT_INITRD_EFI, entry->lines);
2107    
2108      if (line && line->numElements >= 2) {      if (line && line->numElements >= 2) {
2109   if (!strncmp(prefix, line->elements[1].item, strlen(prefix)))   if (!strncmp(prefix, line->elements[1].item, strlen(prefix)))
# Line 2420  struct singleLine * addLineTmpl(struct s Line 2504  struct singleLine * addLineTmpl(struct s
2504  {  {
2505      struct singleLine * newLine = lineDup(tmplLine);      struct singleLine * newLine = lineDup(tmplLine);
2506    
2507        if (isEfi && cfi == &grub2ConfigType) {
2508     enum lineType_e old = newLine->type;
2509     newLine->type = preferredLineType(newLine->type, cfi);
2510     if (old != newLine->type)
2511        newLine->elements[0].item = getKeyByType(newLine->type, cfi);
2512        }
2513    
2514      if (val) {      if (val) {
2515   /* override the inherited value with our own.   /* override the inherited value with our own.
2516   * 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 2429  struct singleLine * addLineTmpl(struct s Line 2520  struct singleLine * addLineTmpl(struct s
2520   insertElement(newLine, val, 1, cfi);   insertElement(newLine, val, 1, cfi);
2521    
2522   /* but try to keep the rootspec from the template... sigh */   /* but try to keep the rootspec from the template... sigh */
2523   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)) {
2524      char * rootspec = getRootSpecifier(tmplLine->elements[1].item);      char * rootspec = getRootSpecifier(tmplLine->elements[1].item);
2525      if (rootspec != NULL) {      if (rootspec != NULL) {
2526   free(newLine->elements[1].item);   free(newLine->elements[1].item);
# Line 2466  struct singleLine *  addLine(struct sing Line 2557  struct singleLine *  addLine(struct sing
2557      /* 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
2558       * stack since it calls addLineTmpl which will make copies.       * stack since it calls addLineTmpl which will make copies.
2559       */       */
   
2560      if (type == LT_TITLE && cfi->titleBracketed) {      if (type == LT_TITLE && cfi->titleBracketed) {
2561   /* we're doing a bracketed title (zipl) */   /* we're doing a bracketed title (zipl) */
2562   tmpl.type = type;   tmpl.type = type;
# Line 2800  int updateActualImage(struct grubConfig Line 2890  int updateActualImage(struct grubConfig
2890      firstElement = 2;      firstElement = 2;
2891    
2892   } else {   } else {
2893      line = getLineByType(LT_KERNEL|LT_MBMODULE, entry->lines);      line = getLineByType(LT_KERNEL|LT_MBMODULE|LT_KERNEL_EFI, entry->lines);
2894      if (!line) {      if (!line) {
2895   /* no LT_KERNEL or LT_MBMODULE in this entry? */   /* no LT_KERNEL or LT_MBMODULE in this entry? */
2896   continue;   continue;
# Line 2965  int updateInitrd(struct grubConfig * cfg Line 3055  int updateInitrd(struct grubConfig * cfg
3055      if (!image) return 0;      if (!image) return 0;
3056    
3057      for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {      for (; (entry = findEntryByPath(cfg, image, prefix, &index)); index++) {
3058          kernelLine = getLineByType(LT_KERNEL, entry->lines);          kernelLine = getLineByType(LT_KERNEL|LT_KERNEL_EFI, entry->lines);
3059          if (!kernelLine) continue;          if (!kernelLine) continue;
3060    
3061          line = getLineByType(LT_INITRD, entry->lines);          line = getLineByType(LT_INITRD|LT_INITRD_EFI, entry->lines);
3062          if (line)          if (line)
3063              removeLine(entry, line);              removeLine(entry, line);
3064          if (prefix) {          if (prefix) {
# Line 2979  int updateInitrd(struct grubConfig * cfg Line 3069  int updateInitrd(struct grubConfig * cfg
3069   endLine = getLineByType(LT_ENTRY_END, entry->lines);   endLine = getLineByType(LT_ENTRY_END, entry->lines);
3070   if (endLine)   if (endLine)
3071      removeLine(entry, endLine);      removeLine(entry, endLine);
3072          line = addLine(entry, cfg->cfi, LT_INITRD, kernelLine->indent, initrd);          line = addLine(entry, cfg->cfi, preferredLineType(LT_INITRD, cfg->cfi),
3073     kernelLine->indent, initrd);
3074          if (!line)          if (!line)
3075      return 1;      return 1;
3076   if (endLine) {   if (endLine) {
# Line 3392  int addNewKernel(struct grubConfig * con Line 3483  int addNewKernel(struct grubConfig * con
3483      while (*chptr && isspace(*chptr)) chptr++;      while (*chptr && isspace(*chptr)) chptr++;
3484      if (*chptr == '#') continue;      if (*chptr == '#') continue;
3485    
3486      if (tmplLine->type == LT_KERNEL &&      if (iskernel(tmplLine->type) && tmplLine->numElements >= 2) {
     tmplLine->numElements >= 2) {  
3487   if (!template->multiboot && (needs & NEED_MB)) {   if (!template->multiboot && (needs & NEED_MB)) {
3488      /* it's not a multiboot template and this is the kernel      /* it's not a multiboot template and this is the kernel
3489       * line.  Try to be intelligent about inserting the       * line.  Try to be intelligent about inserting the
# Line 3470  int addNewKernel(struct grubConfig * con Line 3560  int addNewKernel(struct grubConfig * con
3560      /* template is multi but new is not,      /* template is multi but new is not,
3561       * insert the kernel in the first module slot       * insert the kernel in the first module slot
3562       */       */
3563      tmplLine->type = LT_KERNEL;      tmplLine->type = preferredLineType(LT_KERNEL, config->cfi);
3564      free(tmplLine->elements[0].item);      free(tmplLine->elements[0].item);
3565      tmplLine->elements[0].item =      tmplLine->elements[0].item =
3566   strdup(getKeywordByType(LT_KERNEL, config->cfi)->key);   strdup(getKeywordByType(tmplLine->type,
3567     config->cfi)->key);
3568      newLine = addLineTmpl(new, tmplLine, newLine,      newLine = addLineTmpl(new, tmplLine, newLine,
3569    newKernelPath + strlen(prefix), config->cfi);    newKernelPath + strlen(prefix),
3570      config->cfi);
3571      needs &= ~NEED_KERNEL;      needs &= ~NEED_KERNEL;
3572   } else if (needs & NEED_INITRD) {   } else if (needs & NEED_INITRD) {
3573      char *initrdVal;      char *initrdVal;
3574      /* template is multi but new is not,      /* template is multi but new is not,
3575       * insert the initrd in the second module slot       * insert the initrd in the second module slot
3576       */       */
3577      tmplLine->type = LT_INITRD;      tmplLine->type = preferredLineType(LT_INITRD, config->cfi);
3578      free(tmplLine->elements[0].item);      free(tmplLine->elements[0].item);
3579      tmplLine->elements[0].item =      tmplLine->elements[0].item =
3580   strdup(getKeywordByType(LT_INITRD, config->cfi)->key);   strdup(getKeywordByType(tmplLine->type,
3581     config->cfi)->key);
3582      initrdVal = getInitrdVal(config, prefix, tmplLine, newKernelInitrd, extraInitrds, extraInitrdCount);      initrdVal = getInitrdVal(config, prefix, tmplLine, newKernelInitrd, extraInitrds, extraInitrdCount);
3583      newLine = addLineTmpl(new, tmplLine, newLine, initrdVal, config->cfi);      newLine = addLineTmpl(new, tmplLine, newLine, initrdVal, config->cfi);
3584      free(initrdVal);      free(initrdVal);
3585      needs &= ~NEED_INITRD;      needs &= ~NEED_INITRD;
3586   }   }
3587    
3588      } else if (tmplLine->type == LT_INITRD &&      } else if (isinitrd(tmplLine->type) && tmplLine->numElements >= 2) {
        tmplLine->numElements >= 2) {  
3589   if (needs & NEED_INITRD &&   if (needs & NEED_INITRD &&
3590      new->multiboot && !template->multiboot &&      new->multiboot && !template->multiboot &&
3591      config->cfi->mbInitRdIsModule) {      config->cfi->mbInitRdIsModule) {
# Line 3547  int addNewKernel(struct grubConfig * con Line 3639  int addNewKernel(struct grubConfig * con
3639      static const char *prefix = "'Loading ";      static const char *prefix = "'Loading ";
3640      if (tmplLine->numElements > 1 &&      if (tmplLine->numElements > 1 &&
3641      strstr(tmplLine->elements[1].item, prefix) &&      strstr(tmplLine->elements[1].item, prefix) &&
3642      masterLine->next && masterLine->next->type == LT_KERNEL) {      masterLine->next &&
3643        iskernel(masterLine->next->type)) {
3644   char *newTitle = malloc(strlen(prefix) +   char *newTitle = malloc(strlen(prefix) +
3645   strlen(newKernelTitle) + 2);   strlen(newKernelTitle) + 2);
3646    
# Line 3574  int addNewKernel(struct grubConfig * con Line 3667  int addNewKernel(struct grubConfig * con
3667   */   */
3668   switch (config->cfi->entryStart) {   switch (config->cfi->entryStart) {
3669      case LT_KERNEL:      case LT_KERNEL:
3670        case LT_KERNEL_EFI:
3671   if (new->multiboot && config->cfi->mbHyperFirst) {   if (new->multiboot && config->cfi->mbHyperFirst) {
3672      /* fall through to LT_HYPER */      /* fall through to LT_HYPER */
3673   } else {   } else {
3674      newLine = addLine(new, config->cfi, LT_KERNEL,      newLine = addLine(new, config->cfi,
3675              preferredLineType(LT_KERNEL, config->cfi),
3676        config->primaryIndent,        config->primaryIndent,
3677        newKernelPath + strlen(prefix));        newKernelPath + strlen(prefix));
3678      needs &= ~NEED_KERNEL;      needs &= ~NEED_KERNEL;
# Line 3653  int addNewKernel(struct grubConfig * con Line 3748  int addNewKernel(struct grubConfig * con
3748      if (needs & NEED_KERNEL) {      if (needs & NEED_KERNEL) {
3749   newLine = addLine(new, config->cfi,   newLine = addLine(new, config->cfi,
3750    (new->multiboot && getKeywordByType(LT_MBMODULE,    (new->multiboot && getKeywordByType(LT_MBMODULE,
3751        config->cfi)) ?        config->cfi))
3752    LT_MBMODULE : LT_KERNEL,     ? LT_MBMODULE
3753     : preferredLineType(LT_KERNEL, config->cfi),
3754    config->secondaryIndent,    config->secondaryIndent,
3755    newKernelPath + strlen(prefix));    newKernelPath + strlen(prefix));
3756   needs &= ~NEED_KERNEL;   needs &= ~NEED_KERNEL;
# Line 3670  int addNewKernel(struct grubConfig * con Line 3766  int addNewKernel(struct grubConfig * con
3766   initrdVal = getInitrdVal(config, prefix, NULL, newKernelInitrd, extraInitrds, extraInitrdCount);   initrdVal = getInitrdVal(config, prefix, NULL, newKernelInitrd, extraInitrds, extraInitrdCount);
3767   newLine = addLine(new, config->cfi,   newLine = addLine(new, config->cfi,
3768    (new->multiboot && getKeywordByType(LT_MBMODULE,    (new->multiboot && getKeywordByType(LT_MBMODULE,
3769        config->cfi)) ?        config->cfi))
3770    LT_MBMODULE : LT_INITRD,     ? LT_MBMODULE
3771       : preferredLineType(LT_INITRD, config->cfi),
3772    config->secondaryIndent,    config->secondaryIndent,
3773    initrdVal);    initrdVal);
3774   free(initrdVal);   free(initrdVal);
# Line 3703  static void traceback(int signum) Line 3800  static void traceback(int signum)
3800      memset(array, '\0', sizeof (array));      memset(array, '\0', sizeof (array));
3801      size = backtrace(array, 40);      size = backtrace(array, 40);
3802    
3803      fprintf(stderr, "grubby recieved SIGSEGV!  Backtrace (%ld):\n",      fprintf(stderr, "grubby received SIGSEGV!  Backtrace (%ld):\n",
3804              (unsigned long)size);              (unsigned long)size);
3805      backtrace_symbols_fd(array, size, STDERR_FILENO);      backtrace_symbols_fd(array, size, STDERR_FILENO);
3806      exit(1);      exit(1);
# Line 3787  int main(int argc, const char ** argv) { Line 3884  int main(int argc, const char ** argv) {
3884      _("display the title of the default kernel") },      _("display the title of the default kernel") },
3885   { "elilo", 0, POPT_ARG_NONE, &configureELilo, 0,   { "elilo", 0, POPT_ARG_NONE, &configureELilo, 0,
3886      _("configure elilo bootloader") },      _("configure elilo bootloader") },
3887     { "efi", 0, POPT_ARG_NONE, &isEfi, 0,
3888        _("force grub2 stanzas to use efi") },
3889   { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0,   { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0,
3890      _("configure extlinux bootloader (from syslinux)") },      _("configure extlinux bootloader (from syslinux)") },
3891   { "grub", 0, POPT_ARG_NONE, &configureGrub, 0,   { "grub", 0, POPT_ARG_NONE, &configureGrub, 0,
# Line 3799  int main(int argc, const char ** argv) { Line 3898  int main(int argc, const char ** argv) {
3898   { "initrd", 0, POPT_ARG_STRING, &newKernelInitrd, 0,   { "initrd", 0, POPT_ARG_STRING, &newKernelInitrd, 0,
3899      _("initrd image for the new kernel"), _("initrd-path") },      _("initrd image for the new kernel"), _("initrd-path") },
3900   { "extra-initrd", 'i', POPT_ARG_STRING, NULL, 'i',   { "extra-initrd", 'i', POPT_ARG_STRING, NULL, 'i',
3901      _("auxilliary initrd image for things other than the new kernel"), _("initrd-path") },      _("auxiliary initrd image for things other than the new kernel"), _("initrd-path") },
3902   { "lilo", 0, POPT_ARG_NONE, &configureLilo, 0,   { "lilo", 0, POPT_ARG_NONE, &configureLilo, 0,
3903      _("configure lilo bootloader") },      _("configure lilo bootloader") },
3904   { "make-default", 0, 0, &makeDefault, 0,   { "make-default", 0, 0, &makeDefault, 0,
# Line 3843  int main(int argc, const char ** argv) { Line 3942  int main(int argc, const char ** argv) {
3942    
3943      signal(SIGSEGV, traceback);      signal(SIGSEGV, traceback);
3944    
3945        int i = 0;
3946        for (int j = 1; j < argc; j++)
3947     i += strlen(argv[j]) + 1;
3948        saved_command_line = malloc(i);
3949        if (!saved_command_line) {
3950     fprintf(stderr, "grubby: %m\n");
3951     exit(1);
3952        }
3953        saved_command_line[0] = '\0';
3954        for (int j = 1; j < argc; j++) {
3955     strcat(saved_command_line, argv[j]);
3956     strncat(saved_command_line, j == argc -1 ? "" : " ", 1);
3957        }
3958    
3959      optCon = poptGetContext("grubby", argc, argv, options, 0);      optCon = poptGetContext("grubby", argc, argv, options, 0);
3960      poptReadDefaultConfig(optCon, 1);      poptReadDefaultConfig(optCon, 1);
3961    
# Line 4069  int main(int argc, const char ** argv) { Line 4182  int main(int argc, const char ** argv) {
4182      if (!yconfig)      if (!yconfig)
4183   yrc = 1;   yrc = 1;
4184      else      else
4185   yrc = checkForYaboot(lconfig);   yrc = checkForYaboot(yconfig);
4186   }   }
4187    
4188   if (lrc == 1 || grc == 1 || gr2c == 1 || extrc == 1 || yrc == 1 ||   if (lrc == 1 || grc == 1 || gr2c == 1 || extrc == 1 || yrc == 1 ||
# Line 4086  int main(int argc, const char ** argv) { Line 4199  int main(int argc, const char ** argv) {
4199   return 0;   return 0;
4200      }      }
4201    
4202        if (grubConfig == NULL) {
4203     printf("Could not find bootloader configuration file.\n");
4204     exit(1);
4205        }
4206    
4207      config = readConfig(grubConfig, cfi);      config = readConfig(grubConfig, cfi);
4208      if (!config) return 1;      if (!config) return 1;
4209    
# Line 4099  int main(int argc, const char ** argv) { Line 4217  int main(int argc, const char ** argv) {
4217   if (!entry) return 0;   if (!entry) return 0;
4218   if (!suitableImage(entry, bootPrefix, 0, flags)) return 0;   if (!suitableImage(entry, bootPrefix, 0, flags)) return 0;
4219    
4220   line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines);   line = getLineByType(LT_KERNEL|LT_HYPER|LT_KERNEL_EFI, entry->lines);
4221   if (!line) return 0;   if (!line) return 0;
4222    
4223          rootspec = getRootSpecifier(line->elements[1].item);          rootspec = getRootSpecifier(line->elements[1].item);
# Line 4136  int main(int argc, const char ** argv) { Line 4254  int main(int argc, const char ** argv) {
4254      } else if (displayDefaultIndex) {      } else if (displayDefaultIndex) {
4255          if (config->defaultImage == -1) return 0;          if (config->defaultImage == -1) return 0;
4256          printf("%i\n", config->defaultImage);          printf("%i\n", config->defaultImage);
4257            return 0;
4258    
4259      } else if (kernelInfo)      } else if (kernelInfo)
4260   return displayInfo(config, kernelInfo, bootPrefix);   return displayInfo(config, kernelInfo, bootPrefix);

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