--- trunk/grubby/grubby.c 2012/02/18 00:47:17 1717 +++ trunk/grubby/grubby.c 2012/02/18 00:53:14 1722 @@ -51,6 +51,9 @@ #define MAX_EXTRA_INITRDS 16 /* code segment checked by --bootloader-probe */ #define CODE_SEG_SIZE 128 /* code segment checked by --bootloader-probe */ +#define NOOP_OPCODE 0x90 +#define JMP_SHORT_OPCODE 0xeb + /* comments get lumped in with indention */ struct lineElement { char * item; @@ -2468,12 +2471,22 @@ if (memcmp(boot, bootSect, 3)) return 0; - if (boot[1] == 0xeb) { + if (boot[1] == JMP_SHORT_OPCODE) { offset = boot[2] + 2; } else if (boot[1] == 0xe8 || boot[1] == 0xe9) { offset = (boot[3] << 8) + boot[2] + 2; - } else if (boot[0] == 0xeb) { - offset = boot[1] + 2; + } else if (boot[0] == JMP_SHORT_OPCODE) { + offset = boot[1] + 2; + /* + * it looks like grub, when copying stage1 into the mbr, patches stage1 + * right after the JMP location, replacing other instructions such as + * JMPs for NOOPs. So, relax the check a little bit by skipping those + * different bytes. + */ + if ((bootSect[offset + 1] == NOOP_OPCODE) + && (bootSect[offset + 2] == NOOP_OPCODE)) { + offset = offset + 3; + } } else if (boot[0] == 0xe8 || boot[0] == 0xe9) { offset = (boot[2] << 8) + boot[1] + 2; } else { @@ -2948,9 +2961,10 @@ } } else if (tmplLine->type == LT_ECHO) { requote(tmplLine, config->cfi); + static const char *prefix = "'Loading "; if (tmplLine->numElements > 1 && - strstr(tmplLine->elements[1].item, "'Loading Linux ")) { - char *prefix = "'Loading "; + strstr(tmplLine->elements[1].item, prefix) && + masterLine->next && masterLine->next->type == LT_KERNEL) { char *newTitle = malloc(strlen(prefix) + strlen(newKernelTitle) + 2); @@ -3147,6 +3161,8 @@ struct singleEntry * template = NULL; int copyDefault = 0, makeDefault = 0; int displayDefault = 0; + int displayDefaultIndex = 0; + int displayDefaultTitle = 0; struct poptOption options[] = { { "add-kernel", 0, POPT_ARG_STRING, &newKernelPath, 0, _("add an entry for the specified kernel"), _("kernel-path") }, @@ -3179,6 +3195,10 @@ "template"), NULL }, { "default-kernel", 0, 0, &displayDefault, 0, _("display the path of the default kernel") }, + { "default-index", 0, 0, &displayDefaultIndex, 0, + _("display the index of the default kernel") }, + { "default-title", 0, 0, &displayDefaultTitle, 0, + _("display the title of the default kernel") }, { "elilo", 0, POPT_ARG_NONE, &configureELilo, 0, _("configure elilo bootloader") }, { "extlinux", 0, POPT_ARG_NONE, &configureExtLinux, 0, @@ -3322,7 +3342,7 @@ if (bootloaderProbe && (displayDefault || kernelInfo || newKernelVersion || newKernelPath || removeKernelPath || makeDefault || - defaultKernel)) { + defaultKernel || displayDefaultIndex || displayDefaultTitle)) { fprintf(stderr, _("grubby: --bootloader-probe may not be used with " "specified option")); return 1; @@ -3373,7 +3393,7 @@ if (!removeKernelPath && !newKernelPath && !displayDefault && !defaultKernel && !kernelInfo && !bootloaderProbe && !updateKernelPath - && !removeMBKernel) { + && !removeMBKernel && !displayDefaultIndex && !displayDefaultTitle) { fprintf(stderr, _("grubby: no action specified\n")); return 1; } @@ -3468,6 +3488,59 @@ ((rootspec != NULL) ? strlen(rootspec) : 0)); return 0; + + } else if (displayDefaultTitle) { + struct singleLine * line; + struct singleEntry * entry; + + if (config->defaultImage == -1) return 0; + entry = findEntryByIndex(config, config->defaultImage); + if (!entry) return 0; + + if (!configureGrub2) { + line = getLineByType(LT_TITLE, entry->lines); + if (!line) return 0; + printf("%s\n", line->elements[1].item); + + } else { + int i; + size_t len; + char * start; + char * tmp; + + dbgPrintf("This is GRUB2, default title is embeded in menuentry\n"); + line = getLineByType(LT_MENUENTRY, entry->lines); + if (!line) return 0; + + for (i = 0; i < line->numElements; i++) { + + if (!strcmp(line->elements[i].item, "menuentry")) + continue; + + if (*line->elements[i].item == '\'') + start = line->elements[i].item + 1; + else + start = line->elements[i].item; + + len = strlen(start); + if (*(start + len - 1) == '\'') { + tmp = strdup(start); + *(tmp + len - 1) = '\0'; + printf("%s", tmp); + free(tmp); + break; + } else { + printf("%s ", start); + } + } + printf("\n"); + } + return 0; + + } else if (displayDefaultIndex) { + if (config->defaultImage == -1) return 0; + printf("%i\n", config->defaultImage); + } else if (kernelInfo) return displayInfo(config, kernelInfo, bootPrefix);