Magellan Linux

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

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

revision 1717 by niro, Sat Feb 18 00:47:17 2012 UTC revision 1736 by niro, Sat Feb 18 01:02:17 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  int suitableImage(struct singleEntry * entry, const char * bootPrefix,  int suitableImage(struct singleEntry * entry, const char * bootPrefix,
1372    int skipRemoved, int flags) {    int skipRemoved, int flags) {
1373      struct singleLine * line;      struct singleLine * line;
# Line 1344  int suitableImage(struct singleEntry * e Line 1377  int suitableImage(struct singleEntry * e
1377      char * rootspec;      char * rootspec;
1378      char * rootdev;      char * rootdev;
1379    
1380      if (skipRemoved && entry->skip) return 0;      if (skipRemoved && entry->skip) {
1381     notSuitablePrintf(entry, "marked to skip\n");
1382     return 0;
1383        }
1384    
1385      line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines);      line = getLineByType(LT_KERNEL|LT_HYPER, entry->lines);
1386      if (!line || line->numElements < 2) return 0;      if (!line) {
1387     notSuitablePrintf(entry, "no line found\n");
1388     return 0;
1389        }
1390        if (line->numElements < 2) {
1391     notSuitablePrintf(entry, "line has only %d elements\n",
1392        line->numElements);
1393     return 0;
1394        }
1395    
1396      if (flags & GRUBBY_BADIMAGE_OKAY) return 1;      if (flags & GRUBBY_BADIMAGE_OKAY) return 1;
1397    
# Line 1356  int suitableImage(struct singleEntry * e Line 1400  int suitableImage(struct singleEntry * e
1400      rootspec = getRootSpecifier(line->elements[1].item);      rootspec = getRootSpecifier(line->elements[1].item);
1401      sprintf(fullName, "%s%s", bootPrefix,      sprintf(fullName, "%s%s", bootPrefix,
1402              line->elements[1].item + (rootspec ? strlen(rootspec) : 0));              line->elements[1].item + (rootspec ? strlen(rootspec) : 0));
1403      if (access(fullName, R_OK)) return 0;      if (access(fullName, R_OK)) {
1404     notSuitablePrintf(entry, "access to %s failed\n", fullName);
1405     return 0;
1406        }
1407      for (i = 2; i < line->numElements; i++)      for (i = 2; i < line->numElements; i++)
1408   if (!strncasecmp(line->elements[i].item, "root=", 5)) break;   if (!strncasecmp(line->elements[i].item, "root=", 5)) break;
1409      if (i < line->numElements) {      if (i < line->numElements) {
# Line 1375  int suitableImage(struct singleEntry * e Line 1421  int suitableImage(struct singleEntry * e
1421      line = getLineByType(LT_KERNELARGS|LT_MBMODULE, entry->lines);      line = getLineByType(LT_KERNELARGS|LT_MBMODULE, entry->lines);
1422    
1423              /* failed to find one */              /* failed to find one */
1424              if (!line) return 0;              if (!line) {
1425     notSuitablePrintf(entry, "no line found\n");
1426     return 0;
1427                }
1428    
1429      for (i = 1; i < line->numElements; i++)      for (i = 1; i < line->numElements; i++)
1430          if (!strncasecmp(line->elements[i].item, "root=", 5)) break;          if (!strncasecmp(line->elements[i].item, "root=", 5)) break;
1431      if (i < line->numElements)      if (i < line->numElements)
1432          dev = line->elements[i].item + 5;          dev = line->elements[i].item + 5;
1433      else {      else {
1434     notSuitablePrintf(entry, "no root= entry found\n");
1435   /* it failed too...  can't find root= */   /* it failed too...  can't find root= */
1436          return 0;          return 0;
1437              }              }
# Line 1389  int suitableImage(struct singleEntry * e Line 1439  int suitableImage(struct singleEntry * e
1439      }      }
1440    
1441      dev = getpathbyspec(dev);      dev = getpathbyspec(dev);
1442      if (!dev)      if (!getpathbyspec(dev)) {
1443            notSuitablePrintf(entry, "can't find blkid entry for %s\n", dev);
1444          return 0;          return 0;
1445        } else
1446     dev = getpathbyspec(dev);
1447    
1448      rootdev = findDiskForRoot();      rootdev = findDiskForRoot();
1449      if (!rootdev)      if (!rootdev) {
1450            notSuitablePrintf(entry, "can't find root device\n");
1451   return 0;   return 0;
1452        }
1453    
1454      if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) {      if (!getuuidbydev(rootdev) || !getuuidbydev(dev)) {
1455            notSuitablePrintf(entry, "uuid missing: rootdev %s, dev %s\n",
1456     getuuidbydev(rootdev), getuuidbydev(dev));
1457          free(rootdev);          free(rootdev);
1458          return 0;          return 0;
1459      }      }
1460    
1461      if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) {      if (strcmp(getuuidbydev(rootdev), getuuidbydev(dev))) {
1462            notSuitablePrintf(entry, "uuid mismatch: rootdev %s, dev %s\n",
1463     getuuidbydev(rootdev), getuuidbydev(dev));
1464   free(rootdev);   free(rootdev);
1465          return 0;          return 0;
1466      }      }
# Line 2468  int checkDeviceBootloader(const char * d Line 2527  int checkDeviceBootloader(const char * d
2527      if (memcmp(boot, bootSect, 3))      if (memcmp(boot, bootSect, 3))
2528   return 0;   return 0;
2529    
2530      if (boot[1] == 0xeb) {      if (boot[1] == JMP_SHORT_OPCODE) {
2531   offset = boot[2] + 2;   offset = boot[2] + 2;
2532      } else if (boot[1] == 0xe8 || boot[1] == 0xe9) {      } else if (boot[1] == 0xe8 || boot[1] == 0xe9) {
2533   offset = (boot[3] << 8) + boot[2] + 2;   offset = (boot[3] << 8) + boot[2] + 2;
2534      } else if (boot[0] == 0xeb) {      } else if (boot[0] == JMP_SHORT_OPCODE) {
2535   offset = boot[1] + 2;        offset = boot[1] + 2;
2536            /*
2537     * it looks like grub, when copying stage1 into the mbr, patches stage1
2538     * right after the JMP location, replacing other instructions such as
2539     * JMPs for NOOPs. So, relax the check a little bit by skipping those
2540     * different bytes.
2541     */
2542          if ((bootSect[offset + 1] == NOOP_OPCODE)
2543      && (bootSect[offset + 2] == NOOP_OPCODE)) {
2544     offset = offset + 3;
2545          }
2546      } else if (boot[0] == 0xe8 || boot[0] == 0xe9) {      } else if (boot[0] == 0xe8 || boot[0] == 0xe9) {
2547   offset = (boot[2] << 8) + boot[1] + 2;   offset = (boot[2] << 8) + boot[1] + 2;
2548      } else {      } else {
# Line 2948  int addNewKernel(struct grubConfig * con Line 3017  int addNewKernel(struct grubConfig * con
3017   }   }
3018      } else if (tmplLine->type == LT_ECHO) {      } else if (tmplLine->type == LT_ECHO) {
3019      requote(tmplLine, config->cfi);      requote(tmplLine, config->cfi);
3020        static const char *prefix = "'Loading ";
3021      if (tmplLine->numElements > 1 &&      if (tmplLine->numElements > 1 &&
3022      strstr(tmplLine->elements[1].item, "'Loading Linux ")) {      strstr(tmplLine->elements[1].item, prefix) &&
3023   char *prefix = "'Loading ";      masterLine->next && masterLine->next->type == LT_KERNEL) {
3024   char *newTitle = malloc(strlen(prefix) +   char *newTitle = malloc(strlen(prefix) +
3025   strlen(newKernelTitle) + 2);   strlen(newKernelTitle) + 2);
3026    
# Line 3147  int main(int argc, const char ** argv) { Line 3217  int main(int argc, const char ** argv) {
3217      struct singleEntry * template = NULL;      struct singleEntry * template = NULL;
3218      int copyDefault = 0, makeDefault = 0;      int copyDefault = 0, makeDefault = 0;
3219      int displayDefault = 0;      int displayDefault = 0;
3220        int displayDefaultIndex = 0;
3221        int displayDefaultTitle = 0;
3222      struct poptOption options[] = {      struct poptOption options[] = {
3223   { "add-kernel", 0, POPT_ARG_STRING, &newKernelPath, 0,   { "add-kernel", 0, POPT_ARG_STRING, &newKernelPath, 0,
3224      _("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 3249  int main(int argc, const char ** argv) {
3249        "the kernel referenced by the default image does not exist, "        "the kernel referenced by the default image does not exist, "
3250        "the first linux entry whose kernel does exist is used as the "        "the first linux entry whose kernel does exist is used as the "
3251        "template"), NULL },        "template"), NULL },
3252     { "debug", 0, 0, &debug, 0,
3253        _("print debugging information for failures") },
3254   { "default-kernel", 0, 0, &displayDefault, 0,   { "default-kernel", 0, 0, &displayDefault, 0,
3255      _("display the path of the default kernel") },      _("display the path of the default kernel") },
3256     { "default-index", 0, 0, &displayDefaultIndex, 0,
3257        _("display the index of the default kernel") },
3258     { "default-title", 0, 0, &displayDefaultTitle, 0,
3259        _("display the title of the default kernel") },
3260   { "elilo", 0, POPT_ARG_NONE, &configureELilo, 0,   { "elilo", 0, POPT_ARG_NONE, &configureELilo, 0,
3261      _("configure elilo bootloader") },      _("configure elilo bootloader") },
3262   { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0,   { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0,
# Line 3322  int main(int argc, const char ** argv) { Line 3400  int main(int argc, const char ** argv) {
3400    
3401      if (bootloaderProbe && (displayDefault || kernelInfo || newKernelVersion ||      if (bootloaderProbe && (displayDefault || kernelInfo || newKernelVersion ||
3402    newKernelPath || removeKernelPath || makeDefault ||    newKernelPath || removeKernelPath || makeDefault ||
3403    defaultKernel)) {    defaultKernel || displayDefaultIndex || displayDefaultTitle)) {
3404   fprintf(stderr, _("grubby: --bootloader-probe may not be used with "   fprintf(stderr, _("grubby: --bootloader-probe may not be used with "
3405    "specified option"));    "specified option"));
3406   return 1;   return 1;
# Line 3373  int main(int argc, const char ** argv) { Line 3451  int main(int argc, const char ** argv) {
3451    
3452      if (!removeKernelPath && !newKernelPath && !displayDefault && !defaultKernel      if (!removeKernelPath && !newKernelPath && !displayDefault && !defaultKernel
3453   && !kernelInfo && !bootloaderProbe && !updateKernelPath   && !kernelInfo && !bootloaderProbe && !updateKernelPath
3454          && !removeMBKernel) {          && !removeMBKernel && !displayDefaultIndex && !displayDefaultTitle) {
3455   fprintf(stderr, _("grubby: no action specified\n"));   fprintf(stderr, _("grubby: no action specified\n"));
3456   return 1;   return 1;
3457      }      }
# Line 3468  int main(int argc, const char ** argv) { Line 3546  int main(int argc, const char ** argv) {
3546                 ((rootspec != NULL) ? strlen(rootspec) : 0));                 ((rootspec != NULL) ? strlen(rootspec) : 0));
3547    
3548   return 0;   return 0;
3549    
3550        } else if (displayDefaultTitle) {
3551     struct singleLine * line;
3552     struct singleEntry * entry;
3553    
3554     if (config->defaultImage == -1) return 0;
3555     entry = findEntryByIndex(config, config->defaultImage);
3556     if (!entry) return 0;
3557    
3558     if (!configureGrub2) {
3559      line = getLineByType(LT_TITLE, entry->lines);
3560      if (!line) return 0;
3561      printf("%s\n", line->elements[1].item);
3562    
3563     } else {
3564      int i;
3565      size_t len;
3566      char * start;
3567      char * tmp;
3568    
3569      dbgPrintf("This is GRUB2, default title is embeded in menuentry\n");
3570      line = getLineByType(LT_MENUENTRY, entry->lines);
3571      if (!line) return 0;
3572    
3573      for (i = 0; i < line->numElements; i++) {
3574    
3575        if (!strcmp(line->elements[i].item, "menuentry"))
3576          continue;
3577    
3578        if (*line->elements[i].item == '\'')
3579          start = line->elements[i].item + 1;
3580        else
3581          start = line->elements[i].item;
3582    
3583        len = strlen(start);
3584        if (*(start + len - 1) == '\'') {
3585          tmp = strdup(start);
3586          *(tmp + len - 1) = '\0';
3587          printf("%s", tmp);
3588          free(tmp);
3589          break;
3590        } else {
3591          printf("%s ", start);
3592        }
3593      }
3594      printf("\n");
3595     }
3596     return 0;
3597    
3598        } else if (displayDefaultIndex) {
3599            if (config->defaultImage == -1) return 0;
3600            printf("%i\n", config->defaultImage);
3601    
3602      } else if (kernelInfo)      } else if (kernelInfo)
3603   return displayInfo(config, kernelInfo, bootPrefix);   return displayInfo(config, kernelInfo, bootPrefix);
3604    

Legend:
Removed from v.1717  
changed lines
  Added in v.1736