Magellan Linux

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

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

revision 1715 by niro, Sat Feb 18 00:35:46 2012 UTC revision 1745 by niro, Sat Feb 18 01:05:52 2012 UTC
# Line 46  Line 46 
46  #define dbgPrintf(format, args...)  #define dbgPrintf(format, args...)
47  #endif  #endif
48    
49    int debug = 0; /* Currently just for template debugging */
50    
51  #define _(A) (A)  #define _(A) (A)
52    
53  #define MAX_EXTRA_INITRDS  16 /* code segment checked by --bootloader-probe */  #define MAX_EXTRA_INITRDS  16 /* code segment checked by --bootloader-probe */
54  #define CODE_SEG_SIZE  128 /* code segment checked by --bootloader-probe */  #define CODE_SEG_SIZE  128 /* code segment checked by --bootloader-probe */
55    
56    #define NOOP_OPCODE 0x90
57    #define JMP_SHORT_OPCODE 0xeb
58    
59  /* comments get lumped in with indention */  /* comments get lumped in with indention */
60  struct lineElement {  struct lineElement {
61      char * item;      char * item;
# Line 871  static struct grubConfig * readConfig(co Line 876  static struct grubConfig * readConfig(co
876      cfg->secondaryIndent = strdup(line->indent);      cfg->secondaryIndent = strdup(line->indent);
877   }   }
878    
879   if (isEntryStart(line, cfi)) {   if (isEntryStart(line, cfi) || (cfg->entries && !sawEntry)) {
880      sawEntry = 1;      sawEntry = 1;
881      if (!entry) {      if (!entry) {
882   cfg->entries = malloc(sizeof(*entry));   cfg->entries = malloc(sizeof(*entry));
# Line 1335  static char *findDiskForRoot() Line 1340  static char *findDiskForRoot()
1340      return NULL;      return NULL;
1341  }  }
1342    
1343    void printEntry(struct singleEntry * entry) {
1344        int i;
1345        struct singleLine * line;
1346    
1347        for (line = entry->lines; line; line = line->next) {
1348     fprintf(stderr, "DBG: %s", line->indent);
1349     for (i = 0; i < line->numElements; i++) {
1350     fprintf(stderr, "%s%s",
1351        line->elements[i].item, line->elements[i].indent);
1352     }
1353     fprintf(stderr, "\n");
1354        }
1355    }
1356    
1357    void notSuitablePrintf(struct singleEntry * entry, const char *fmt, ...)
1358    {
1359        va_list argp;
1360    
1361        if (!debug)
1362     return;
1363    
1364        va_start(argp, fmt);
1365        fprintf(stderr, "DBG: Image entry failed: ");
1366        vfprintf(stderr, fmt, argp);
1367        printEntry(entry);
1368        va_end(argp);
1369    }
1370    
1371    #define beginswith(s, c) ((s) && (s)[0] == (c))
1372    
1373    static int endswith(const char *s, char c)
1374    {
1375     int slen;
1376    
1377     if (!s && !s[0])
1378     return 0;
1379     slen = strlen(s) - 1;
1380    
1381     return s[slen] == c;
1382    }
1383    
1384  int suitableImage(struct singleEntry * entry, const char * bootPrefix,  int suitableImage(struct singleEntry * entry, const char * bootPrefix,
1385    int skipRemoved, int flags) {    int skipRemoved, int flags) {
1386      struct singleLine * line;      struct singleLine * line;
# Line 1344  int suitableImage(struct singleEntry * e Line 1390  int suitableImage(struct singleEntry * e
1390      char * rootspec;      char * rootspec;
1391      char * rootdev;      char * rootdev;
1392    
1393      if (skipRemoved && entry->skip) return 0;      if (skipRemoved && entry->skip) {
1394     notSuitablePrintf(entry, "marked to skip\n");
1395     return 0;
1396        }
1397    
1398      line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines);      line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines);
1399      if (!line || line->numElements < 2) return 0;      if (!line) {
1400     notSuitablePrintf(entry, "no line found\n");
1401     return 0;
1402        }
1403        if (line->numElements < 2) {
1404     notSuitablePrintf(entry, "line has only %d elements\n",
1405        line->numElements);
1406     return 0;
1407        }
1408    
1409      if (flags & GRUBBY_BADIMAGE_OKAY) return 1;      if (flags & GRUBBY_BADIMAGE_OKAY) return 1;
1410    
1411      fullName = alloca(strlen(bootPrefix) +      fullName = alloca(strlen(bootPrefix) +
1412        strlen(line->elements[1].item) + 1);        strlen(line->elements[1].item) + 1);
1413      rootspec = getRootSpecifier(line->elements[1].item);      rootspec = getRootSpecifier(line->elements[1].item);
1414      sprintf(fullName, "%s%s", bootPrefix,      int rootspec_offset = rootspec ? strlen(rootspec) : 0;
1415              line->elements[1].item + (rootspec ? strlen(rootspec) : 0));      int hasslash = endswith(bootPrefix, '/') ||
1416      if (access(fullName, R_OK)) return 0;       beginswith(line->elements[1].item + rootspec_offset, '/');
1417        sprintf(fullName, "%s%s%s", bootPrefix, hasslash ? "" : "/",
1418                line->elements[1].item + rootspec_offset);
1419        if (access(fullName, R_OK)) {
1420     notSuitablePrintf(entry, "access to %s failed\n", fullName);
1421     return 0;
1422        }
1423      for (i = 2; i < line->numElements; i++)      for (i = 2; i < line->numElements; i++)
1424   if (!strncasecmp(line->elements[i].item, "root=", 5)) break;   if (!strncasecmp(line->elements[i].item, "root=", 5)) break;
1425      if (i < line->numElements) {      if (i < line->numElements) {
# Line 1375  int suitableImage(struct singleEntry * e Line 1437  int suitableImage(struct singleEntry * e
1437      line = getLineByType(LT_KERNELARGS|LT_MBMODULE, entry->lines);      line = getLineByType(LT_KERNELARGS|LT_MBMODULE, entry->lines);
1438    
1439              /* failed to find one */              /* failed to find one */
1440              if (!line) return 0;              if (!line) {
1441     notSuitablePrintf(entry, "no line found\n");
1442     return 0;
1443                }
1444    
1445      for (i = 1; i < line->numElements; i++)      for (i = 1; i < line->numElements; i++)
1446          if (!strncasecmp(line->elements[i].item, "root=", 5)) break;          if (!strncasecmp(line->elements[i].item, "root=", 5)) break;
1447      if (i < line->numElements)      if (i < line->numElements)
1448          dev = line->elements[i].item + 5;          dev = line->elements[i].item + 5;
1449      else {      else {
1450     notSuitablePrintf(entry, "no root= entry found\n");
1451   /* it failed too...  can't find root= */   /* it failed too...  can't find root= */
1452          return 0;          return 0;
1453              }              }
# Line 1389  int suitableImage(struct singleEntry * e Line 1455  int suitableImage(struct singleEntry * e
1455      }      }
1456    
1457      dev = getpathbyspec(dev);      dev = getpathbyspec(dev);
1458      if (!dev)      if (!getpathbyspec(dev)) {
1459            notSuitablePrintf(entry, "can't find blkid entry for %s\n", dev);
1460          return 0;          return 0;
1461        } else
1462     dev = getpathbyspec(dev);
1463    
1464      rootdev = findDiskForRoot();      rootdev = findDiskForRoot();
1465      if (!rootdev)      if (!rootdev) {
1466            notSuitablePrintf(entry, "can't find root device\n");
1467   return 0;   return 0;
1468        }
1469    
1470      if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) {      if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) {
1471            notSuitablePrintf(entry, "uuid missing: rootdev %s, dev %s\n",
1472     getuuidbydev(rootdev), getuuidbydev(dev));
1473          free(rootdev);          free(rootdev);
1474          return 0;          return 0;
1475      }      }
1476    
1477      if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) {      if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) {
1478            notSuitablePrintf(entry, "uuid mismatch: rootdev %s, dev %s\n",
1479     getuuidbydev(rootdev), getuuidbydev(dev));
1480   free(rootdev);   free(rootdev);
1481          return 0;          return 0;
1482      }      }
# Line 2468  int checkDeviceBootloader(const char * d Line 2543  int checkDeviceBootloader(const char * d
2543      if (memcmp(boot, bootSect, 3))      if (memcmp(boot, bootSect, 3))
2544   return 0;   return 0;
2545    
2546      if (boot[1] == 0xeb) {      if (boot[1] == JMP_SHORT_OPCODE) {
2547   offset = boot[2] + 2;   offset = boot[2] + 2;
2548      } else if (boot[1] == 0xe8 || boot[1] == 0xe9) {      } else if (boot[1] == 0xe8 || boot[1] == 0xe9) {
2549   offset = (boot[3] << 8) + boot[2] + 2;   offset = (boot[3] << 8) + boot[2] + 2;
2550      } else if (boot[0] == 0xeb) {      } else if (boot[0] == JMP_SHORT_OPCODE) {
2551   offset = boot[1] + 2;        offset = boot[1] + 2;
2552            /*
2553     * it looks like grub, when copying stage1 into the mbr, patches stage1
2554     * right after the JMP location, replacing other instructions such as
2555     * JMPs for NOOPs. So, relax the check a little bit by skipping those
2556     * different bytes.
2557     */
2558          if ((bootSect[offset + 1] == NOOP_OPCODE)
2559      && (bootSect[offset + 2] == NOOP_OPCODE)) {
2560     offset = offset + 3;
2561          }
2562      } else if (boot[0] == 0xe8 || boot[0] == 0xe9) {      } else if (boot[0] == 0xe8 || boot[0] == 0xe9) {
2563   offset = (boot[2] << 8) + boot[1] + 2;   offset = (boot[2] << 8) + boot[1] + 2;
2564      } else {      } else {
# Line 2948  int addNewKernel(struct grubConfig * con Line 3033  int addNewKernel(struct grubConfig * con
3033   }   }
3034      } else if (tmplLine->type == LT_ECHO) {      } else if (tmplLine->type == LT_ECHO) {
3035      requote(tmplLine, config->cfi);      requote(tmplLine, config->cfi);
3036        static const char *prefix = "'Loading ";
3037      if (tmplLine->numElements > 1 &&      if (tmplLine->numElements > 1 &&
3038      strstr(tmplLine->elements[1].item, "'Loading Linux ")) {      strstr(tmplLine->elements[1].item, prefix) &&
3039   char *prefix = "'Loading ";      masterLine->next && masterLine->next->type == LT_KERNEL) {
3040   char *newTitle = malloc(strlen(prefix) +   char *newTitle = malloc(strlen(prefix) +
3041   strlen(newKernelTitle) + 2);   strlen(newKernelTitle) + 2);
3042    
# Line 3147  int main(int argc, const char ** argv) { Line 3233  int main(int argc, const char ** argv) {
3233      struct singleEntry * template = NULL;      struct singleEntry * template = NULL;
3234      int copyDefault = 0, makeDefault = 0;      int copyDefault = 0, makeDefault = 0;
3235      int displayDefault = 0;      int displayDefault = 0;
3236        int displayDefaultIndex = 0;
3237        int displayDefaultTitle = 0;
3238      struct poptOption options[] = {      struct poptOption options[] = {
3239   { "add-kernel", 0, POPT_ARG_STRING, &newKernelPath, 0,   { "add-kernel", 0, POPT_ARG_STRING, &newKernelPath, 0,
3240      _("add an entry for the specified kernel"), _("kernel-path") },      _("add an entry for the specified kernel"), _("kernel-path") },
# Line 3177  int main(int argc, const char ** argv) { Line 3265  int main(int argc, const char ** argv) {
3265        "the kernel referenced by the default image does not exist, "        "the kernel referenced by the default image does not exist, "
3266        "the first linux entry whose kernel does exist is used as the "        "the first linux entry whose kernel does exist is used as the "
3267        "template"), NULL },        "template"), NULL },
3268     { "debug", 0, 0, &debug, 0,
3269        _("print debugging information for failures") },
3270   { "default-kernel", 0, 0, &displayDefault, 0,   { "default-kernel", 0, 0, &displayDefault, 0,
3271      _("display the path of the default kernel") },      _("display the path of the default kernel") },
3272     { "default-index", 0, 0, &displayDefaultIndex, 0,
3273        _("display the index of the default kernel") },
3274     { "default-title", 0, 0, &displayDefaultTitle, 0,
3275        _("display the title of the default kernel") },
3276   { "elilo", 0, POPT_ARG_NONE, &configureELilo, 0,   { "elilo", 0, POPT_ARG_NONE, &configureELilo, 0,
3277      _("configure elilo bootloader") },      _("configure elilo bootloader") },
3278   { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0,   { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0,
# Line 3322  int main(int argc, const char ** argv) { Line 3416  int main(int argc, const char ** argv) {
3416    
3417      if (bootloaderProbe && (displayDefault || kernelInfo || newKernelVersion ||      if (bootloaderProbe && (displayDefault || kernelInfo || newKernelVersion ||
3418    newKernelPath || removeKernelPath || makeDefault ||    newKernelPath || removeKernelPath || makeDefault ||
3419    defaultKernel)) {    defaultKernel || displayDefaultIndex || displayDefaultTitle)) {
3420   fprintf(stderr, _("grubby: --bootloader-probe may not be used with "   fprintf(stderr, _("grubby: --bootloader-probe may not be used with "
3421    "specified option"));    "specified option"));
3422   return 1;   return 1;
# Line 3365  int main(int argc, const char ** argv) { Line 3459  int main(int argc, const char ** argv) {
3459   defaultKernel = NULL;   defaultKernel = NULL;
3460      }      }
3461    
3462      if (!strcmp(grubConfig, "-") && !outputFile) {      if (grubConfig && !strcmp(grubConfig, "-") && !outputFile) {
3463   fprintf(stderr, _("grubby: output file must be specified if stdin "   fprintf(stderr, _("grubby: output file must be specified if stdin "
3464   "is used\n"));   "is used\n"));
3465   return 1;   return 1;
# Line 3373  int main(int argc, const char ** argv) { Line 3467  int main(int argc, const char ** argv) {
3467    
3468      if (!removeKernelPath && !newKernelPath && !displayDefault && !defaultKernel      if (!removeKernelPath && !newKernelPath && !displayDefault && !defaultKernel
3469   && !kernelInfo && !bootloaderProbe && !updateKernelPath   && !kernelInfo && !bootloaderProbe && !updateKernelPath
3470          && !removeMBKernel) {          && !removeMBKernel && !displayDefaultIndex && !displayDefaultTitle) {
3471   fprintf(stderr, _("grubby: no action specified\n"));   fprintf(stderr, _("grubby: no action specified\n"));
3472   return 1;   return 1;
3473      }      }
# Line 3468  int main(int argc, const char ** argv) { Line 3562  int main(int argc, const char ** argv) {
3562                 ((rootspec != NULL) ? strlen(rootspec) : 0));                 ((rootspec != NULL) ? strlen(rootspec) : 0));
3563    
3564   return 0;   return 0;
3565    
3566        } else if (displayDefaultTitle) {
3567     struct singleLine * line;
3568     struct singleEntry * entry;
3569    
3570     if (config->defaultImage == -1) return 0;
3571     entry = findEntryByIndex(config, config->defaultImage);
3572     if (!entry) return 0;
3573    
3574     if (!configureGrub2) {
3575      line = getLineByType(LT_TITLE, entry->lines);
3576      if (!line) return 0;
3577      printf("%s\n", line->elements[1].item);
3578    
3579     } else {
3580      int i;
3581      size_t len;
3582      char * start;
3583      char * tmp;
3584    
3585      dbgPrintf("This is GRUB2, default title is embeded in menuentry\n");
3586      line = getLineByType(LT_MENUENTRY, entry->lines);
3587      if (!line) return 0;
3588    
3589      for (i = 0; i < line->numElements; i++) {
3590    
3591        if (!strcmp(line->elements[i].item, "menuentry"))
3592          continue;
3593    
3594        if (*line->elements[i].item == '\'')
3595          start = line->elements[i].item + 1;
3596        else
3597          start = line->elements[i].item;
3598    
3599        len = strlen(start);
3600        if (*(start + len - 1) == '\'') {
3601          tmp = strdup(start);
3602          *(tmp + len - 1) = '\0';
3603          printf("%s", tmp);
3604          free(tmp);
3605          break;
3606        } else {
3607          printf("%s ", start);
3608        }
3609      }
3610      printf("\n");
3611     }
3612     return 0;
3613    
3614        } else if (displayDefaultIndex) {
3615            if (config->defaultImage == -1) return 0;
3616            printf("%i\n", config->defaultImage);
3617    
3618      } else if (kernelInfo)      } else if (kernelInfo)
3619   return displayInfo(config, kernelInfo, bootPrefix);   return displayInfo(config, kernelInfo, bootPrefix);
3620    

Legend:
Removed from v.1715  
changed lines
  Added in v.1745